blob: 428a411cffa157ac7f3c7a92c3e3d47ff4b1599d [file] [log] [blame]
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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.impl;
17
andreaed976a42015-10-05 14:38:25 -070018import com.fasterxml.jackson.databind.JsonNode;
debanshur37cf6ba2018-05-08 20:07:30 +053019import com.google.common.base.Strings;
andreaed976a42015-10-05 14:38:25 -070020import com.google.common.collect.ImmutableList;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070021import org.onlab.packet.IpAddress;
22import org.onlab.packet.MacAddress;
Hyunsun Moon5fb20a52015-09-25 17:02:33 -070023import org.onlab.packet.TpPort;
Jian Lieaf31032018-05-03 15:54:03 +090024import org.onlab.util.Tools;
25import org.onosproject.cfg.ComponentConfigService;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070026import org.onosproject.ovsdb.controller.DefaultEventSubject;
27import org.onosproject.ovsdb.controller.EventSubject;
28import org.onosproject.ovsdb.controller.OvsdbClientService;
29import org.onosproject.ovsdb.controller.OvsdbConstant;
30import org.onosproject.ovsdb.controller.OvsdbController;
31import org.onosproject.ovsdb.controller.OvsdbDatapathId;
32import org.onosproject.ovsdb.controller.OvsdbEvent;
33import org.onosproject.ovsdb.controller.OvsdbEvent.Type;
34import org.onosproject.ovsdb.controller.OvsdbEventListener;
35import org.onosproject.ovsdb.controller.OvsdbIfaceId;
36import org.onosproject.ovsdb.controller.OvsdbNodeId;
37import org.onosproject.ovsdb.controller.OvsdbNodeListener;
38import org.onosproject.ovsdb.controller.OvsdbPortName;
39import org.onosproject.ovsdb.controller.OvsdbPortNumber;
40import org.onosproject.ovsdb.controller.OvsdbPortType;
41import org.onosproject.ovsdb.controller.driver.OvsdbAgent;
debanshur37cf6ba2018-05-08 20:07:30 +053042import org.onosproject.ovsdb.controller.impl.TlsParams.TlsMode;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070043import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
44import org.onosproject.ovsdb.rfc.message.TableUpdate;
45import org.onosproject.ovsdb.rfc.message.TableUpdates;
46import org.onosproject.ovsdb.rfc.message.UpdateNotification;
47import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
48import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
49import org.onosproject.ovsdb.rfc.notation.Row;
Jonathan Hart51539b82015-10-29 09:53:04 -070050import org.onosproject.ovsdb.rfc.notation.Uuid;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070051import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
52import org.onosproject.ovsdb.rfc.table.Bridge;
53import org.onosproject.ovsdb.rfc.table.Interface;
54import org.onosproject.ovsdb.rfc.table.OvsdbTable;
55import org.onosproject.ovsdb.rfc.table.TableGenerator;
56import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
57import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070058import org.osgi.service.component.annotations.Activate;
59import org.osgi.service.component.annotations.Component;
60import org.osgi.service.component.annotations.Deactivate;
61import org.osgi.service.component.annotations.Modified;
62import org.osgi.service.component.annotations.Reference;
63import org.osgi.service.component.annotations.ReferenceCardinality;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070064import org.slf4j.Logger;
65import org.slf4j.LoggerFactory;
66
andreaed976a42015-10-05 14:38:25 -070067import java.math.BigInteger;
Jian Lieaf31032018-05-03 15:54:03 +090068import java.util.Dictionary;
andreaed976a42015-10-05 14:38:25 -070069import java.util.HashSet;
70import java.util.Iterator;
71import java.util.List;
72import java.util.Map;
debanshur37cf6ba2018-05-08 20:07:30 +053073import java.util.Objects;
andreaed976a42015-10-05 14:38:25 -070074import java.util.Set;
75import java.util.concurrent.ConcurrentHashMap;
76import java.util.concurrent.CopyOnWriteArraySet;
77import java.util.concurrent.ExecutionException;
jiangruibce80652017-10-17 14:35:42 +080078import java.util.concurrent.TimeUnit;
79import java.util.concurrent.TimeoutException;
jaegonkim1af0ae52017-01-01 10:46:55 +090080import java.util.function.Consumer;
andreaed976a42015-10-05 14:38:25 -070081
82import static com.google.common.base.Preconditions.checkNotNull;
debanshur37cf6ba2018-05-08 20:07:30 +053083import static org.onlab.util.Tools.get;
debanshur37cf6ba2018-05-08 20:07:30 +053084import static org.onosproject.ovsdb.controller.impl.Controller.MIN_KS_LENGTH;
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -070085import static org.onosproject.ovsdb.controller.impl.OsgiPropertyConstants.*;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070086
87/**
88 * The implementation of OvsdbController.
89 */
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -070090@Component(immediate = true, service = OvsdbController.class,
91 property = {
92 "serverMode" + ":Boolean=" + SERVER_MODE_DEFAULT,
93 "enableOvsdbTls" + ":Boolean=" + OVSDB_TLS_FLAG_DEFAULT,
94 "keyStoreLocation" + "=" + KS_FILE_DEFAULT,
95 "keyStorePassword" + "=" + KS_PASSWORD_DEFAULT,
96 "trustStoreLocation" + "=" + TS_FILE_DEFAULT,
97 "trustStorePassword" + "=" + TS_PASSWORD_DEFAULT,
98 })
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070099public class OvsdbControllerImpl implements OvsdbController {
100
101 public static final Logger log = LoggerFactory
102 .getLogger(OvsdbControllerImpl.class);
jiangruibce80652017-10-17 14:35:42 +0800103 private static final long DEFAULT_OVSDB_RPC_TIMEOUT = 3000;
104 private final Controller controller = new Controller();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700105 protected ConcurrentHashMap<OvsdbNodeId, OvsdbClientService> ovsdbClients =
kdarapufce5abb2018-05-10 19:37:53 +0530106 new ConcurrentHashMap<>();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700107 protected OvsdbAgent agent = new InternalOvsdbNodeAgent();
108 protected InternalMonitorCallBack updateCallback = new InternalMonitorCallBack();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700109 protected Set<OvsdbNodeListener> ovsdbNodeListener = new CopyOnWriteArraySet<>();
110 protected Set<OvsdbEventListener> ovsdbEventListener = new CopyOnWriteArraySet<>();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700111 protected ConcurrentHashMap<String, OvsdbClientService> requestNotification =
kdarapufce5abb2018-05-10 19:37:53 +0530112 new ConcurrentHashMap<>();
113 protected ConcurrentHashMap<String, String> requestDbName = new ConcurrentHashMap<>();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700114
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700115 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lieaf31032018-05-03 15:54:03 +0900116 protected ComponentConfigService configService;
117
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700118 /** Run as server mode, listen on 6640 port. */
119 private boolean serverMode = SERVER_MODE_DEFAULT;
Jian Lieaf31032018-05-03 15:54:03 +0900120
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700121 /** TLS mode for OVSDB channel; options are: true false. */
122 private boolean enableOvsdbTls = OVSDB_TLS_FLAG_DEFAULT;
debanshur37cf6ba2018-05-08 20:07:30 +0530123
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700124 /** File path to KeyStore for Ovsdb TLS Connections. */
125 protected String keyStoreLocation = KS_FILE_DEFAULT;
debanshur37cf6ba2018-05-08 20:07:30 +0530126
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700127 /** File path to TrustStore for Ovsdb TLS Connections. */
128 protected String trustStoreLocation = TS_FILE_DEFAULT;
debanshur37cf6ba2018-05-08 20:07:30 +0530129
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700130 /** KeyStore Password. */
131 protected String keyStorePassword = KS_PASSWORD_DEFAULT;
debanshur37cf6ba2018-05-08 20:07:30 +0530132
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700133 /** TrustStore Password. */
134 protected String trustStorePassword = TS_PASSWORD_DEFAULT;
debanshur37cf6ba2018-05-08 20:07:30 +0530135
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700136 @Activate
137 public void activate(ComponentContext context) {
Jian Lieaf31032018-05-03 15:54:03 +0900138 configService.registerProperties(getClass());
debanshur37cf6ba2018-05-08 20:07:30 +0530139 modified(context);
140 controller.start(agent, updateCallback, serverMode);
Jian Lieaf31032018-05-03 15:54:03 +0900141
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700142 log.info("Started");
143 }
144
145 @Deactivate
146 public void deactivate() {
147 controller.stop();
Jian Lieaf31032018-05-03 15:54:03 +0900148
149 configService.unregisterProperties(getClass(), false);
150
debanshur37cf6ba2018-05-08 20:07:30 +0530151 log.info("Stopped");
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700152 }
153
Jian Lieaf31032018-05-03 15:54:03 +0900154 @Modified
155 protected void modified(ComponentContext context) {
debanshur37cf6ba2018-05-08 20:07:30 +0530156 this.setConfigParams(context.getProperties());
157 }
Jian Lieaf31032018-05-03 15:54:03 +0900158
debanshur37cf6ba2018-05-08 20:07:30 +0530159 /**
160 * Sets config params.
161 *
162 * @param properties dictionary
163 */
164 public void setConfigParams(Dictionary<?, ?> properties) {
165 boolean restartRequired = setServerMode(properties);
166 TlsParams tlsParams = getTlsParams(properties);
167 restartRequired |= controller.setTlsParameters(tlsParams);
168 if (restartRequired) {
169 restartController();
170 }
171 }
172
173 /**
174 * Gets the TLS parameters from the properties dict.
175 *
176 * @param properties dictionary
177 * @return TlsParams Modified Tls Params
178 */
179 private TlsParams getTlsParams(Dictionary<?, ?> properties) {
180 TlsMode mode = null;
181
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700182 boolean flag = Tools.isPropertyEnabled(properties, OVSDB_TLS_FLAG);
debanshur37cf6ba2018-05-08 20:07:30 +0530183 if (Objects.isNull(flag) || !flag) {
184 log.warn("OvsdbTLS Disabled");
185 mode = TlsMode.DISABLED;
186 } else {
187 log.warn("OvsdbTLS Enabled");
188 mode = TlsMode.ENABLED;
189 }
190
191 String ksLocation = null, tsLocation = null, ksPwd = null, tsPwd = null;
192
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700193 ksLocation = get(properties, KS_FILE);
debanshur37cf6ba2018-05-08 20:07:30 +0530194 if (Strings.isNullOrEmpty(ksLocation)) {
195 log.warn("trustStoreLocation is not configured");
196 mode = TlsMode.DISABLED;
197 }
198
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700199 tsLocation = get(properties, TS_FILE);
debanshur37cf6ba2018-05-08 20:07:30 +0530200 if (Strings.isNullOrEmpty(tsLocation)) {
201 log.warn("trustStoreLocation is not configured");
202 mode = TlsMode.DISABLED;
203 }
204
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700205 ksPwd = get(properties, KS_PASSWORD);
debanshur37cf6ba2018-05-08 20:07:30 +0530206 if (Strings.isNullOrEmpty(ksPwd) || MIN_KS_LENGTH > ksPwd.length()) {
207 log.warn("keyStorePassword is not configured or Password length too small");
208 mode = TlsMode.DISABLED;
209 }
210
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700211 tsPwd = get(properties, TS_PASSWORD);
debanshur37cf6ba2018-05-08 20:07:30 +0530212 if (Strings.isNullOrEmpty(tsPwd) || MIN_KS_LENGTH > tsPwd.length()) {
213 log.warn("trustStorePassword is not configured or Password length too small");
214 mode = TlsMode.DISABLED;
215 }
216
217 TlsParams tlsParams = new TlsParams(mode, ksLocation, tsLocation, ksPwd, tsPwd);
218 log.info("OVSDB TLS Params: {}", tlsParams);
219 return tlsParams;
220 }
221
222 private boolean setServerMode(Dictionary<?, ?> properties) {
223 boolean flag = Tools.isPropertyEnabled(properties, "serverMode");
224 if (Objects.isNull(flag) || flag == serverMode) {
225 log.info("Ovsdb server mode is not configured, " +
226 "or modified. Using current value of {}", serverMode);
227 return false;
Jian Lieaf31032018-05-03 15:54:03 +0900228 } else {
229 serverMode = flag;
230 log.info("Configured. OVSDB server mode was {}",
debanshur37cf6ba2018-05-08 20:07:30 +0530231 serverMode ? "enabled" : "disabled");
232 return true;
Jian Lieaf31032018-05-03 15:54:03 +0900233 }
234
Jian Lieaf31032018-05-03 15:54:03 +0900235 }
236
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700237 @Override
238 public void addNodeListener(OvsdbNodeListener listener) {
239 if (!ovsdbNodeListener.contains(listener)) {
240 this.ovsdbNodeListener.add(listener);
241 }
242 }
243
244 @Override
245 public void removeNodeListener(OvsdbNodeListener listener) {
246 this.ovsdbNodeListener.remove(listener);
247 }
248
249 @Override
250 public void addOvsdbEventListener(OvsdbEventListener listener) {
251 if (!ovsdbEventListener.contains(listener)) {
252 this.ovsdbEventListener.add(listener);
253 }
254 }
255
256 @Override
257 public void removeOvsdbEventListener(OvsdbEventListener listener) {
258 this.ovsdbEventListener.remove(listener);
259 }
260
261 @Override
262 public List<OvsdbNodeId> getNodeIds() {
andreaed976a42015-10-05 14:38:25 -0700263 return ImmutableList.copyOf(ovsdbClients.keySet());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700264 }
265
266 @Override
267 public OvsdbClientService getOvsdbClient(OvsdbNodeId nodeId) {
268 return ovsdbClients.get(nodeId);
269 }
270
Hyunsun Moon5fb20a52015-09-25 17:02:33 -0700271 @Override
272 public void connect(IpAddress ip, TpPort port) {
273 controller.connect(ip, port);
274 }
275
jaegonkim1af0ae52017-01-01 10:46:55 +0900276 @Override
277 public void connect(IpAddress ip, TpPort port, Consumer<Exception> failhandler) {
278 controller.connect(ip, port, failhandler);
279 }
280
Jian Lieaf31032018-05-03 15:54:03 +0900281 @Override
282 public void setServerMode(boolean serverMode) {
283 this.serverMode = serverMode;
284 restartController();
285 }
286
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700287 /**
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700288 * Processes table updates.
289 *
290 * @param clientService OvsdbClientService instance
andreaed976a42015-10-05 14:38:25 -0700291 * @param updates TableUpdates instance
292 * @param dbName ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700293 */
294 private void processTableUpdates(OvsdbClientService clientService,
295 TableUpdates updates, String dbName)
296 throws InterruptedException {
297 checkNotNull(clientService, "OvsdbClientService is not null");
298
299 DatabaseSchema dbSchema = clientService.getDatabaseSchema(dbName);
300
301 for (String tableName : updates.result().keySet()) {
302 TableUpdate update = updates.result().get(tableName);
Jonathan Hart51539b82015-10-29 09:53:04 -0700303 for (Uuid uuid : (Set<Uuid>) update.rows().keySet()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700304 log.debug("Begin to process table updates uuid: {}, databaseName: {}, tableName: {}",
305 uuid.value(), dbName, tableName);
306
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700307 Row newRow = update.getNew(uuid);
308 if (newRow != null) {
309 clientService.updateOvsdbStore(dbName, tableName,
310 uuid.value(), newRow);
311
312 if (OvsdbConstant.INTERFACE.equals(tableName)) {
313 dispatchInterfaceEvent(clientService,
CNluciusa66c3972015-09-06 20:31:29 +0800314 newRow,
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700315 OvsdbEvent.Type.PORT_ADDED,
316 dbSchema);
317 }
318 } else if (update.getOld(uuid) != null) {
CNluciusa66c3972015-09-06 20:31:29 +0800319 if (OvsdbConstant.INTERFACE.equals(tableName)) {
320 Row row = clientService.getRow(OvsdbConstant.DATABASENAME, tableName, uuid.value());
321 dispatchInterfaceEvent(clientService,
322 row,
andreaed976a42015-10-05 14:38:25 -0700323 OvsdbEvent.Type.PORT_REMOVED,
324 dbSchema);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700325 }
CNluciusa66c3972015-09-06 20:31:29 +0800326 clientService.removeRow(dbName, tableName, uuid.value());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700327 }
328 }
329 }
330 }
331
332 /**
333 * Dispatches event to the north.
334 *
335 * @param clientService OvsdbClientService instance
tanbangchenge8d04392017-11-18 18:12:47 +0800336 * @param row a new row
andreaed976a42015-10-05 14:38:25 -0700337 * @param eventType type of event
338 * @param dbSchema ovsdb database schema
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700339 */
340 private void dispatchInterfaceEvent(OvsdbClientService clientService,
CNluciusa66c3972015-09-06 20:31:29 +0800341 Row row,
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700342 Type eventType,
343 DatabaseSchema dbSchema) {
344
345 long dpid = getDataPathid(clientService, dbSchema);
346 Interface intf = (Interface) TableGenerator
CNluciusa66c3972015-09-06 20:31:29 +0800347 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700348 if (intf == null) {
349 return;
350 }
351
352 String portType = (String) intf.getTypeColumn().data();
353 long localPort = getOfPort(intf);
354 if (localPort < 0) {
355 return;
356 }
357 String[] macAndIfaceId = getMacAndIfaceid(intf);
358 if (macAndIfaceId == null) {
359 return;
360 }
361
362 EventSubject eventSubject = new DefaultEventSubject(MacAddress.valueOf(
andreaed976a42015-10-05 14:38:25 -0700363 macAndIfaceId[0]),
kdarapufce5abb2018-05-10 19:37:53 +0530364 new HashSet<>(),
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700365 new OvsdbPortName(intf
andreaed976a42015-10-05 14:38:25 -0700366 .getName()),
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700367 new OvsdbPortNumber(localPort),
368 new OvsdbDatapathId(Long
andreaed976a42015-10-05 14:38:25 -0700369 .toString(dpid)),
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700370 new OvsdbPortType(portType),
371 new OvsdbIfaceId(macAndIfaceId[1]));
372 for (OvsdbEventListener listener : ovsdbEventListener) {
kdarapufce5abb2018-05-10 19:37:53 +0530373 listener.handle(new OvsdbEvent<>(eventType,
374 eventSubject));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700375 }
376 }
377
378 /**
379 * Gets mac and iface from the table Interface.
380 *
381 * @param intf Interface instance
382 * @return attachedMac, ifaceid
383 */
384 private String[] getMacAndIfaceid(Interface intf) {
385 OvsdbMap ovsdbMap = (OvsdbMap) intf.getExternalIdsColumn().data();
386 @SuppressWarnings("unchecked")
387 Map<String, String> externalIds = ovsdbMap.map();
388 if (externalIds == null) {
389 log.warn("The external_ids is null");
390 return null;
391 }
392
393 String attachedMac = externalIds.get(OvsdbConstant.EXTERNAL_ID_VM_MAC);
394 if (attachedMac == null) {
andreaed976a42015-10-05 14:38:25 -0700395 log.debug("The attachedMac is null"); //FIXME why always null?
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700396 return null;
397 }
398 String ifaceid = externalIds
399 .get(OvsdbConstant.EXTERNAL_ID_INTERFACE_ID);
400 if (ifaceid == null) {
401 log.warn("The ifaceid is null");
402 return null;
403 }
andreaed976a42015-10-05 14:38:25 -0700404 return new String[]{attachedMac, ifaceid};
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700405 }
406
407 /**
408 * Gets ofPorts number from table Interface.
409 *
410 * @param intf Interface instance
411 * @return ofport the ofport number
412 */
413 private long getOfPort(Interface intf) {
414 OvsdbSet ofPortSet = (OvsdbSet) intf.getOpenFlowPortColumn().data();
415 @SuppressWarnings("unchecked")
416 Set<Integer> ofPorts = ofPortSet.set();
Jon Hallb1f4e0f2017-02-22 13:36:16 -0800417 if (ofPorts == null || ofPorts.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700418 log.debug("The ofport is null in {}", intf.getName());
419 return -1;
420 }
421 Iterator<Integer> it = ofPorts.iterator();
422 return Long.parseLong(it.next().toString());
423 }
424
425 /**
426 * Gets datapathid from table bridge.
427 *
428 * @param clientService OvsdbClientService instance
andreaed976a42015-10-05 14:38:25 -0700429 * @param dbSchema ovsdb database schema
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700430 * @return datapathid the bridge datapathid
431 */
432 private long getDataPathid(OvsdbClientService clientService,
433 DatabaseSchema dbSchema) {
434 String bridgeUuid = clientService
435 .getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
436 if (bridgeUuid == null) {
437 log.debug("Unable to spot bridge uuid for {} in {}",
438 OvsdbConstant.INTEGRATION_BRIDGE, clientService);
439 return 0;
440 }
441
442 Row bridgeRow = clientService.getRow(OvsdbConstant.DATABASENAME,
443 "Bridge", bridgeUuid);
444 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
445 OvsdbTable.BRIDGE);
446 OvsdbSet dpidSet = (OvsdbSet) bridge.getDatapathIdColumn().data();
447 @SuppressWarnings("unchecked")
448 Set<String> dpids = dpidSet.set();
Jon Hallcbd1b392017-01-18 20:15:44 -0800449 if (dpids == null || dpids.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700450 return 0;
451 }
452 return stringToLong((String) dpids.toArray()[0]);
453 }
454
455 private long stringToLong(String values) {
456 long value = (new BigInteger(values.replaceAll(":", ""), 16))
457 .longValue();
458 return value;
459 }
460
Jian Lieaf31032018-05-03 15:54:03 +0900461 private void restartController() {
462 controller.stop();
463 controller.start(agent, updateCallback, serverMode);
464 }
465
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700466 /**
jiangruibce80652017-10-17 14:35:42 +0800467 * Implementation of an Ovsdb Agent which is responsible for keeping track
468 * of connected node and the state in which they are.
469 */
470 private class InternalOvsdbNodeAgent implements OvsdbAgent {
471 @Override
472 public void addConnectedNode(OvsdbNodeId nodeId,
473 OvsdbClientService ovsdbClient) {
474
475 if (ovsdbClients.get(nodeId) != null) {
476 ovsdbClient.disconnect();
477 return;
478 } else {
479
480 try {
481 List<String> dbNames = ovsdbClient.listDbs().get(DEFAULT_OVSDB_RPC_TIMEOUT, TimeUnit.MILLISECONDS);
482 for (String dbName : dbNames) {
483 DatabaseSchema dbSchema;
484 dbSchema = ovsdbClient.getOvsdbSchema(dbName)
485 .get(DEFAULT_OVSDB_RPC_TIMEOUT, TimeUnit.MILLISECONDS);
486
487 log.debug("Begin to monitor tables");
488 String id = java.util.UUID.randomUUID().toString();
489 TableUpdates updates = ovsdbClient
490 .monitorTables(dbName, id).get(DEFAULT_OVSDB_RPC_TIMEOUT, TimeUnit.MILLISECONDS);
491
492 requestDbName.put(id, dbName);
493 requestNotification.put(id, ovsdbClient);
494
495 if (updates != null) {
496 processTableUpdates(ovsdbClient, updates,
497 dbSchema.name());
498 }
499 }
500 } catch (InterruptedException e) {
501 log.warn("Interrupted while waiting to get message from ovsdb");
502 Thread.currentThread().interrupt();
503 return;
504 } catch (ExecutionException e) {
505 log.error("Exception thrown while to get message from ovsdb");
506 ovsdbClient.disconnect();
507 return;
508 } catch (TimeoutException e) {
509 log.error("TimeoutException thrown while to get message from ovsdb");
510 ovsdbClient.disconnect();
511 return;
512 }
513 ovsdbClients.put(nodeId, ovsdbClient);
514
515 log.debug("Add node to north");
516 for (OvsdbNodeListener l : ovsdbNodeListener) {
517 l.nodeAdded(nodeId);
518 }
519 return;
520 }
521 }
522
523 @Override
524 public void removeConnectedNode(OvsdbNodeId nodeId) {
tanbangchenge8d04392017-11-18 18:12:47 +0800525 requestNotification.forEach((k, v) -> {
526 if (v.nodeId().equals(nodeId)) {
527 requestNotification.remove(k);
528 requestDbName.remove(k);
529
530 ovsdbClients.remove(nodeId);
531 log.debug("Node connection is removed");
532 for (OvsdbNodeListener l : ovsdbNodeListener) {
533 l.nodeRemoved(nodeId);
534 }
535 }
536 });
jiangruibce80652017-10-17 14:35:42 +0800537 }
538 }
539
540 /**
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700541 * Implementation of an Callback which is responsible for receiving request
542 * infomation from ovsdb.
543 */
544 private class InternalMonitorCallBack implements Callback {
545 @Override
546 public void update(UpdateNotification updateNotification) {
547 Object key = updateNotification.jsonValue();
548 OvsdbClientService ovsdbClient = requestNotification.get(key);
549
550 String dbName = requestDbName.get(key);
551 JsonNode updatesJson = updateNotification.tbUpdatesJsonNode();
552 DatabaseSchema dbSchema = ovsdbClient.getDatabaseSchema(dbName);
553 TableUpdates updates = FromJsonUtil
554 .jsonNodeToTableUpdates(updatesJson, dbSchema);
555 try {
556 processTableUpdates(ovsdbClient, updates, dbName);
557 } catch (InterruptedException e) {
558 log.warn("Interrupted while processing table updates");
559 Thread.currentThread().interrupt();
560 }
561 }
562
563 @Override
564 public void locked(List<String> ids) {
565 // TODO Auto-generated method stub
566 }
567
568 @Override
569 public void stolen(List<String> ids) {
570 // TODO Auto-generated method stub
571 }
572
573 }
574
575}