blob: 11bfaae507766722ce8bf3136a84385d1efa90e8 [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.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
Jian Lieaf31032018-05-03 15:54:03 +090024import org.apache.felix.scr.annotations.Modified;
25import org.apache.felix.scr.annotations.Property;
26import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070028import org.apache.felix.scr.annotations.Service;
29import org.onlab.packet.IpAddress;
30import org.onlab.packet.MacAddress;
Hyunsun Moon5fb20a52015-09-25 17:02:33 -070031import org.onlab.packet.TpPort;
Jian Lieaf31032018-05-03 15:54:03 +090032import org.onlab.util.Tools;
33import org.onosproject.cfg.ComponentConfigService;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070034import org.onosproject.ovsdb.controller.DefaultEventSubject;
35import org.onosproject.ovsdb.controller.EventSubject;
36import org.onosproject.ovsdb.controller.OvsdbClientService;
37import org.onosproject.ovsdb.controller.OvsdbConstant;
38import org.onosproject.ovsdb.controller.OvsdbController;
39import org.onosproject.ovsdb.controller.OvsdbDatapathId;
40import org.onosproject.ovsdb.controller.OvsdbEvent;
41import org.onosproject.ovsdb.controller.OvsdbEvent.Type;
42import org.onosproject.ovsdb.controller.OvsdbEventListener;
43import org.onosproject.ovsdb.controller.OvsdbIfaceId;
44import org.onosproject.ovsdb.controller.OvsdbNodeId;
45import org.onosproject.ovsdb.controller.OvsdbNodeListener;
46import org.onosproject.ovsdb.controller.OvsdbPortName;
47import org.onosproject.ovsdb.controller.OvsdbPortNumber;
48import org.onosproject.ovsdb.controller.OvsdbPortType;
49import org.onosproject.ovsdb.controller.driver.OvsdbAgent;
debanshur37cf6ba2018-05-08 20:07:30 +053050import org.onosproject.ovsdb.controller.impl.TlsParams.TlsMode;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070051import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
52import org.onosproject.ovsdb.rfc.message.TableUpdate;
53import org.onosproject.ovsdb.rfc.message.TableUpdates;
54import org.onosproject.ovsdb.rfc.message.UpdateNotification;
55import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
56import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
57import org.onosproject.ovsdb.rfc.notation.Row;
Jonathan Hart51539b82015-10-29 09:53:04 -070058import org.onosproject.ovsdb.rfc.notation.Uuid;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070059import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
60import org.onosproject.ovsdb.rfc.table.Bridge;
61import org.onosproject.ovsdb.rfc.table.Interface;
62import org.onosproject.ovsdb.rfc.table.OvsdbTable;
63import org.onosproject.ovsdb.rfc.table.TableGenerator;
64import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
65import org.osgi.service.component.ComponentContext;
66import org.slf4j.Logger;
67import org.slf4j.LoggerFactory;
68
andreaed976a42015-10-05 14:38:25 -070069import java.math.BigInteger;
Jian Lieaf31032018-05-03 15:54:03 +090070import java.util.Dictionary;
andreaed976a42015-10-05 14:38:25 -070071import java.util.HashSet;
72import java.util.Iterator;
73import java.util.List;
74import java.util.Map;
debanshur37cf6ba2018-05-08 20:07:30 +053075import java.util.Objects;
andreaed976a42015-10-05 14:38:25 -070076import java.util.Set;
77import java.util.concurrent.ConcurrentHashMap;
78import java.util.concurrent.CopyOnWriteArraySet;
79import java.util.concurrent.ExecutionException;
jiangruibce80652017-10-17 14:35:42 +080080import java.util.concurrent.TimeUnit;
81import java.util.concurrent.TimeoutException;
jaegonkim1af0ae52017-01-01 10:46:55 +090082import java.util.function.Consumer;
andreaed976a42015-10-05 14:38:25 -070083
84import static com.google.common.base.Preconditions.checkNotNull;
debanshur37cf6ba2018-05-08 20:07:30 +053085import static org.onlab.util.Tools.get;
Jian Lieaf31032018-05-03 15:54:03 +090086import static org.onosproject.ovsdb.controller.OvsdbConstant.SERVER_MODE;
debanshur37cf6ba2018-05-08 20:07:30 +053087import static org.onosproject.ovsdb.controller.OvsdbConstant.DEFAULT_KS_PASSWORD;
88import static org.onosproject.ovsdb.controller.OvsdbConstant.DEFAULT_KS_FILE;
89import static org.onosproject.ovsdb.controller.OvsdbConstant.OVSDB_TLS_FLAG;
90import static org.onosproject.ovsdb.controller.impl.Controller.MIN_KS_LENGTH;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070091
92/**
93 * The implementation of OvsdbController.
94 */
95@Component(immediate = true)
96@Service
97public class OvsdbControllerImpl implements OvsdbController {
98
99 public static final Logger log = LoggerFactory
100 .getLogger(OvsdbControllerImpl.class);
jiangruibce80652017-10-17 14:35:42 +0800101 private static final long DEFAULT_OVSDB_RPC_TIMEOUT = 3000;
102 private final Controller controller = new Controller();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700103 protected ConcurrentHashMap<OvsdbNodeId, OvsdbClientService> ovsdbClients =
kdarapufce5abb2018-05-10 19:37:53 +0530104 new ConcurrentHashMap<>();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700105 protected OvsdbAgent agent = new InternalOvsdbNodeAgent();
106 protected InternalMonitorCallBack updateCallback = new InternalMonitorCallBack();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700107 protected Set<OvsdbNodeListener> ovsdbNodeListener = new CopyOnWriteArraySet<>();
108 protected Set<OvsdbEventListener> ovsdbEventListener = new CopyOnWriteArraySet<>();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700109 protected ConcurrentHashMap<String, OvsdbClientService> requestNotification =
kdarapufce5abb2018-05-10 19:37:53 +0530110 new ConcurrentHashMap<>();
111 protected ConcurrentHashMap<String, String> requestDbName = new ConcurrentHashMap<>();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700112
Jian Lieaf31032018-05-03 15:54:03 +0900113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected ComponentConfigService configService;
115
116 @Property(name = "serverMode", boolValue = SERVER_MODE,
117 label = "Run as server mode, listen on 6640 port")
118 private boolean serverMode = SERVER_MODE;
119
debanshur37cf6ba2018-05-08 20:07:30 +0530120 @Property(name = "enableOvsdbTls", boolValue = OVSDB_TLS_FLAG,
121 label = "TLS mode for OVSDB channel; options are: true false")
122 private boolean enableOvsdbTls = OVSDB_TLS_FLAG;
123
124 @Property(name = "keyStoreLocation", value = DEFAULT_KS_FILE,
125 label = "File path to KeyStore for Ovsdb TLS Connections")
126 protected String keyStoreLocation = DEFAULT_KS_FILE;
127
128 @Property(name = "trustStoreLocation", value = DEFAULT_KS_FILE,
129 label = "File path to TrustStore for Ovsdb TLS Connections")
130 protected String trustStoreLocation = DEFAULT_KS_FILE;
131
132 @Property(name = "keyStorePassword", value = DEFAULT_KS_PASSWORD,
133 label = "KeyStore Password")
134 protected String keyStorePassword = DEFAULT_KS_PASSWORD;
135
136 @Property(name = "trustStorePassword", value = DEFAULT_KS_PASSWORD,
137 label = "TrustStore Password")
138 protected String trustStorePassword = DEFAULT_KS_PASSWORD;
139
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700140 @Activate
141 public void activate(ComponentContext context) {
Jian Lieaf31032018-05-03 15:54:03 +0900142 configService.registerProperties(getClass());
debanshur37cf6ba2018-05-08 20:07:30 +0530143 modified(context);
144 controller.start(agent, updateCallback, serverMode);
Jian Lieaf31032018-05-03 15:54:03 +0900145
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700146 log.info("Started");
147 }
148
149 @Deactivate
150 public void deactivate() {
151 controller.stop();
Jian Lieaf31032018-05-03 15:54:03 +0900152
153 configService.unregisterProperties(getClass(), false);
154
debanshur37cf6ba2018-05-08 20:07:30 +0530155 log.info("Stopped");
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700156 }
157
Jian Lieaf31032018-05-03 15:54:03 +0900158 @Modified
159 protected void modified(ComponentContext context) {
debanshur37cf6ba2018-05-08 20:07:30 +0530160 this.setConfigParams(context.getProperties());
161 }
Jian Lieaf31032018-05-03 15:54:03 +0900162
debanshur37cf6ba2018-05-08 20:07:30 +0530163 /**
164 * Sets config params.
165 *
166 * @param properties dictionary
167 */
168 public void setConfigParams(Dictionary<?, ?> properties) {
169 boolean restartRequired = setServerMode(properties);
170 TlsParams tlsParams = getTlsParams(properties);
171 restartRequired |= controller.setTlsParameters(tlsParams);
172 if (restartRequired) {
173 restartController();
174 }
175 }
176
177 /**
178 * Gets the TLS parameters from the properties dict.
179 *
180 * @param properties dictionary
181 * @return TlsParams Modified Tls Params
182 */
183 private TlsParams getTlsParams(Dictionary<?, ?> properties) {
184 TlsMode mode = null;
185
186 boolean flag = Tools.isPropertyEnabled(properties, "enableOvsdbTls");
187 if (Objects.isNull(flag) || !flag) {
188 log.warn("OvsdbTLS Disabled");
189 mode = TlsMode.DISABLED;
190 } else {
191 log.warn("OvsdbTLS Enabled");
192 mode = TlsMode.ENABLED;
193 }
194
195 String ksLocation = null, tsLocation = null, ksPwd = null, tsPwd = null;
196
197 ksLocation = get(properties, "keyStoreLocation");
198 if (Strings.isNullOrEmpty(ksLocation)) {
199 log.warn("trustStoreLocation is not configured");
200 mode = TlsMode.DISABLED;
201 }
202
203 tsLocation = get(properties, "trustStoreLocation");
204 if (Strings.isNullOrEmpty(tsLocation)) {
205 log.warn("trustStoreLocation is not configured");
206 mode = TlsMode.DISABLED;
207 }
208
209 ksPwd = get(properties, "keyStorePassword");
210 if (Strings.isNullOrEmpty(ksPwd) || MIN_KS_LENGTH > ksPwd.length()) {
211 log.warn("keyStorePassword is not configured or Password length too small");
212 mode = TlsMode.DISABLED;
213 }
214
215 tsPwd = get(properties, "trustStorePassword");
216 if (Strings.isNullOrEmpty(tsPwd) || MIN_KS_LENGTH > tsPwd.length()) {
217 log.warn("trustStorePassword is not configured or Password length too small");
218 mode = TlsMode.DISABLED;
219 }
220
221 TlsParams tlsParams = new TlsParams(mode, ksLocation, tsLocation, ksPwd, tsPwd);
222 log.info("OVSDB TLS Params: {}", tlsParams);
223 return tlsParams;
224 }
225
226 private boolean setServerMode(Dictionary<?, ?> properties) {
227 boolean flag = Tools.isPropertyEnabled(properties, "serverMode");
228 if (Objects.isNull(flag) || flag == serverMode) {
229 log.info("Ovsdb server mode is not configured, " +
230 "or modified. Using current value of {}", serverMode);
231 return false;
Jian Lieaf31032018-05-03 15:54:03 +0900232 } else {
233 serverMode = flag;
234 log.info("Configured. OVSDB server mode was {}",
debanshur37cf6ba2018-05-08 20:07:30 +0530235 serverMode ? "enabled" : "disabled");
236 return true;
Jian Lieaf31032018-05-03 15:54:03 +0900237 }
238
Jian Lieaf31032018-05-03 15:54:03 +0900239 }
240
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700241 @Override
242 public void addNodeListener(OvsdbNodeListener listener) {
243 if (!ovsdbNodeListener.contains(listener)) {
244 this.ovsdbNodeListener.add(listener);
245 }
246 }
247
248 @Override
249 public void removeNodeListener(OvsdbNodeListener listener) {
250 this.ovsdbNodeListener.remove(listener);
251 }
252
253 @Override
254 public void addOvsdbEventListener(OvsdbEventListener listener) {
255 if (!ovsdbEventListener.contains(listener)) {
256 this.ovsdbEventListener.add(listener);
257 }
258 }
259
260 @Override
261 public void removeOvsdbEventListener(OvsdbEventListener listener) {
262 this.ovsdbEventListener.remove(listener);
263 }
264
265 @Override
266 public List<OvsdbNodeId> getNodeIds() {
andreaed976a42015-10-05 14:38:25 -0700267 return ImmutableList.copyOf(ovsdbClients.keySet());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700268 }
269
270 @Override
271 public OvsdbClientService getOvsdbClient(OvsdbNodeId nodeId) {
272 return ovsdbClients.get(nodeId);
273 }
274
Hyunsun Moon5fb20a52015-09-25 17:02:33 -0700275 @Override
276 public void connect(IpAddress ip, TpPort port) {
277 controller.connect(ip, port);
278 }
279
jaegonkim1af0ae52017-01-01 10:46:55 +0900280 @Override
281 public void connect(IpAddress ip, TpPort port, Consumer<Exception> failhandler) {
282 controller.connect(ip, port, failhandler);
283 }
284
Jian Lieaf31032018-05-03 15:54:03 +0900285 @Override
286 public void setServerMode(boolean serverMode) {
287 this.serverMode = serverMode;
288 restartController();
289 }
290
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700291 /**
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700292 * Processes table updates.
293 *
294 * @param clientService OvsdbClientService instance
andreaed976a42015-10-05 14:38:25 -0700295 * @param updates TableUpdates instance
296 * @param dbName ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700297 */
298 private void processTableUpdates(OvsdbClientService clientService,
299 TableUpdates updates, String dbName)
300 throws InterruptedException {
301 checkNotNull(clientService, "OvsdbClientService is not null");
302
303 DatabaseSchema dbSchema = clientService.getDatabaseSchema(dbName);
304
305 for (String tableName : updates.result().keySet()) {
306 TableUpdate update = updates.result().get(tableName);
Jonathan Hart51539b82015-10-29 09:53:04 -0700307 for (Uuid uuid : (Set<Uuid>) update.rows().keySet()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700308 log.debug("Begin to process table updates uuid: {}, databaseName: {}, tableName: {}",
309 uuid.value(), dbName, tableName);
310
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700311 Row newRow = update.getNew(uuid);
312 if (newRow != null) {
313 clientService.updateOvsdbStore(dbName, tableName,
314 uuid.value(), newRow);
315
316 if (OvsdbConstant.INTERFACE.equals(tableName)) {
317 dispatchInterfaceEvent(clientService,
CNluciusa66c3972015-09-06 20:31:29 +0800318 newRow,
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700319 OvsdbEvent.Type.PORT_ADDED,
320 dbSchema);
321 }
322 } else if (update.getOld(uuid) != null) {
CNluciusa66c3972015-09-06 20:31:29 +0800323 if (OvsdbConstant.INTERFACE.equals(tableName)) {
324 Row row = clientService.getRow(OvsdbConstant.DATABASENAME, tableName, uuid.value());
325 dispatchInterfaceEvent(clientService,
326 row,
andreaed976a42015-10-05 14:38:25 -0700327 OvsdbEvent.Type.PORT_REMOVED,
328 dbSchema);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700329 }
CNluciusa66c3972015-09-06 20:31:29 +0800330 clientService.removeRow(dbName, tableName, uuid.value());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700331 }
332 }
333 }
334 }
335
336 /**
337 * Dispatches event to the north.
338 *
339 * @param clientService OvsdbClientService instance
tanbangchenge8d04392017-11-18 18:12:47 +0800340 * @param row a new row
andreaed976a42015-10-05 14:38:25 -0700341 * @param eventType type of event
342 * @param dbSchema ovsdb database schema
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700343 */
344 private void dispatchInterfaceEvent(OvsdbClientService clientService,
CNluciusa66c3972015-09-06 20:31:29 +0800345 Row row,
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700346 Type eventType,
347 DatabaseSchema dbSchema) {
348
349 long dpid = getDataPathid(clientService, dbSchema);
350 Interface intf = (Interface) TableGenerator
CNluciusa66c3972015-09-06 20:31:29 +0800351 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700352 if (intf == null) {
353 return;
354 }
355
356 String portType = (String) intf.getTypeColumn().data();
357 long localPort = getOfPort(intf);
358 if (localPort < 0) {
359 return;
360 }
361 String[] macAndIfaceId = getMacAndIfaceid(intf);
362 if (macAndIfaceId == null) {
363 return;
364 }
365
366 EventSubject eventSubject = new DefaultEventSubject(MacAddress.valueOf(
andreaed976a42015-10-05 14:38:25 -0700367 macAndIfaceId[0]),
kdarapufce5abb2018-05-10 19:37:53 +0530368 new HashSet<>(),
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700369 new OvsdbPortName(intf
andreaed976a42015-10-05 14:38:25 -0700370 .getName()),
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700371 new OvsdbPortNumber(localPort),
372 new OvsdbDatapathId(Long
andreaed976a42015-10-05 14:38:25 -0700373 .toString(dpid)),
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700374 new OvsdbPortType(portType),
375 new OvsdbIfaceId(macAndIfaceId[1]));
376 for (OvsdbEventListener listener : ovsdbEventListener) {
kdarapufce5abb2018-05-10 19:37:53 +0530377 listener.handle(new OvsdbEvent<>(eventType,
378 eventSubject));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700379 }
380 }
381
382 /**
383 * Gets mac and iface from the table Interface.
384 *
385 * @param intf Interface instance
386 * @return attachedMac, ifaceid
387 */
388 private String[] getMacAndIfaceid(Interface intf) {
389 OvsdbMap ovsdbMap = (OvsdbMap) intf.getExternalIdsColumn().data();
390 @SuppressWarnings("unchecked")
391 Map<String, String> externalIds = ovsdbMap.map();
392 if (externalIds == null) {
393 log.warn("The external_ids is null");
394 return null;
395 }
396
397 String attachedMac = externalIds.get(OvsdbConstant.EXTERNAL_ID_VM_MAC);
398 if (attachedMac == null) {
andreaed976a42015-10-05 14:38:25 -0700399 log.debug("The attachedMac is null"); //FIXME why always null?
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700400 return null;
401 }
402 String ifaceid = externalIds
403 .get(OvsdbConstant.EXTERNAL_ID_INTERFACE_ID);
404 if (ifaceid == null) {
405 log.warn("The ifaceid is null");
406 return null;
407 }
andreaed976a42015-10-05 14:38:25 -0700408 return new String[]{attachedMac, ifaceid};
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700409 }
410
411 /**
412 * Gets ofPorts number from table Interface.
413 *
414 * @param intf Interface instance
415 * @return ofport the ofport number
416 */
417 private long getOfPort(Interface intf) {
418 OvsdbSet ofPortSet = (OvsdbSet) intf.getOpenFlowPortColumn().data();
419 @SuppressWarnings("unchecked")
420 Set<Integer> ofPorts = ofPortSet.set();
Jon Hallb1f4e0f2017-02-22 13:36:16 -0800421 if (ofPorts == null || ofPorts.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700422 log.debug("The ofport is null in {}", intf.getName());
423 return -1;
424 }
425 Iterator<Integer> it = ofPorts.iterator();
426 return Long.parseLong(it.next().toString());
427 }
428
429 /**
430 * Gets datapathid from table bridge.
431 *
432 * @param clientService OvsdbClientService instance
andreaed976a42015-10-05 14:38:25 -0700433 * @param dbSchema ovsdb database schema
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700434 * @return datapathid the bridge datapathid
435 */
436 private long getDataPathid(OvsdbClientService clientService,
437 DatabaseSchema dbSchema) {
438 String bridgeUuid = clientService
439 .getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
440 if (bridgeUuid == null) {
441 log.debug("Unable to spot bridge uuid for {} in {}",
442 OvsdbConstant.INTEGRATION_BRIDGE, clientService);
443 return 0;
444 }
445
446 Row bridgeRow = clientService.getRow(OvsdbConstant.DATABASENAME,
447 "Bridge", bridgeUuid);
448 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
449 OvsdbTable.BRIDGE);
450 OvsdbSet dpidSet = (OvsdbSet) bridge.getDatapathIdColumn().data();
451 @SuppressWarnings("unchecked")
452 Set<String> dpids = dpidSet.set();
Jon Hallcbd1b392017-01-18 20:15:44 -0800453 if (dpids == null || dpids.isEmpty()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700454 return 0;
455 }
456 return stringToLong((String) dpids.toArray()[0]);
457 }
458
459 private long stringToLong(String values) {
460 long value = (new BigInteger(values.replaceAll(":", ""), 16))
461 .longValue();
462 return value;
463 }
464
Jian Lieaf31032018-05-03 15:54:03 +0900465 private void restartController() {
466 controller.stop();
467 controller.start(agent, updateCallback, serverMode);
468 }
469
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700470 /**
jiangruibce80652017-10-17 14:35:42 +0800471 * Implementation of an Ovsdb Agent which is responsible for keeping track
472 * of connected node and the state in which they are.
473 */
474 private class InternalOvsdbNodeAgent implements OvsdbAgent {
475 @Override
476 public void addConnectedNode(OvsdbNodeId nodeId,
477 OvsdbClientService ovsdbClient) {
478
479 if (ovsdbClients.get(nodeId) != null) {
480 ovsdbClient.disconnect();
481 return;
482 } else {
483
484 try {
485 List<String> dbNames = ovsdbClient.listDbs().get(DEFAULT_OVSDB_RPC_TIMEOUT, TimeUnit.MILLISECONDS);
486 for (String dbName : dbNames) {
487 DatabaseSchema dbSchema;
488 dbSchema = ovsdbClient.getOvsdbSchema(dbName)
489 .get(DEFAULT_OVSDB_RPC_TIMEOUT, TimeUnit.MILLISECONDS);
490
491 log.debug("Begin to monitor tables");
492 String id = java.util.UUID.randomUUID().toString();
493 TableUpdates updates = ovsdbClient
494 .monitorTables(dbName, id).get(DEFAULT_OVSDB_RPC_TIMEOUT, TimeUnit.MILLISECONDS);
495
496 requestDbName.put(id, dbName);
497 requestNotification.put(id, ovsdbClient);
498
499 if (updates != null) {
500 processTableUpdates(ovsdbClient, updates,
501 dbSchema.name());
502 }
503 }
504 } catch (InterruptedException e) {
505 log.warn("Interrupted while waiting to get message from ovsdb");
506 Thread.currentThread().interrupt();
507 return;
508 } catch (ExecutionException e) {
509 log.error("Exception thrown while to get message from ovsdb");
510 ovsdbClient.disconnect();
511 return;
512 } catch (TimeoutException e) {
513 log.error("TimeoutException thrown while to get message from ovsdb");
514 ovsdbClient.disconnect();
515 return;
516 }
517 ovsdbClients.put(nodeId, ovsdbClient);
518
519 log.debug("Add node to north");
520 for (OvsdbNodeListener l : ovsdbNodeListener) {
521 l.nodeAdded(nodeId);
522 }
523 return;
524 }
525 }
526
527 @Override
528 public void removeConnectedNode(OvsdbNodeId nodeId) {
tanbangchenge8d04392017-11-18 18:12:47 +0800529 requestNotification.forEach((k, v) -> {
530 if (v.nodeId().equals(nodeId)) {
531 requestNotification.remove(k);
532 requestDbName.remove(k);
533
534 ovsdbClients.remove(nodeId);
535 log.debug("Node connection is removed");
536 for (OvsdbNodeListener l : ovsdbNodeListener) {
537 l.nodeRemoved(nodeId);
538 }
539 }
540 });
jiangruibce80652017-10-17 14:35:42 +0800541 }
542 }
543
544 /**
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700545 * Implementation of an Callback which is responsible for receiving request
546 * infomation from ovsdb.
547 */
548 private class InternalMonitorCallBack implements Callback {
549 @Override
550 public void update(UpdateNotification updateNotification) {
551 Object key = updateNotification.jsonValue();
552 OvsdbClientService ovsdbClient = requestNotification.get(key);
553
554 String dbName = requestDbName.get(key);
555 JsonNode updatesJson = updateNotification.tbUpdatesJsonNode();
556 DatabaseSchema dbSchema = ovsdbClient.getDatabaseSchema(dbName);
557 TableUpdates updates = FromJsonUtil
558 .jsonNodeToTableUpdates(updatesJson, dbSchema);
559 try {
560 processTableUpdates(ovsdbClient, updates, dbName);
561 } catch (InterruptedException e) {
562 log.warn("Interrupted while processing table updates");
563 Thread.currentThread().interrupt();
564 }
565 }
566
567 @Override
568 public void locked(List<String> ids) {
569 // TODO Auto-generated method stub
570 }
571
572 @Override
573 public void stolen(List<String> ids) {
574 // TODO Auto-generated method stub
575 }
576
577 }
578
579}