blob: cc6e8b585b832be24166d11f6b72180eb938c1f1 [file] [log] [blame]
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07003 *
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 */
16package org.onosproject.ovsdb.controller.driver;
17
andreaed976a42015-10-05 14:38:25 -070018import com.fasterxml.jackson.databind.JsonNode;
19import com.google.common.base.Function;
Pier Ventref5d72362016-07-17 12:02:14 +020020import com.google.common.collect.ImmutableList;
21import com.google.common.collect.ImmutableSet;
andreaed976a42015-10-05 14:38:25 -070022import com.google.common.collect.Lists;
23import com.google.common.collect.Maps;
24import com.google.common.collect.Sets;
25import com.google.common.util.concurrent.Futures;
26import com.google.common.util.concurrent.ListenableFuture;
27import com.google.common.util.concurrent.SettableFuture;
lishuai6c56f5e2015-11-17 16:38:19 +080028
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070029import io.netty.channel.Channel;
lishuai6c56f5e2015-11-17 16:38:19 +080030
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070031import org.onlab.packet.IpAddress;
andreaed976a42015-10-05 14:38:25 -070032import org.onosproject.net.DeviceId;
Frank Wange11a98d2016-10-26 17:04:03 +080033import org.onosproject.net.PortNumber;
Hyunsun Moon1251e192016-06-07 16:57:05 -070034import org.onosproject.net.behaviour.BridgeDescription;
andreaed976a42015-10-05 14:38:25 -070035import org.onosproject.net.behaviour.ControllerInfo;
Pier Ventref5d72362016-07-17 12:02:14 +020036import org.onosproject.net.behaviour.MirroringStatistics;
37import org.onosproject.net.behaviour.MirroringName;
Frank Wange11a98d2016-10-26 17:04:03 +080038import org.onosproject.net.behaviour.QosId;
39import org.onosproject.net.behaviour.QueueId;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070040import org.onosproject.ovsdb.controller.OvsdbBridge;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070041import org.onosproject.ovsdb.controller.OvsdbClientService;
Hyunsun Moondd14e8e2016-06-09 16:17:32 -070042import org.onosproject.ovsdb.controller.OvsdbInterface;
43import org.onosproject.ovsdb.controller.OvsdbInterface.Type;
Pier Ventref5d72362016-07-17 12:02:14 +020044import org.onosproject.ovsdb.controller.OvsdbMirror;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070045import org.onosproject.ovsdb.controller.OvsdbNodeId;
46import org.onosproject.ovsdb.controller.OvsdbPort;
47import org.onosproject.ovsdb.controller.OvsdbPortName;
48import org.onosproject.ovsdb.controller.OvsdbPortNumber;
Frank Wange11a98d2016-10-26 17:04:03 +080049import org.onosproject.ovsdb.controller.OvsdbQos;
50import org.onosproject.ovsdb.controller.OvsdbQueue;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070051import org.onosproject.ovsdb.controller.OvsdbRowStore;
52import org.onosproject.ovsdb.controller.OvsdbStore;
53import org.onosproject.ovsdb.controller.OvsdbTableStore;
Pier Ventref5d72362016-07-17 12:02:14 +020054
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070055import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
56import org.onosproject.ovsdb.rfc.message.OperationResult;
57import org.onosproject.ovsdb.rfc.message.TableUpdates;
Frank Wange11a98d2016-10-26 17:04:03 +080058import org.onosproject.ovsdb.rfc.notation.Column;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070059import org.onosproject.ovsdb.rfc.notation.Condition;
60import org.onosproject.ovsdb.rfc.notation.Mutation;
CNluciusa66c3972015-09-06 20:31:29 +080061import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070062import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
63import org.onosproject.ovsdb.rfc.notation.Row;
Jonathan Hart51539b82015-10-29 09:53:04 -070064import org.onosproject.ovsdb.rfc.notation.Uuid;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070065import org.onosproject.ovsdb.rfc.operations.Delete;
66import org.onosproject.ovsdb.rfc.operations.Insert;
67import org.onosproject.ovsdb.rfc.operations.Mutate;
68import org.onosproject.ovsdb.rfc.operations.Operation;
69import org.onosproject.ovsdb.rfc.operations.Update;
70import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
71import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
72import org.onosproject.ovsdb.rfc.schema.TableSchema;
73import org.onosproject.ovsdb.rfc.table.Bridge;
74import org.onosproject.ovsdb.rfc.table.Controller;
75import org.onosproject.ovsdb.rfc.table.Interface;
Pier Ventref5d72362016-07-17 12:02:14 +020076import org.onosproject.ovsdb.rfc.table.Mirror;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070077import org.onosproject.ovsdb.rfc.table.OvsdbTable;
78import org.onosproject.ovsdb.rfc.table.Port;
Frank Wange11a98d2016-10-26 17:04:03 +080079import org.onosproject.ovsdb.rfc.table.Qos;
80import org.onosproject.ovsdb.rfc.table.Queue;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070081import org.onosproject.ovsdb.rfc.table.TableGenerator;
82import org.onosproject.ovsdb.rfc.utils.ConditionUtil;
83import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
84import org.onosproject.ovsdb.rfc.utils.JsonRpcWriterUtil;
85import org.onosproject.ovsdb.rfc.utils.MutationUtil;
86import org.slf4j.Logger;
87import org.slf4j.LoggerFactory;
88
andreaed976a42015-10-05 14:38:25 -070089import java.net.InetSocketAddress;
90import java.util.ArrayList;
Pier Ventref5d72362016-07-17 12:02:14 +020091
Frank Wange11a98d2016-10-26 17:04:03 +080092import java.util.HashMap;
andreaed976a42015-10-05 14:38:25 -070093import java.util.HashSet;
94import java.util.Iterator;
95import java.util.List;
96import java.util.Map;
Pier Ventref5d72362016-07-17 12:02:14 +020097import java.util.Objects;
Hyunsun Moondd14e8e2016-06-09 16:17:32 -070098import java.util.Optional;
andreaed976a42015-10-05 14:38:25 -070099import java.util.Set;
100import java.util.concurrent.ConcurrentMap;
101import java.util.concurrent.ExecutionException;
jaegonkim01d7c912017-01-22 22:03:38 +0900102import java.util.concurrent.TimeUnit;
103import java.util.concurrent.TimeoutException;
andreaed976a42015-10-05 14:38:25 -0700104import java.util.concurrent.atomic.AtomicReference;
105import java.util.stream.Collectors;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700106
Hyunsun Moon1251e192016-06-07 16:57:05 -0700107import static org.onosproject.ovsdb.controller.OvsdbConstant.*;
108
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700109/**
110 * An representation of an ovsdb client.
111 */
Hyunsun Moon1251e192016-06-07 16:57:05 -0700112public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientService {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700113
jaegonkim01d7c912017-01-22 22:03:38 +0900114 private static final int TRANSACTCONFIG_TIMEOUT = 3; //sec
115
Hyunsun Moon1251e192016-06-07 16:57:05 -0700116 private final Logger log = LoggerFactory.getLogger(DefaultOvsdbClient.class);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700117
118 private Channel channel;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700119 private OvsdbAgent agent;
120 private boolean connected;
121 private OvsdbNodeId nodeId;
122 private Callback monitorCallBack;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700123 private OvsdbStore ovsdbStore = new OvsdbStore();
124
125 private final Map<String, String> requestMethod = Maps.newHashMap();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700126 private final Map<String, SettableFuture<? extends Object>> requestResult = Maps.newHashMap();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700127 private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700128
Pier Ventref5d72362016-07-17 12:02:14 +0200129
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700130 /**
131 * Creates an OvsdbClient.
132 *
133 * @param nodeId ovsdb node id
134 */
135 public DefaultOvsdbClient(OvsdbNodeId nodeId) {
136 this.nodeId = nodeId;
137 }
138
139 @Override
140 public OvsdbNodeId nodeId() {
141 return nodeId;
142 }
143
144 @Override
145 public void setAgent(OvsdbAgent agent) {
146 if (this.agent == null) {
147 this.agent = agent;
148 }
149 }
150
151 @Override
152 public void setChannel(Channel channel) {
153 this.channel = channel;
154 }
155
156 @Override
157 public void setConnection(boolean connected) {
158 this.connected = connected;
159 }
160
161 @Override
162 public boolean isConnected() {
163 return this.connected;
164 }
165
166 @Override
167 public void nodeAdded() {
168 this.agent.addConnectedNode(nodeId, this);
169 }
170
171 @Override
172 public void nodeRemoved() {
173 this.agent.removeConnectedNode(nodeId);
174 channel.disconnect();
175 }
176
177 /**
178 * Gets the ovsdb table store.
179 *
180 * @param dbName the ovsdb database name
181 * @return ovsTableStore, empty if table store is find
182 */
183 private OvsdbTableStore getTableStore(String dbName) {
184 if (ovsdbStore == null) {
185 return null;
186 }
187 return ovsdbStore.getOvsdbTableStore(dbName);
188 }
189
190 /**
191 * Gets the ovsdb row store.
192 *
andreaed976a42015-10-05 14:38:25 -0700193 * @param dbName the ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700194 * @param tableName the ovsdb table name
Hyunsun Moon6125c612015-10-15 10:54:44 -0700195 * @return ovsRowStore, empty store if no rows exist in the table
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700196 */
197 private OvsdbRowStore getRowStore(String dbName, String tableName) {
198 OvsdbTableStore tableStore = getTableStore(dbName);
199 if (tableStore == null) {
200 return null;
201 }
Hyunsun Moon6125c612015-10-15 10:54:44 -0700202
203 OvsdbRowStore rowStore = tableStore.getRows(tableName);
204 if (rowStore == null) {
205 rowStore = new OvsdbRowStore();
206 }
207 return rowStore;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700208 }
209
210 /**
211 * Gets the ovsdb row.
212 *
andreaed976a42015-10-05 14:38:25 -0700213 * @param dbName the ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700214 * @param tableName the ovsdb table name
andreaed976a42015-10-05 14:38:25 -0700215 * @param uuid the key of the row
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700216 * @return row, empty if row is find
217 */
218 @Override
219 public Row getRow(String dbName, String tableName, String uuid) {
220 OvsdbTableStore tableStore = getTableStore(dbName);
221 if (tableStore == null) {
222 return null;
223 }
224 OvsdbRowStore rowStore = tableStore.getRows(tableName);
225 if (rowStore == null) {
226 return null;
227 }
228 return rowStore.getRow(uuid);
229 }
230
231 @Override
232 public void removeRow(String dbName, String tableName, String uuid) {
233 OvsdbTableStore tableStore = getTableStore(dbName);
234 if (tableStore == null) {
235 return;
236 }
237 OvsdbRowStore rowStore = tableStore.getRows(tableName);
238 if (rowStore == null) {
239 return;
240 }
241 rowStore.deleteRow(uuid);
242 }
243
244 @Override
245 public void updateOvsdbStore(String dbName, String tableName, String uuid,
246 Row row) {
247 OvsdbTableStore tableStore = ovsdbStore.getOvsdbTableStore(dbName);
248 if (tableStore == null) {
249 tableStore = new OvsdbTableStore();
250 }
251 OvsdbRowStore rowStore = tableStore.getRows(tableName);
252 if (rowStore == null) {
253 rowStore = new OvsdbRowStore();
254 }
255 rowStore.insertRow(uuid, row);
256 tableStore.createOrUpdateTable(tableName, rowStore);
257 ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
258 }
259
Pier Ventref5d72362016-07-17 12:02:14 +0200260 /**
261 * Gets the Mirror uuid.
262 *
263 * @param mirrorName mirror name
264 * @return mirror uuid, empty if no uuid is found
265 */
266 @Override
267 public String getMirrorUuid(String mirrorName) {
268 DatabaseSchema dbSchema = schema.get(DATABASENAME);
269 OvsdbRowStore rowStore = getRowStore(DATABASENAME, MIRROR);
270 if (rowStore == null) {
271 log.warn("The mirror uuid is null");
272 return null;
273 }
274
275 ConcurrentMap<String, Row> mirrorTableRows = rowStore.getRowStore();
276 if (mirrorTableRows == null) {
277 log.warn("The mirror uuid is null");
278 return null;
279 }
280
281 for (String uuid : mirrorTableRows.keySet()) {
282 Mirror mirror = (Mirror) TableGenerator
283 .getTable(dbSchema, mirrorTableRows.get(uuid), OvsdbTable.MIRROR);
284 String name = mirror.getName();
285 if (name.contains(mirrorName)) {
286 return uuid;
287 }
288 }
289 log.warn("Mirroring not found");
290 return null;
291 }
292
293 /**
294 * Gets mirrors of the device.
295 *
296 * @param deviceId target device id
297 * @return set of mirroring; empty if no mirror is found
298 */
299 @Override
300 public Set<MirroringStatistics> getMirroringStatistics(DeviceId deviceId) {
301 Uuid bridgeUuid = getBridgeUuid(deviceId);
302 if (bridgeUuid == null) {
303 log.warn("Couldn't find bridge {} in {}", deviceId, nodeId.getIpAddress());
304 return null;
305 }
306
307 List<MirroringStatistics> mirrorings = getMirrorings(bridgeUuid);
308 if (mirrorings == null) {
309 log.warn("Couldn't find mirrors in {}", nodeId.getIpAddress());
310 return null;
311 }
312 return ImmutableSet.copyOf(mirrorings);
313 }
314
315 /**
316 * Helper method which retrieves mirrorings statistics using bridge uuid.
317 *
318 * @param bridgeUuid the uuid of the bridge
319 * @return the list of the mirrorings statistics.
320 */
321 private List<MirroringStatistics> getMirrorings(Uuid bridgeUuid) {
322 DatabaseSchema dbSchema = schema.get(DATABASENAME);
323 if (dbSchema == null) {
324 log.warn("Unable to retrieve dbSchema {}", DATABASENAME);
325 return null;
326 }
327 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
328 if (rowStore == null) {
329 log.warn("Unable to retrieve rowStore {} of {}", BRIDGE, DATABASENAME);
330 return null;
331 }
332
333 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
334 Bridge bridge = (Bridge) TableGenerator.
335 getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
336
337 Set<Uuid> mirroringsUuids = (Set<Uuid>) ((OvsdbSet) bridge
338 .getMirrorsColumn().data()).set();
339
340 OvsdbRowStore mirrorRowStore = getRowStore(DATABASENAME, MIRROR);
341 if (mirrorRowStore == null) {
342 log.warn("Unable to retrieve rowStore {} of {}", MIRROR, DATABASENAME);
343 return null;
344 }
345
346 List<MirroringStatistics> mirroringStatistics = new ArrayList<>();
347 ConcurrentMap<String, Row> mirrorTableRows = mirrorRowStore.getRowStore();
348 mirrorTableRows.forEach((key, row) -> {
349 if (!mirroringsUuids.contains(Uuid.uuid(key))) {
350 return;
351 }
352 Mirror mirror = (Mirror) TableGenerator
353 .getTable(dbSchema, row, OvsdbTable.MIRROR);
354 mirroringStatistics.add(MirroringStatistics.mirroringStatistics(mirror.getName(),
355 (Map<String, Integer>) ((OvsdbMap) mirror
356 .getStatisticsColumn().data()).map()));
357 });
358 return ImmutableList.copyOf(mirroringStatistics);
359 }
360
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700361 @Override
362 public String getPortUuid(String portName, String bridgeUuid) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700363 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700364
Hyunsun Moon1251e192016-06-07 16:57:05 -0700365 Row bridgeRow = getRow(DATABASENAME, BRIDGE, bridgeUuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700366 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
367 OvsdbTable.BRIDGE);
368 if (bridge != null) {
369 OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data();
370 @SuppressWarnings("unchecked")
Jonathan Hart51539b82015-10-29 09:53:04 -0700371 Set<Uuid> ports = setPorts.set();
Jon Hallcbd1b392017-01-18 20:15:44 -0800372 if (ports == null || ports.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700373 log.warn("The port uuid is null");
374 return null;
375 }
376
Jonathan Hart51539b82015-10-29 09:53:04 -0700377 for (Uuid uuid : ports) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700378 Row portRow = getRow(DATABASENAME, PORT, uuid.value());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700379 Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
380 OvsdbTable.PORT);
381 if (port != null && portName.equalsIgnoreCase(port.getName())) {
382 return uuid.value();
383 }
384 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700385 }
386 return null;
387 }
388
389 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700390 public String getBridgeUuid(String bridgeName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700391 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700392 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700393 if (rowStore == null) {
394 log.debug("The bridge uuid is null");
395 return null;
396 }
397
398 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
399 if (bridgeTableRows == null) {
400 log.debug("The bridge uuid is null");
401 return null;
402 }
403
404 for (String uuid : bridgeTableRows.keySet()) {
405 Bridge bridge = (Bridge) TableGenerator
Hyunsun Moon1251e192016-06-07 16:57:05 -0700406 .getTable(dbSchema, bridgeTableRows.get(uuid), OvsdbTable.BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700407 if (bridge.getName().equals(bridgeName)) {
408 return uuid;
409 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700410 }
411 return null;
412 }
413
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700414 private String getOvsUuid(String dbName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700415 OvsdbRowStore rowStore = getRowStore(DATABASENAME, DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700416 if (rowStore == null) {
417 log.debug("The bridge uuid is null");
418 return null;
419 }
420 ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
421 if (ovsTableRows != null) {
422 for (String uuid : ovsTableRows.keySet()) {
423 Row row = ovsTableRows.get(uuid);
424 String tableName = row.tableName();
425 if (tableName.equals(dbName)) {
426 return uuid;
427 }
428 }
429 }
430 return null;
431 }
432
433 @Override
434 public void createPort(String bridgeName, String portName) {
435 String bridgeUuid = getBridgeUuid(bridgeName);
436 if (bridgeUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700437 log.error("Can't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700438 return;
439 }
440
Hyunsun Moon1251e192016-06-07 16:57:05 -0700441 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700442 String portUuid = getPortUuid(portName, bridgeUuid);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700443 Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700444 port.setName(portName);
445 if (portUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700446 insertConfig(PORT, UUID, BRIDGE, PORTS, bridgeUuid, port.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700447 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700448 }
449
450 @Override
451 public void dropPort(String bridgeName, String portName) {
452 String bridgeUuid = getBridgeUuid(bridgeName);
453 if (bridgeUuid == null) {
454 log.error("Could not find Bridge {} in {}", bridgeName, nodeId);
455 return;
456 }
457
458 String portUuid = getPortUuid(portName, bridgeUuid);
459 if (portUuid != null) {
460 log.info("Port {} delete", portName);
Frank Wange11a98d2016-10-26 17:04:03 +0800461 deleteConfig(PORT, UUID, portUuid, BRIDGE, PORTS, Uuid.uuid(portUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700462 }
463 }
464
Hyunsun Moon1251e192016-06-07 16:57:05 -0700465 @Deprecated
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700466 @Override
467 public void createBridge(String bridgeName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700468 OvsdbBridge ovsdbBridge = OvsdbBridge.builder()
469 .name(bridgeName)
470 .build();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700471
Hyunsun Moon1251e192016-06-07 16:57:05 -0700472 createBridge(ovsdbBridge);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700473 }
474
Hyunsun Moon1251e192016-06-07 16:57:05 -0700475 @Deprecated
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700476 @Override
lishuai6c56f5e2015-11-17 16:38:19 +0800477 public void createBridge(String bridgeName, String dpid, String exPortName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700478 OvsdbBridge ovsdbBridge = OvsdbBridge.builder()
479 .name(bridgeName)
480 .failMode(BridgeDescription.FailMode.SECURE)
481 .datapathId(dpid)
482 .disableInBand()
483 .controllers(Lists.newArrayList(localController()))
484 .build();
lishuai6c56f5e2015-11-17 16:38:19 +0800485
Hyunsun Moon1251e192016-06-07 16:57:05 -0700486 createBridge(ovsdbBridge);
lishuai6c56f5e2015-11-17 16:38:19 +0800487
lishuai6c56f5e2015-11-17 16:38:19 +0800488 if (exPortName != null) {
489 createPort(bridgeName, exPortName);
490 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700491 }
lishuai6c56f5e2015-11-17 16:38:19 +0800492
Hyunsun Moon1251e192016-06-07 16:57:05 -0700493 @Deprecated
494 @Override
495 public boolean createBridge(String bridgeName, String dpid, List<ControllerInfo> controllers) {
496 OvsdbBridge ovsdbBridge = OvsdbBridge.builder()
497 .name(bridgeName)
498 .failMode(BridgeDescription.FailMode.SECURE)
499 .datapathId(dpid)
500 .disableInBand()
501 .controllers(controllers)
502 .build();
503
504 return createBridge(ovsdbBridge);
lishuai6c56f5e2015-11-17 16:38:19 +0800505 }
506
507 @Override
Hyunsun Moon1251e192016-06-07 16:57:05 -0700508 public boolean createBridge(OvsdbBridge ovsdbBridge) {
509 DatabaseSchema dbSchema = schema.get(DATABASENAME);
510 String ovsUuid = getOvsUuid(DATABASENAME);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700511
512 if (dbSchema == null || ovsUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700513 log.error("Can't find database Open_vSwitch");
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700514 return false;
515 }
516
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700517 Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema, OvsdbTable.BRIDGE);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700518 bridge.setOtherConfig(ovsdbBridge.otherConfigs());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700519
Hyunsun Moon1251e192016-06-07 16:57:05 -0700520 if (ovsdbBridge.failMode().isPresent()) {
521 String failMode = ovsdbBridge.failMode().get().name().toLowerCase();
522 bridge.setFailMode(Sets.newHashSet(failMode));
Bob zhoue9795fd2016-05-12 20:18:45 +0800523 }
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700524
jaegonkim80bee532017-05-15 15:16:38 +0900525 if (ovsdbBridge.datapathType().isPresent()) {
526 String datapathType = ovsdbBridge.datapathType().get();
527 bridge.setDatapathType(datapathType);
528 }
529
Hyunsun Moon1251e192016-06-07 16:57:05 -0700530 String bridgeUuid = getBridgeUuid(ovsdbBridge.name());
Hyunsun Moon98025542016-03-08 04:36:02 -0800531 if (bridgeUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700532 bridge.setName(ovsdbBridge.name());
533 bridgeUuid = insertConfig(
534 BRIDGE, UUID, DATABASENAME, BRIDGES,
535 ovsUuid, bridge.getRow());
Hyunsun Moon98025542016-03-08 04:36:02 -0800536 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700537 // update the bridge if it's already existing
538 updateConfig(BRIDGE, UUID, bridgeUuid, bridge.getRow());
Hyunsun Moon98025542016-03-08 04:36:02 -0800539 }
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700540
Hyunsun Moon1251e192016-06-07 16:57:05 -0700541 if (bridgeUuid == null) {
542 log.warn("Failed to create bridge {} on {}", ovsdbBridge.name(), nodeId);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700543 return false;
544 }
545
Hyunsun Moon1251e192016-06-07 16:57:05 -0700546 createPort(ovsdbBridge.name(), ovsdbBridge.name());
547 setControllersWithUuid(Uuid.uuid(bridgeUuid), ovsdbBridge.controllers());
548
549 log.info("Created bridge {}", ovsdbBridge.name());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700550 return true;
551 }
552
Hyunsun Moon1251e192016-06-07 16:57:05 -0700553 @Override
554 public ControllerInfo localController() {
555 IpAddress ipAddress = IpAddress.valueOf(((InetSocketAddress)
556 channel.localAddress()).getAddress());
557 return new ControllerInfo(ipAddress, OFPORT, "tcp");
andreaed976a42015-10-05 14:38:25 -0700558 }
559
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700560 private void setControllersWithUuid(Uuid bridgeUuid, List<ControllerInfo> controllers) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700561 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -0700562 if (dbSchema == null) {
563 log.debug("There is no schema");
564 return;
565 }
566 List<Controller> oldControllers = getControllers(bridgeUuid);
567 if (oldControllers == null) {
568 log.warn("There are no controllers");
569 return;
570 }
571
Jonathan Hart51539b82015-10-29 09:53:04 -0700572 Set<Uuid> newControllerUuids = new HashSet<>();
andreaed976a42015-10-05 14:38:25 -0700573
574 Set<ControllerInfo> newControllers = new HashSet<>(controllers);
575 List<Controller> removeControllers = new ArrayList<>();
576 oldControllers.forEach(controller -> {
577 ControllerInfo controllerInfo = new ControllerInfo((String) controller.getTargetColumn().data());
578 if (newControllers.contains(controllerInfo)) {
579 newControllers.remove(controllerInfo);
580 newControllerUuids.add(controller.getRow().uuid());
581 } else {
582 removeControllers.add(controller);
583 }
584 });
Hyunsun Moon1251e192016-06-07 16:57:05 -0700585 OvsdbRowStore controllerRowStore = getRowStore(DATABASENAME, CONTROLLER);
andreaed976a42015-10-05 14:38:25 -0700586 if (controllerRowStore == null) {
587 log.debug("There is no controller table");
588 return;
589 }
590
Hyunsun Moon1251e192016-06-07 16:57:05 -0700591 removeControllers.forEach(c -> deleteConfig(CONTROLLER, UUID, c.getRow().uuid().value(),
Frank Wange11a98d2016-10-26 17:04:03 +0800592 BRIDGE, "controller", c.getRow().uuid()));
andreaed976a42015-10-05 14:38:25 -0700593 newControllers.stream().map(c -> {
594 Controller controller = (Controller) TableGenerator
595 .createTable(dbSchema, OvsdbTable.CONTROLLER);
596 controller.setTarget(c.target());
597 return controller;
598 }).forEach(c -> {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700599 String uuid = insertConfig(CONTROLLER, UUID, BRIDGE, "controller", bridgeUuid.value(),
andreaed976a42015-10-05 14:38:25 -0700600 c.getRow());
Jonathan Hart51539b82015-10-29 09:53:04 -0700601 newControllerUuids.add(Uuid.uuid(uuid));
andreaed976a42015-10-05 14:38:25 -0700602
603 });
604
Hyunsun Moon1251e192016-06-07 16:57:05 -0700605 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -0700606 if (rowStore == null) {
607 log.debug("There is no bridge table");
608 return;
609 }
610
611 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
612 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
613 bridge.setController(OvsdbSet.ovsdbSet(newControllerUuids));
Hyunsun Moon1251e192016-06-07 16:57:05 -0700614 updateConfig(BRIDGE, UUID, bridgeUuid.value(), bridge.getRow());
andreaed976a42015-10-05 14:38:25 -0700615 }
616
andreaed976a42015-10-05 14:38:25 -0700617 @Override
618 public void setControllersWithDeviceId(DeviceId deviceId, List<ControllerInfo> controllers) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700619 setControllersWithUuid(getBridgeUuid(deviceId), controllers);
andreaed976a42015-10-05 14:38:25 -0700620 }
621
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700622 @Override
623 public void dropBridge(String bridgeName) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700624 String bridgeUuid = getBridgeUuid(bridgeName);
625 if (bridgeUuid == null) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700626 log.warn("Could not find bridge in node", nodeId.getIpAddress());
627 return;
628 }
Frank Wange11a98d2016-10-26 17:04:03 +0800629 deleteConfig(BRIDGE, UUID, bridgeUuid, DATABASENAME, BRIDGES, Uuid.uuid(bridgeUuid));
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700630 }
631
Frank Wange11a98d2016-10-26 17:04:03 +0800632 @Override
633 public void applyQos(PortNumber portNumber, String qosName) {
634 DatabaseSchema dbSchema = schema.get(DATABASENAME);
635 OvsdbRowStore portRowStore = getRowStore(DATABASENAME, PORT);
636 if (portRowStore == null) {
637 log.debug("The port uuid is null");
638 return;
639 }
640 OvsdbRowStore qosRowStore = getRowStore(DATABASENAME, QOS);
641 if (qosRowStore == null) {
642 log.debug("The qos uuid is null");
643 return;
644 }
645
646 // Due to Qos Table doesn't have a unique identifier except uuid, unlike
647 // Bridge or Port Table has a name column,in order to make the api more
648 // general, put qos name in external_ids column of Qos Table if this qos
649 // created by onos.
650 ConcurrentMap<String, Row> qosTableRows = qosRowStore.getRowStore();
651 ConcurrentMap<String, Row> portTableRows = portRowStore.getRowStore();
652 Row qosRow = qosTableRows.values().stream().filter(r -> {
653 OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
654 return qosName.equals(ovsdbMap.map().get(QOS_EXTERNAL_ID_KEY));
655 }).findFirst().orElse(null);
656
657 Row portRow = portTableRows.values().stream()
658 .filter(r -> r.getColumn("name").data().equals(portNumber.name()))
659 .findFirst().orElse(null);
660 if (portRow != null && qosRow != null) {
661 String qosId = qosRow.uuid().value();
662 Uuid portUuid = portRow.uuid();
663 Map<String, Column> columns = new HashMap<>();
664 Row newPortRow = new Row(PORT, portUuid, columns);
665 Port newport = new Port(dbSchema, newPortRow);
666 columns.put(Port.PortColumn.QOS.columnName(), newport.getQosColumn());
667 newport.setQos(Uuid.uuid(qosId));
668 updateConfig(PORT, UUID, portUuid.value(), newport.getRow());
669 }
670 }
671
672 @Override
673 public void removeQos(PortNumber portNumber) {
674 DatabaseSchema dbSchema = schema.get(DATABASENAME);
675 OvsdbRowStore rowStore = getRowStore(DATABASENAME, PORT);
676 if (rowStore == null) {
677 log.debug("The qos uuid is null");
678 return;
679 }
680
681 ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
682 Row portRow = ovsTableRows.values().stream()
683 .filter(r -> r.getColumn("name").data().equals(portNumber.name()))
684 .findFirst().orElse(null);
685 if (portRow == null) {
686 log.warn("Couldn't find port {} in ovsdb port table.", portNumber.name());
687 return;
688 }
689
690 OvsdbSet ovsdbSet = ((OvsdbSet) portRow.getColumn(PORT_QOS).data());
691 @SuppressWarnings("unchecked")
692 Set<Uuid> qosIdSet = ovsdbSet.set();
693 if (qosIdSet == null || qosIdSet.isEmpty()) {
694 return;
695 }
696 Uuid qosUuid = (Uuid) qosIdSet.toArray()[0];
697 Condition condition = ConditionUtil.isEqual(UUID, portRow.uuid());
698 List<Condition> conditions = Lists.newArrayList(condition);
699 Mutation mutation = MutationUtil.delete(PORT_QOS, qosUuid);
700 List<Mutation> mutations = Lists.newArrayList(mutation);
701
702 ArrayList<Operation> operations = Lists.newArrayList();
703 Mutate mutate = new Mutate(dbSchema.getTableSchema(PORT), conditions, mutations);
704 operations.add(mutate);
705 transactConfig(DATABASENAME, operations);
706 }
707
708 @Override
709 public boolean createQos(OvsdbQos ovsdbQos) {
710 DatabaseSchema dbSchema = schema.get(DATABASENAME);
711 Qos qos = (Qos) TableGenerator.createTable(dbSchema, OvsdbTable.QOS);
712 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QOS);
713 if (rowStore == null) {
714 log.debug("The qos uuid is null");
715 return false;
716 }
717
718 ArrayList<Operation> operations = Lists.newArrayList();
719 Set<String> types = Sets.newHashSet();
720 Map<Long, Uuid> queues = Maps.newHashMap();
721
722 types.add(ovsdbQos.qosType());
723 qos.setOtherConfig(ovsdbQos.otherConfigs());
724 qos.setExternalIds(ovsdbQos.externalIds());
725 qos.setType(types);
726 if (ovsdbQos.qosQueues().isPresent()) {
727 for (Map.Entry<Long, String> entry : ovsdbQos.qosQueues().get().entrySet()) {
728 OvsdbRowStore queueRowStore = getRowStore(DATABASENAME, QUEUE);
729 if (queueRowStore != null) {
730 ConcurrentMap<String, Row> queueTableRows = queueRowStore.getRowStore();
731 Row queueRow = queueTableRows.values().stream().filter(r -> {
732 OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
733 return entry.getValue().equals(ovsdbMap.map().get(QUEUE_EXTERNAL_ID_KEY));
734 }).findFirst().orElse(null);
735 if (queueRow != null) {
736 queues.put(entry.getKey(), queueRow.uuid());
737 }
738 }
739 }
740 qos.setQueues(queues);
741 }
742
743 Insert qosInsert = new Insert(dbSchema.getTableSchema(QOS), QOS, qos.getRow());
744 operations.add(qosInsert);
745 try {
746 transactConfig(DATABASENAME, operations).get();
747 } catch (InterruptedException | ExecutionException e) {
748 return false;
749 }
750 return true;
751 }
752
753 @Override
754 public void dropQos(QosId qosId) {
755 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QOS);
756 if (rowStore != null) {
757 ConcurrentMap<String, Row> qosTableRows = rowStore.getRowStore();
758 Row qosRow = qosTableRows.values().stream().filter(r -> {
759 OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
760 return qosId.name().equals(ovsdbMap.map().get(QOS_EXTERNAL_ID_KEY));
761 }).findFirst().orElse(null);
762 if (qosRow != null) {
763 deleteConfig(QOS, UUID, qosRow.uuid().value(), PORT, PORT_QOS, qosRow.uuid());
764 }
765 }
766 }
767 @Override
768 public OvsdbQos getQos(QosId qosId) {
769 Set<OvsdbQos> ovsdbQoses = getQoses();
770 return ovsdbQoses.stream().filter(r ->
771 qosId.name().equals(r.externalIds().get(QOS_EXTERNAL_ID_KEY))).
772 findFirst().orElse(null);
773 }
774
775 @Override
776 public Set<OvsdbQos> getQoses() {
777 Set<OvsdbQos> ovsdbQoses = new HashSet<>();
778 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QOS);
779 if (rowStore == null) {
780 log.debug("The qos uuid is null");
781 return ovsdbQoses;
782 }
783 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
784 for (String uuid : rows.keySet()) {
785 Row row = getRow(DATABASENAME, QOS, uuid);
786 OvsdbQos ovsdbQos = getOvsdbQos(row);
787 if (ovsdbQos != null) {
788 ovsdbQoses.add(ovsdbQos);
789 }
790 }
791 return ovsdbQoses;
792 }
793
794 @Override
795 public boolean createQueue(OvsdbQueue ovsdbQueue) {
796 DatabaseSchema dbSchema = schema.get(DATABASENAME);
797 Queue queue = (Queue) TableGenerator.createTable(dbSchema, OvsdbTable.QUEUE);
798 ArrayList<Operation> operations = Lists.newArrayList();
799 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QUEUE);
800 if (rowStore == null) {
801 log.debug("The queue uuid is null");
802 return false;
803 }
804
805 if (ovsdbQueue.dscp().isPresent()) {
806 queue.setDscp(ImmutableSet.of(ovsdbQueue.dscp().get()));
807 }
808 queue.setOtherConfig(ovsdbQueue.otherConfigs());
809 queue.setExternalIds(ovsdbQueue.externalIds());
810 Insert queueInsert = new Insert(dbSchema.getTableSchema(QUEUE), QUEUE, queue.getRow());
811 operations.add(queueInsert);
812
813 try {
814 transactConfig(DATABASENAME, operations).get();
815 } catch (InterruptedException | ExecutionException e) {
816 log.error("createQueue transactConfig get exception !");
817 }
818 return true;
819 }
820
821 @Override
822 public void dropQueue(QueueId queueId) {
823 OvsdbRowStore queueRowStore = getRowStore(DATABASENAME, QUEUE);
824 if (queueRowStore == null) {
825 return;
826 }
827
828 ConcurrentMap<String, Row> queueTableRows = queueRowStore.getRowStore();
829 Row queueRow = queueTableRows.values().stream().filter(r -> {
830 OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
831 return queueId.name().equals(ovsdbMap.map().get(QUEUE_EXTERNAL_ID_KEY));
832 }).findFirst().orElse(null);
833 if (queueRow == null) {
834 return;
835 }
836
837 String queueUuid = queueRow.uuid().value();
838 OvsdbRowStore qosRowStore = getRowStore(DATABASENAME, QOS);
839 if (qosRowStore != null) {
840 Map<Long, Uuid> queueMap = new HashMap<>();
841 ConcurrentMap<String, Row> qosTableRows = qosRowStore.getRowStore();
842 qosTableRows.values().stream().filter(r -> {
843 Map<Integer, Uuid> ovsdbMap = ((OvsdbMap) r.getColumn(QUEUES).data()).map();
844 Set<Integer> keySet = ovsdbMap.keySet();
845 for (Integer keyId : keySet) {
846 if (ovsdbMap.get(keyId).equals(Uuid.uuid(queueUuid))) {
847 queueMap.put(keyId.longValue(), Uuid.uuid(queueUuid));
848 return true;
849 }
850 }
851 return false;
852 }).findFirst().orElse(null);
853 deleteConfig(QUEUE, UUID, queueUuid, QOS, QUEUES, OvsdbMap.ovsdbMap(queueMap));
854 } else {
855 deleteConfig(QUEUE, UUID, queueUuid, null, null, null);
856 }
857 }
858 @Override
859 public OvsdbQueue getQueue(QueueId queueId) {
860 Set<OvsdbQueue> ovsdbQueues = getQueues();
861 return ovsdbQueues.stream().filter(r ->
862 queueId.name().equals(r.externalIds().get(QUEUE_EXTERNAL_ID_KEY))).
863 findFirst().orElse(null);
864 }
865
866 @Override
867 public Set<OvsdbQueue> getQueues() {
868 Set<OvsdbQueue> ovsdbqueues = new HashSet<>();
869 OvsdbRowStore rowStore = getRowStore(DATABASENAME, QUEUE);
870 if (rowStore == null) {
871 log.debug("The queue uuid is null");
872 return ovsdbqueues;
873 }
874 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
875 for (String uuid : rows.keySet()) {
876 Row row = getRow(DATABASENAME, QUEUE, uuid);
877 OvsdbQueue ovsdbQueue = getOvsdbQueue(row);
878 if (ovsdbQueue != null) {
879 ovsdbqueues.add(ovsdbQueue);
880 }
881 }
882 return ovsdbqueues;
883 }
Pier Ventref5d72362016-07-17 12:02:14 +0200884 /**
885 * Creates a mirror port. Mirrors the traffic
886 * that goes to selectDstPort or comes from
887 * selectSrcPort or packets containing selectVlan
888 * to mirrorPort or to all ports that trunk mirrorVlan.
889 *
890 * @param mirror the OVSDB mirror description
891 * @return true if mirror creation is successful, false otherwise
892 */
893 @Override
894 public boolean createMirror(String bridgeName, OvsdbMirror mirror) {
895
896 /**
897 * Retrieves bridge's uuid. It is necessary to update
898 * Bridge table.
899 */
900 String bridgeUuid = getBridgeUuid(bridgeName);
901 if (bridgeUuid == null) {
902 log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
903 return false;
904 }
905
906 OvsdbMirror.Builder mirrorBuilder = OvsdbMirror.builder();
907
908 mirrorBuilder.mirroringName(mirror.mirroringName());
909 mirrorBuilder.selectAll(mirror.selectAll());
910
911 /**
912 * Retrieves the uuid of the monitored dst ports.
913 */
914 mirrorBuilder.monitorDstPorts(mirror.monitorDstPorts().parallelStream()
915 .map(dstPort -> {
916 String dstPortUuid = getPortUuid(dstPort.value(), bridgeUuid);
917 if (dstPortUuid != null) {
918 return Uuid.uuid(dstPortUuid);
919 }
920 log.warn("Couldn't find port {} in {}",
921 dstPort.value(), nodeId.getIpAddress());
922 return null;
923 })
924 .filter(Objects::nonNull)
925 .collect(Collectors.toSet())
926 );
927
928 /**
929 * Retrieves the uuid of the monitored src ports.
930 */
931 mirrorBuilder.monitorSrcPorts(mirror.monitorSrcPorts().parallelStream()
932 .map(srcPort -> {
933 String srcPortUuid = getPortUuid(srcPort.value(), bridgeUuid);
934 if (srcPortUuid != null) {
935 return Uuid.uuid(srcPortUuid);
936 }
937 log.warn("Couldn't find port {} in {}",
938 srcPort.value(), nodeId.getIpAddress());
939 return null;
940 }).filter(Objects::nonNull)
941 .collect(Collectors.toSet())
942 );
943
944 mirrorBuilder.monitorVlans(mirror.monitorVlans());
945 mirrorBuilder.mirrorPort(mirror.mirrorPort());
946 mirrorBuilder.mirrorVlan(mirror.mirrorVlan());
947 mirrorBuilder.externalIds(mirror.externalIds());
948 mirror = mirrorBuilder.build();
949
Jon Hallcbd1b392017-01-18 20:15:44 -0800950 if (mirror.monitorDstPorts().isEmpty() &&
951 mirror.monitorSrcPorts().isEmpty() &&
952 mirror.monitorVlans().isEmpty()) {
Pier Ventref5d72362016-07-17 12:02:14 +0200953 log.warn("Invalid monitoring data");
954 return false;
955 }
956
957 DatabaseSchema dbSchema = schema.get(DATABASENAME);
958
959 Mirror mirrorEntry = (Mirror) TableGenerator.createTable(dbSchema, OvsdbTable.MIRROR);
960 mirrorEntry.setName(mirror.mirroringName());
961 mirrorEntry.setSelectDstPort(mirror.monitorDstPorts());
962 mirrorEntry.setSelectSrcPort(mirror.monitorSrcPorts());
963 mirrorEntry.setSelectVlan(mirror.monitorVlans());
964 mirrorEntry.setExternalIds(mirror.externalIds());
965
966 /**
967 * If mirror port, retrieves the uuid of the mirror port.
968 */
969 if (mirror.mirrorPort() != null) {
970
971 String outputPortUuid = getPortUuid(mirror.mirrorPort().value(), bridgeUuid);
972 if (outputPortUuid == null) {
973 log.warn("Couldn't find port {} in {}", mirror.mirrorPort().value(), nodeId.getIpAddress());
974 return false;
975 }
976
977 mirrorEntry.setOutputPort(Uuid.uuid(outputPortUuid));
978
979 } else if (mirror.mirrorVlan() != null) {
980
981 mirrorEntry.setOutputVlan(mirror.mirrorVlan());
982
983 } else {
984 log.warn("Invalid mirror, no mirror port and no mirror vlan");
985 return false;
986 }
987
988 ArrayList<Operation> operations = Lists.newArrayList();
989 Insert mirrorInsert = new Insert(dbSchema.getTableSchema("Mirror"), "Mirror", mirrorEntry.getRow());
990 operations.add(mirrorInsert);
991
992 // update the bridge table
993 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(bridgeUuid));
994 Mutation mutation = MutationUtil.insert(MIRRORS, Uuid.uuid("Mirror"));
995 List<Condition> conditions = Lists.newArrayList(condition);
996 List<Mutation> mutations = Lists.newArrayList(mutation);
997 operations.add(new Mutate(dbSchema.getTableSchema("Bridge"), conditions, mutations));
998
999 transactConfig(DATABASENAME, operations);
1000 log.info("Created mirror {}", mirror.mirroringName());
1001 return true;
1002 }
1003
1004 /**
1005 * Drops the configuration for mirror.
1006 *
Ray Milkeyef794342016-11-09 16:20:29 -08001007 * @param mirroringName name of mirror to drop
Pier Ventref5d72362016-07-17 12:02:14 +02001008 */
1009 @Override
1010 public void dropMirror(MirroringName mirroringName) {
1011 String mirrorUuid = getMirrorUuid(mirroringName.name());
1012 if (mirrorUuid != null) {
1013 log.info("Deleted mirror {}", mirroringName.name());
Frank Wange11a98d2016-10-26 17:04:03 +08001014 deleteConfig(MIRROR, UUID, mirrorUuid, BRIDGE, MIRRORS, Uuid.uuid(mirrorUuid));
Pier Ventref5d72362016-07-17 12:02:14 +02001015 }
1016 log.warn("Unable to delete {}", mirroringName.name());
1017 return;
1018 }
1019
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001020 @Deprecated
1021 @Override
1022 public boolean createTunnel(String bridgeName, String ifaceName, String tunnelType,
1023 Map<String, String> options) {
1024 OvsdbInterface ovsdbIface = OvsdbInterface.builder()
1025 .name(ifaceName)
1026 .type(Type.valueOf(tunnelType))
1027 .options(options)
1028 .build();
1029
1030 return createInterface(bridgeName, ovsdbIface);
1031 }
1032
1033 @Deprecated
1034 @Override
1035 public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001036 }
1037
1038 @Override
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001039 public boolean createInterface(String bridgeName, OvsdbInterface ovsdbIface) {
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001040 String bridgeUuid = getBridgeUuid(bridgeName);
1041 if (bridgeUuid == null) {
1042 log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
1043 return false;
1044 }
1045
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001046 if (getPortUuid(ovsdbIface.name(), bridgeUuid) != null) {
1047 log.warn("Interface {} already exists", ovsdbIface.name());
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001048 // remove existing one and re-create?
1049 return false;
1050 }
1051
1052 ArrayList<Operation> operations = Lists.newArrayList();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001053 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001054
Hyunsun Moon89478662016-06-09 17:52:34 -07001055 // insert a new port with the interface name
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001056 Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001057 port.setName(ovsdbIface.name());
1058 Insert portInsert = new Insert(dbSchema.getTableSchema(PORT), PORT, port.getRow());
1059 portInsert.getRow().put(INTERFACES, Uuid.uuid(INTERFACE));
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001060 operations.add(portInsert);
1061
Hyunsun Moon89478662016-06-09 17:52:34 -07001062 // update the bridge table with the new port
Hyunsun Moon1251e192016-06-07 16:57:05 -07001063 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(bridgeUuid));
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001064 Mutation mutation = MutationUtil.insert(PORTS, Uuid.uuid(PORT));
1065 List<Condition> conditions = Lists.newArrayList(condition);
1066 List<Mutation> mutations = Lists.newArrayList(mutation);
1067 operations.add(new Mutate(dbSchema.getTableSchema(BRIDGE), conditions, mutations));
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001068
Hyunsun Moon89478662016-06-09 17:52:34 -07001069 // insert an interface
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001070 Interface intf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001071 intf.setName(ovsdbIface.name());
1072 intf.setType(ovsdbIface.typeToString());
1073 intf.setOptions(ovsdbIface.options());
1074 Insert intfInsert = new Insert(dbSchema.getTableSchema(INTERFACE), INTERFACE, intf.getRow());
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001075 operations.add(intfInsert);
1076
Hyunsun Moon1251e192016-06-07 16:57:05 -07001077 transactConfig(DATABASENAME, operations);
Hyunsun Moon89478662016-06-09 17:52:34 -07001078 log.info("Created interface {}", ovsdbIface);
Hyunsun Moon646d8c42015-10-08 20:32:44 -07001079 return true;
1080 }
1081
1082 @Override
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001083 public boolean dropInterface(String ifaceName) {
1084 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
1085 if (rowStore == null) {
1086 log.warn("Failed to get BRIDGE table");
1087 return false;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001088 }
1089
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001090 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
1091 if (bridgeTableRows == null) {
1092 log.warn("Failed to get BRIDGE table rows");
1093 return false;
1094 }
1095
1096 // interface name is unique
1097 Optional<String> bridgeId = bridgeTableRows.keySet().stream()
1098 .filter(uuid -> getPortUuid(ifaceName, uuid) != null)
1099 .findFirst();
1100
1101 if (bridgeId.isPresent()) {
1102 String portId = getPortUuid(ifaceName, bridgeId.get());
Frank Wange11a98d2016-10-26 17:04:03 +08001103 deleteConfig(PORT, UUID, portId, BRIDGE, PORTS, Uuid.uuid(portId));
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001104 return true;
1105 } else {
1106 log.warn("Unable to find the interface with name {}", ifaceName);
1107 return false;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001108 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001109 }
1110
1111 /**
1112 * Delete transact config.
1113 *
andreaed976a42015-10-05 14:38:25 -07001114 * @param childTableName child table name
1115 * @param childColumnName child column name
1116 * @param childUuid child row uuid
1117 * @param parentTableName parent table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001118 * @param parentColumnName parent column
Frank Wange11a98d2016-10-26 17:04:03 +08001119 * @param referencedValue referenced value
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001120 */
1121 private void deleteConfig(String childTableName, String childColumnName,
andreaed976a42015-10-05 14:38:25 -07001122 String childUuid, String parentTableName,
Frank Wange11a98d2016-10-26 17:04:03 +08001123 String parentColumnName, Object referencedValue) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001124 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001125 TableSchema childTableSchema = dbSchema.getTableSchema(childTableName);
1126
1127 ArrayList<Operation> operations = Lists.newArrayList();
Frank Wange11a98d2016-10-26 17:04:03 +08001128 if (parentTableName != null && parentColumnName != null && referencedValue != null) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001129 TableSchema parentTableSchema = dbSchema
1130 .getTableSchema(parentTableName);
1131 ColumnSchema parentColumnSchema = parentTableSchema
1132 .getColumnSchema(parentColumnName);
1133 List<Mutation> mutations = Lists.newArrayList();
Frank Wange11a98d2016-10-26 17:04:03 +08001134 Mutation mutation = MutationUtil.delete(parentColumnSchema.name(), referencedValue);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001135 mutations.add(mutation);
1136 List<Condition> conditions = Lists.newArrayList();
Frank Wange11a98d2016-10-26 17:04:03 +08001137 Condition condition = ConditionUtil.includes(parentColumnName, referencedValue);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001138 conditions.add(condition);
1139 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
1140 operations.add(op);
1141 }
1142
1143 List<Condition> conditions = Lists.newArrayList();
Jonathan Hart51539b82015-10-29 09:53:04 -07001144 Condition condition = ConditionUtil.isEqual(childColumnName, Uuid.uuid(childUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001145 conditions.add(condition);
1146 Delete del = new Delete(childTableSchema, conditions);
1147 operations.add(del);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001148 transactConfig(DATABASENAME, operations);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001149 }
1150
1151 /**
1152 * Update transact config.
1153 *
andreaed976a42015-10-05 14:38:25 -07001154 * @param tableName table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001155 * @param columnName column name
andreaed976a42015-10-05 14:38:25 -07001156 * @param uuid uuid
1157 * @param row the config data
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001158 */
1159 private void updateConfig(String tableName, String columnName, String uuid,
andreaed976a42015-10-05 14:38:25 -07001160 Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001161 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001162 TableSchema tableSchema = dbSchema.getTableSchema(tableName);
1163
1164 List<Condition> conditions = Lists.newArrayList();
Jonathan Hart51539b82015-10-29 09:53:04 -07001165 Condition condition = ConditionUtil.isEqual(columnName, Uuid.uuid(uuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001166 conditions.add(condition);
1167
1168 Update update = new Update(tableSchema, row, conditions);
1169
1170 ArrayList<Operation> operations = Lists.newArrayList();
1171 operations.add(update);
1172
Hyunsun Moon1251e192016-06-07 16:57:05 -07001173 transactConfig(DATABASENAME, operations);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001174 }
1175
1176 /**
1177 * Insert transact config.
1178 *
andreaed976a42015-10-05 14:38:25 -07001179 * @param childTableName child table name
1180 * @param childColumnName child column name
1181 * @param parentTableName parent table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001182 * @param parentColumnName parent column
andreaed976a42015-10-05 14:38:25 -07001183 * @param parentUuid parent uuid
1184 * @param row the config data
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001185 * @return uuid, empty if no uuid is find
1186 */
1187 private String insertConfig(String childTableName, String childColumnName,
andreaed976a42015-10-05 14:38:25 -07001188 String parentTableName, String parentColumnName,
1189 String parentUuid, Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001190 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001191 TableSchema tableSchema = dbSchema.getTableSchema(childTableName);
1192
Sho SHIMIZUff18f8c2016-03-11 14:43:53 -08001193 Insert insert = new Insert(tableSchema, childTableName, row);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001194
1195 ArrayList<Operation> operations = Lists.newArrayList();
1196 operations.add(insert);
1197
1198 if (parentTableName != null && parentColumnName != null) {
1199 TableSchema parentTableSchema = dbSchema
1200 .getTableSchema(parentTableName);
1201 ColumnSchema parentColumnSchema = parentTableSchema
1202 .getColumnSchema(parentColumnName);
1203
1204 List<Mutation> mutations = Lists.newArrayList();
1205 Mutation mutation = MutationUtil.insert(parentColumnSchema.name(),
Sho SHIMIZUff18f8c2016-03-11 14:43:53 -08001206 Uuid.uuid(childTableName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001207 mutations.add(mutation);
1208
1209 List<Condition> conditions = Lists.newArrayList();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001210 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(parentUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001211 conditions.add(condition);
1212
1213 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
1214 operations.add(op);
1215 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001216 if (childTableName.equalsIgnoreCase(PORT)) {
1217 log.debug("Handle port insert");
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001218 Insert intfInsert = handlePortInsertTable(row);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001219
1220 if (intfInsert != null) {
1221 operations.add(intfInsert);
1222 }
1223
1224 Insert ins = (Insert) operations.get(0);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001225 ins.getRow().put("interfaces", Uuid.uuid(INTERFACE));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001226 }
1227
1228 List<OperationResult> results;
1229 try {
jaegonkim01d7c912017-01-22 22:03:38 +09001230 results = transactConfig(DATABASENAME, operations)
1231 .get(TRANSACTCONFIG_TIMEOUT, TimeUnit.SECONDS);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001232 return results.get(0).getUuid().value();
jaegonkim01d7c912017-01-22 22:03:38 +09001233 } catch (TimeoutException e) {
1234 log.warn("TimeoutException thrown while to get result");
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001235 } catch (InterruptedException e) {
1236 log.warn("Interrupted while waiting to get result");
1237 Thread.currentThread().interrupt();
1238 } catch (ExecutionException e) {
1239 log.error("Exception thrown while to get result");
1240 }
1241
1242 return null;
1243 }
1244
jaegonkim01d7c912017-01-22 22:03:38 +09001245
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001246 /**
1247 * Handles port insert.
1248 *
andreaed976a42015-10-05 14:38:25 -07001249 * @param portRow row of port
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001250 * @return insert, empty if null
1251 */
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001252 private Insert handlePortInsertTable(Row portRow) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001253 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001254
Hyunsun Moon1251e192016-06-07 16:57:05 -07001255 TableSchema portTableSchema = dbSchema.getTableSchema(PORT);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001256 ColumnSchema portColumnSchema = portTableSchema.getColumnSchema("name");
1257
1258 String portName = (String) portRow.getColumn(portColumnSchema.name()).data();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001259 Interface inf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001260 inf.setName(portName);
1261
Hyunsun Moon1251e192016-06-07 16:57:05 -07001262 TableSchema intfTableSchema = dbSchema.getTableSchema(INTERFACE);
1263 return new Insert(intfTableSchema, INTERFACE, inf.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001264 }
1265
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001266 @Override
1267 public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
1268 if (dbName == null) {
1269 return null;
1270 }
1271 DatabaseSchema databaseSchema = schema.get(dbName);
1272 if (databaseSchema == null) {
1273 List<String> dbNames = new ArrayList<String>();
1274 dbNames.add(dbName);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001275 Function<JsonNode, DatabaseSchema> rowFunction = input -> {
1276 log.debug("Get ovsdb database schema {}", dbName);
1277 DatabaseSchema dbSchema = FromJsonUtil.jsonNodeToDbSchema(dbName, input);
1278 if (dbSchema == null) {
1279 log.debug("Get ovsdb database schema error");
1280 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001281 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001282 schema.put(dbName, dbSchema);
1283 return dbSchema;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001284 };
1285
1286 ListenableFuture<JsonNode> input = getSchema(dbNames);
1287 if (input != null) {
1288 return Futures.transform(input, rowFunction);
1289 }
1290 return null;
1291 } else {
1292 return Futures.immediateFuture(databaseSchema);
1293 }
1294 }
1295
1296 @Override
1297 public ListenableFuture<TableUpdates> monitorTables(String dbName, String id) {
1298 if (dbName == null) {
1299 return null;
1300 }
1301 DatabaseSchema dbSchema = schema.get(dbName);
1302 if (dbSchema != null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001303 Function<JsonNode, TableUpdates> rowFunction = input -> {
1304 log.debug("Get table updates");
1305 TableUpdates updates = FromJsonUtil.jsonNodeToTableUpdates(input, dbSchema);
1306 if (updates == null) {
1307 log.debug("Get table updates error");
1308 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001309 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001310 return updates;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001311 };
1312 return Futures.transform(monitor(dbSchema, id), rowFunction);
1313 }
1314 return null;
1315 }
1316
Hyunsun Moondd14e8e2016-06-09 16:17:32 -07001317 private ListenableFuture<List<OperationResult>> transactConfig(String dbName,
1318 List<Operation> operations) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001319 if (dbName == null) {
1320 return null;
1321 }
1322 DatabaseSchema dbSchema = schema.get(dbName);
1323 if (dbSchema != null) {
andreaed976a42015-10-05 14:38:25 -07001324 Function<List<JsonNode>, List<OperationResult>> rowFunction = (input -> {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001325 log.debug("Get ovsdb operation result");
1326 List<OperationResult> result = FromJsonUtil.jsonNodeToOperationResult(input, operations);
andreaed976a42015-10-05 14:38:25 -07001327 if (result == null) {
1328 log.debug("The operation result is null");
1329 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001330 }
andreaed976a42015-10-05 14:38:25 -07001331 return result;
1332 });
Hyunsun Moon1251e192016-06-07 16:57:05 -07001333 return Futures.transform(transact(dbSchema, operations), rowFunction);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001334 }
1335 return null;
1336 }
1337
1338 @Override
1339 public ListenableFuture<JsonNode> getSchema(List<String> dbnames) {
1340 String id = java.util.UUID.randomUUID().toString();
1341 String getSchemaString = JsonRpcWriterUtil.getSchemaStr(id, dbnames);
1342
1343 SettableFuture<JsonNode> sf = SettableFuture.create();
1344 requestResult.put(id, sf);
1345 requestMethod.put(id, "getSchema");
1346
1347 channel.writeAndFlush(getSchemaString);
1348 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001349 }
1350
1351 @Override
1352 public ListenableFuture<List<String>> echo() {
1353 String id = java.util.UUID.randomUUID().toString();
1354 String echoString = JsonRpcWriterUtil.echoStr(id);
1355
1356 SettableFuture<List<String>> sf = SettableFuture.create();
1357 requestResult.put(id, sf);
1358 requestMethod.put(id, "echo");
1359
1360 channel.writeAndFlush(echoString);
1361 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001362 }
1363
1364 @Override
1365 public ListenableFuture<JsonNode> monitor(DatabaseSchema dbSchema,
1366 String monitorId) {
1367 String id = java.util.UUID.randomUUID().toString();
1368 String monitorString = JsonRpcWriterUtil.monitorStr(id, monitorId,
1369 dbSchema);
1370
1371 SettableFuture<JsonNode> sf = SettableFuture.create();
1372 requestResult.put(id, sf);
1373 requestMethod.put(id, "monitor");
1374
1375 channel.writeAndFlush(monitorString);
1376 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001377 }
1378
1379 @Override
1380 public ListenableFuture<List<String>> listDbs() {
1381 String id = java.util.UUID.randomUUID().toString();
1382 String listDbsString = JsonRpcWriterUtil.listDbsStr(id);
1383
1384 SettableFuture<List<String>> sf = SettableFuture.create();
1385 requestResult.put(id, sf);
1386 requestMethod.put(id, "listDbs");
1387
1388 channel.writeAndFlush(listDbsString);
1389 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001390 }
1391
1392 @Override
1393 public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema,
1394 List<Operation> operations) {
1395 String id = java.util.UUID.randomUUID().toString();
1396 String transactString = JsonRpcWriterUtil.transactStr(id, dbSchema,
1397 operations);
1398
1399 SettableFuture<List<JsonNode>> sf = SettableFuture.create();
1400 requestResult.put(id, sf);
1401 requestMethod.put(id, "transact");
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001402 channel.writeAndFlush(transactString);
1403 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001404 }
1405
andreaed976a42015-10-05 14:38:25 -07001406 @SuppressWarnings({"rawtypes", "unchecked"})
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001407 @Override
1408 public void processResult(JsonNode response) {
1409 log.debug("Handle result");
1410 String requestId = response.get("id").asText();
1411 SettableFuture sf = requestResult.get(requestId);
1412 if (sf == null) {
1413 log.debug("No such future to process");
1414 return;
1415 }
1416 String methodName = requestMethod.get(requestId);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001417 sf.set(FromJsonUtil.jsonResultParser(response, methodName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001418 }
1419
1420 @Override
1421 public void processRequest(JsonNode requestJson) {
1422 log.debug("Handle request");
1423 if (requestJson.get("method").asText().equalsIgnoreCase("echo")) {
1424 log.debug("handle echo request");
1425
1426 String replyString = FromJsonUtil.getEchoRequestStr(requestJson);
1427 channel.writeAndFlush(replyString);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001428 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001429 FromJsonUtil.jsonCallbackRequestParser(requestJson, monitorCallBack);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001430 }
1431 }
1432
1433 @Override
1434 public void setCallback(Callback monitorCallback) {
1435 this.monitorCallBack = monitorCallback;
1436 }
1437
1438 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001439 public Set<OvsdbBridge> getBridges() {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001440 Set<OvsdbBridge> ovsdbBridges = new HashSet<>();
1441 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001442 if (tableStore == null) {
MaoJianweidac220d2016-07-04 22:37:52 +08001443 return ovsdbBridges;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001444 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001445 OvsdbRowStore rowStore = tableStore.getRows(BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001446 if (rowStore == null) {
MaoJianweidac220d2016-07-04 22:37:52 +08001447 return ovsdbBridges;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001448 }
1449 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1450 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001451 Row row = getRow(DATABASENAME, BRIDGE, uuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001452 OvsdbBridge ovsdbBridge = getOvsdbBridge(row);
1453 if (ovsdbBridge != null) {
1454 ovsdbBridges.add(ovsdbBridge);
1455 }
1456 }
1457 return ovsdbBridges;
1458 }
1459
1460 @Override
andreaed976a42015-10-05 14:38:25 -07001461 public Set<ControllerInfo> getControllers(DeviceId openflowDeviceId) {
Jonathan Hart51539b82015-10-29 09:53:04 -07001462 Uuid bridgeUuid = getBridgeUuid(openflowDeviceId);
andreaed976a42015-10-05 14:38:25 -07001463 if (bridgeUuid == null) {
1464 log.warn("bad bridge Uuid");
1465 return null;
1466 }
1467 List<Controller> controllers = getControllers(bridgeUuid);
1468 if (controllers == null) {
1469 log.warn("bad list of controllers");
1470 return null;
1471 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001472 return controllers.stream().map(controller -> new ControllerInfo(
1473 (String) controller.getTargetColumn()
1474 .data())).collect(Collectors.toSet());
andreaed976a42015-10-05 14:38:25 -07001475 }
1476
Jonathan Hart51539b82015-10-29 09:53:04 -07001477 private List<Controller> getControllers(Uuid bridgeUuid) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001478 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -07001479 if (dbSchema == null) {
1480 return null;
1481 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001482 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -07001483 if (rowStore == null) {
1484 log.debug("There is no bridge table");
1485 return null;
1486 }
1487
1488 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
1489 Bridge bridge = (Bridge) TableGenerator.
1490 getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
1491
1492 //FIXME remove log
1493 log.warn("type of controller column", bridge.getControllerColumn()
1494 .data().getClass());
Jonathan Hart51539b82015-10-29 09:53:04 -07001495 Set<Uuid> controllerUuids = (Set<Uuid>) ((OvsdbSet) bridge
andreaed976a42015-10-05 14:38:25 -07001496 .getControllerColumn().data()).set();
andreaed976a42015-10-05 14:38:25 -07001497
Hyunsun Moon1251e192016-06-07 16:57:05 -07001498 OvsdbRowStore controllerRowStore = getRowStore(DATABASENAME, CONTROLLER);
andreaed976a42015-10-05 14:38:25 -07001499 if (controllerRowStore == null) {
1500 log.debug("There is no controller table");
1501 return null;
1502 }
1503
1504 List<Controller> ovsdbControllers = new ArrayList<>();
1505 ConcurrentMap<String, Row> controllerTableRows = controllerRowStore.getRowStore();
1506 controllerTableRows.forEach((key, row) -> {
Jonathan Hart51539b82015-10-29 09:53:04 -07001507 if (!controllerUuids.contains(Uuid.uuid(key))) {
andreaed976a42015-10-05 14:38:25 -07001508 return;
1509 }
1510 Controller controller = (Controller) TableGenerator
1511 .getTable(dbSchema, row, OvsdbTable.CONTROLLER);
1512 ovsdbControllers.add(controller);
1513 });
1514 return ovsdbControllers;
1515 }
1516
1517
Jonathan Hart51539b82015-10-29 09:53:04 -07001518 private Uuid getBridgeUuid(DeviceId openflowDeviceId) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001519 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -07001520 if (dbSchema == null) {
1521 return null;
1522 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001523 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -07001524 if (rowStore == null) {
1525 log.debug("There is no bridge table");
1526 return null;
1527 }
1528
1529 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
Jonathan Hart51539b82015-10-29 09:53:04 -07001530 final AtomicReference<Uuid> uuid = new AtomicReference<>();
andreaed976a42015-10-05 14:38:25 -07001531 for (Map.Entry<String, Row> entry : bridgeTableRows.entrySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001532 Bridge bridge = (Bridge) TableGenerator.getTable(
1533 dbSchema,
1534 entry.getValue(),
1535 OvsdbTable.BRIDGE);
1536
1537 if (matchesDpid(bridge, openflowDeviceId)) {
Jonathan Hart51539b82015-10-29 09:53:04 -07001538 uuid.set(Uuid.uuid(entry.getKey()));
andreaed976a42015-10-05 14:38:25 -07001539 break;
1540 }
1541 }
1542 if (uuid.get() == null) {
1543 log.debug("There is no bridge for {}", openflowDeviceId);
1544 }
1545 return uuid.get();
andreaed976a42015-10-05 14:38:25 -07001546 }
1547
1548 private static boolean matchesDpid(Bridge b, DeviceId deviceId) {
1549 String ofDpid = deviceId.toString().replace("of:", "");
1550 Set ofDeviceIds = ((OvsdbSet) b.getDatapathIdColumn().data()).set();
1551 //TODO Set<String>
1552 return ofDeviceIds.contains(ofDpid);
1553 }
1554
1555 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001556 public Set<OvsdbPort> getPorts() {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001557 Set<OvsdbPort> ovsdbPorts = new HashSet<>();
1558 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001559 if (tableStore == null) {
1560 return null;
1561 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001562 OvsdbRowStore rowStore = tableStore.getRows(INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001563 if (rowStore == null) {
1564 return null;
1565 }
1566 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1567 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001568 Row row = getRow(DATABASENAME, INTERFACE, uuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001569 OvsdbPort ovsdbPort = getOvsdbPort(row);
1570 if (ovsdbPort != null) {
1571 ovsdbPorts.add(ovsdbPort);
1572 }
1573 }
1574 return ovsdbPorts;
1575 }
1576
1577 @Override
1578 public DatabaseSchema getDatabaseSchema(String dbName) {
1579 return schema.get(dbName);
1580 }
1581
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001582 private OvsdbPort getOvsdbPort(Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001583 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001584 Interface intf = (Interface) TableGenerator
1585 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1586 if (intf == null) {
1587 return null;
1588 }
1589 long ofPort = getOfPort(intf);
1590 String portName = intf.getName();
1591 if ((ofPort < 0) || (portName == null)) {
1592 return null;
1593 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001594 return new OvsdbPort(new OvsdbPortNumber(ofPort), new OvsdbPortName(portName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001595 }
1596
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001597 private OvsdbBridge getOvsdbBridge(Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001598 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
1599 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, row, OvsdbTable.BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001600 if (bridge == null) {
1601 return null;
1602 }
1603
1604 OvsdbSet datapathIdSet = (OvsdbSet) bridge.getDatapathIdColumn().data();
1605 @SuppressWarnings("unchecked")
1606 Set<String> datapathIds = datapathIdSet.set();
Jon Hallcbd1b392017-01-18 20:15:44 -08001607 if (datapathIds == null || datapathIds.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001608 return null;
1609 }
1610 String datapathId = (String) datapathIds.toArray()[0];
1611 String bridgeName = bridge.getName();
1612 if ((datapathId == null) || (bridgeName == null)) {
1613 return null;
1614 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001615 return OvsdbBridge.builder().name(bridgeName).datapathId(datapathId).build();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001616 }
1617
Frank Wange11a98d2016-10-26 17:04:03 +08001618 private OvsdbQos getOvsdbQos(Row row) {
1619 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
1620 Qos qos = (Qos) TableGenerator.getTable(dbSchema, row, OvsdbTable.QOS);
1621 if (qos == null) {
1622 return null;
1623 }
1624
1625 String type = (String) qos.getTypeColumn().data();
1626 Map<String, String> otherConfigs;
1627 Map<String, String> externalIds;
1628 Map<Long, String> queues;
1629
1630 otherConfigs = ((OvsdbMap) qos.getOtherConfigColumn().data()).map();
1631 externalIds = ((OvsdbMap) qos.getExternalIdsColumn().data()).map();
1632 queues = ((OvsdbMap) qos.getQueuesColumn().data()).map();
1633 return OvsdbQos.builder().qosType(type).
1634 queues(queues).otherConfigs(otherConfigs).
1635 externalIds(externalIds).build();
1636 }
1637
1638 private OvsdbQueue getOvsdbQueue(Row row) {
1639 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
1640 Queue queue = (Queue) TableGenerator.getTable(dbSchema, row, OvsdbTable.QUEUE);
1641 if (queue == null) {
1642 return null;
1643 }
1644
1645 OvsdbSet dscpOvsdbSet = ((OvsdbSet) queue.getDscpColumn().data());
1646 @SuppressWarnings("unchecked")
1647 Set<String> dscpSet = dscpOvsdbSet.set();
1648 Long dscp = null;
1649 if (dscpSet != null && !dscpSet.isEmpty()) {
1650 dscp = Long.valueOf((String) dscpSet.toArray()[0]);
1651 }
1652
1653 Map<String, String> otherConfigs;
1654 Map<String, String> externalIds;
1655
1656 otherConfigs = ((OvsdbMap) queue.getOtherConfigColumn().data()).map();
1657 externalIds = ((OvsdbMap) queue.getExternalIdsColumn().data()).map();
1658 return OvsdbQueue.builder().dscp(dscp).
1659 otherConfigs(otherConfigs).externalIds(externalIds).build();
1660 }
1661
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001662 private long getOfPort(Interface intf) {
1663 OvsdbSet ofPortSet = (OvsdbSet) intf.getOpenFlowPortColumn().data();
1664 @SuppressWarnings("unchecked")
1665 Set<Integer> ofPorts = ofPortSet.set();
Jon Hallcbd1b392017-01-18 20:15:44 -08001666 if (ofPorts == null || ofPorts.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001667 log.debug("The ofport is null in {}", intf.getName());
1668 return -1;
1669 }
1670 // return (long) ofPorts.toArray()[0];
1671 Iterator<Integer> it = ofPorts.iterator();
1672 return Long.parseLong(it.next().toString());
1673 }
CNluciusa66c3972015-09-06 20:31:29 +08001674
1675 @Override
1676 public Set<OvsdbPort> getLocalPorts(Iterable<String> ifaceids) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001677 Set<OvsdbPort> ovsdbPorts = new HashSet<>();
1678 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
CNluciusa66c3972015-09-06 20:31:29 +08001679 if (tableStore == null) {
1680 return null;
1681 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001682 OvsdbRowStore rowStore = tableStore.getRows(INTERFACE);
CNluciusa66c3972015-09-06 20:31:29 +08001683 if (rowStore == null) {
1684 return null;
1685 }
1686 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1687 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001688 Row row = getRow(DATABASENAME, INTERFACE, uuid);
1689 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
CNluciusa66c3972015-09-06 20:31:29 +08001690 Interface intf = (Interface) TableGenerator
1691 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1692 if (intf == null || getIfaceid(intf) == null) {
1693 continue;
1694 }
1695 String portName = intf.getName();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001696 if (portName == null) {
1697 continue;
1698 }
CNluciusa66c3972015-09-06 20:31:29 +08001699 Set<String> ifaceidSet = Sets.newHashSet(ifaceids);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001700 if (portName.startsWith(TYPEVXLAN) || !ifaceidSet.contains(getIfaceid(intf))) {
CNluciusa66c3972015-09-06 20:31:29 +08001701 continue;
1702 }
1703 long ofPort = getOfPort(intf);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001704 if (ofPort < 0) {
CNluciusa66c3972015-09-06 20:31:29 +08001705 continue;
1706 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001707 ovsdbPorts.add(new OvsdbPort(new OvsdbPortNumber(ofPort),
1708 new OvsdbPortName(portName)));
CNluciusa66c3972015-09-06 20:31:29 +08001709 }
1710 return ovsdbPorts;
1711 }
1712
1713 private String getIfaceid(Interface intf) {
1714 OvsdbMap ovsdbMap = (OvsdbMap) intf.getExternalIdsColumn().data();
1715 @SuppressWarnings("unchecked")
1716 Map<String, String> externalIds = ovsdbMap.map();
1717 if (externalIds.isEmpty()) {
1718 log.warn("The external_ids is null");
1719 return null;
1720 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001721 String ifaceid = externalIds.get(EXTERNAL_ID_INTERFACE_ID);
CNluciusa66c3972015-09-06 20:31:29 +08001722 if (ifaceid == null) {
1723 log.warn("The ifaceid is null");
1724 return null;
1725 }
1726 return ifaceid;
1727 }
Hyunsun Moon5fb20a52015-09-25 17:02:33 -07001728
1729 @Override
1730 public void disconnect() {
1731 channel.disconnect();
1732 this.agent.removeConnectedNode(nodeId);
1733 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001734}