Use Java declarations instead of Google Collections
[netvirt.git] / openstack / net-virt / src / main / java / org / opendaylight / netvirt / openstack / netvirt / impl / BridgeConfigurationManagerImpl.java
1 /*
2  * Copyright (c) 2013, 2015 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.openstack.netvirt.impl;
10
11 import com.google.common.base.Preconditions;
12 import java.net.InetAddress;
13 import java.net.NetworkInterface;
14 import java.net.UnknownHostException;
15 import java.util.ArrayList;
16 import java.util.Enumeration;
17 import java.util.List;
18 import java.util.Random;
19 import java.util.stream.Collectors;
20 import org.apache.commons.lang3.tuple.ImmutablePair;
21 import org.opendaylight.netvirt.openstack.netvirt.ConfigInterface;
22 import org.opendaylight.netvirt.openstack.netvirt.MdsalHelper;
23 import org.opendaylight.netvirt.openstack.netvirt.NetworkHandler;
24 import org.opendaylight.netvirt.openstack.netvirt.api.BridgeConfigurationManager;
25 import org.opendaylight.netvirt.openstack.netvirt.api.ConfigurationService;
26 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
27 import org.opendaylight.netvirt.openstack.netvirt.api.NetworkingProviderManager;
28 import org.opendaylight.netvirt.openstack.netvirt.api.OvsdbTables;
29 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
30 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronNetwork;
31 import org.opendaylight.netvirt.utils.config.ConfigProperties;
32 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
39 import org.osgi.framework.ServiceReference;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * @author Madhu Venugopal
45  * @author Brent Salisbury
46  * @author Sam Hague (shague@redhat.com)
47  */
48 public class BridgeConfigurationManagerImpl implements BridgeConfigurationManager, ConfigInterface {
49     private static final Logger LOG = LoggerFactory.getLogger(BridgeConfigurationManagerImpl.class);
50
51     // The implementation for each of these services is resolved by the OSGi Service Manager
52     private volatile ConfigurationService configurationService;
53     private volatile NetworkingProviderManager networkingProviderManager;
54     private volatile Southbound southbound;
55     private boolean intBridgeGenMac;
56     private Random random;
57
58     public BridgeConfigurationManagerImpl() {
59         this(true);
60     }
61
62     public BridgeConfigurationManagerImpl(boolean intBridgeGenMac) {
63         this.intBridgeGenMac = intBridgeGenMac;
64         this.random = new Random(System.currentTimeMillis());
65     }
66
67     public void setConfigurationService(ConfigurationService configurationService) {
68         this.configurationService = configurationService;
69     }
70
71     public void setSouthbound(Southbound southbound) {
72         this.southbound = southbound;
73     }
74
75     @Override
76     public String getBridgeUuid(Node node, String bridgeName) {
77         return southbound.getBridgeUuid(node, bridgeName);
78     }
79
80     @Override
81     public boolean isNodeNeutronReady(Node node) {
82         Preconditions.checkNotNull(configurationService);
83         return southbound.getBridge(node, configurationService.getIntegrationBridgeName()) != null;
84     }
85
86     @Override
87     public boolean isNodeOverlayReady(Node node) {
88         Preconditions.checkNotNull(configurationService);
89         return isNodeNeutronReady(node)
90                 && southbound.getBridge(node, configurationService.getNetworkBridgeName()) != null;
91     }
92
93     @Override
94     public boolean isPortOnBridge (Node bridgeNode, String portName) {
95         return southbound.extractTerminationPointAugmentation(bridgeNode, portName) != null;
96     }
97
98     @Override
99     public boolean isNodeTunnelReady(Node bridgeNode, Node ovsdbNode) {
100         Preconditions.checkNotNull(configurationService);
101         if (!southbound.isBridgeOnOvsdbNode(ovsdbNode, configurationService.getIntegrationBridgeName())) {
102             LOG.trace("isNodeTunnelReady: node: {}, {} missing",
103                     bridgeNode, configurationService.getIntegrationBridgeName());
104             return false;
105         }
106
107         return isNodeL3Ready(bridgeNode, ovsdbNode);
108     }
109
110     @Override
111     public boolean isNodeVlanReady(Node bridgeNode, Node ovsdbNode, NeutronNetwork network) {
112         Preconditions.checkNotNull(configurationService);
113
114         final String brInt = configurationService.getIntegrationBridgeName();
115         if (!southbound.isBridgeOnOvsdbNode(ovsdbNode, brInt)) {
116             LOG.trace("isNodeVlanReady: node: {}, {} missing", bridgeNode, brInt);
117             return false;
118         }
119
120         /* Check if physical device is added to br-int. */
121         String phyNetName = getPhysicalInterfaceName(ovsdbNode, network.getProviderPhysicalNetwork());
122         if (!isPortOnBridge(bridgeNode, phyNetName)) {
123             LOG.trace("isNodeVlanReady: node: {}, eth missing", bridgeNode);
124             return false;
125         }
126
127         return isNodeL3Ready(bridgeNode, ovsdbNode);
128     }
129
130     public boolean isNodeL3Ready(Node bridgeNode, Node ovsdbNode) {
131         Preconditions.checkNotNull(configurationService);
132         boolean ready = false;
133         if (configurationService.isL3ForwardingEnabled()) {
134             final String brInt = configurationService.getIntegrationBridgeName();
135             final String brExt = configurationService.getExternalBridgeName();
136             final String portNameInt = configurationService.getPatchPortName(new ImmutablePair<>(brInt, brExt));
137             final String portNameExt = configurationService.getPatchPortName(new ImmutablePair<>(brExt, brInt));
138             Preconditions.checkNotNull(portNameInt);
139             Preconditions.checkNotNull(portNameExt);
140
141             if (southbound.isBridgeOnOvsdbNode(ovsdbNode, brExt)) {
142                 ready = isNetworkPatchCreated(bridgeNode, southbound.readBridgeNode(ovsdbNode, brExt));
143             } else {
144                 LOG.trace("isNodeL3Ready: node: {}, {} missing",
145                         bridgeNode, brExt);
146             }
147         } else {
148             ready = true;
149         }
150         return ready;
151     }
152
153     @Override
154     public void prepareNode(Node ovsdbNode) {
155         Preconditions.checkNotNull(configurationService);
156
157         try {
158             createIntegrationBridge(ovsdbNode);
159         } catch (Exception e) {
160             LOG.error("Error creating Integration Bridge on {}", ovsdbNode, e);
161             return;
162         }
163
164         try {
165             if (configurationService.isL3ForwardingEnabled()) {
166                 createExternalBridge(ovsdbNode);
167             } else if (configurationService.isL3MultipleExternalNetworkEnabled()) {
168                 String brExt = getMultipleExternalBridge(ovsdbNode);
169                 if (brExt == null) {
170                     LOG.warn("The provider mapping external network bridge name is null");
171                     return;
172                 }
173                 //get external bridge
174                 Node extBridgeNode = southbound.readBridgeNode(ovsdbNode, brExt);
175                 LOG.trace("External bridge details in operational data store:extBridgeNode:{}", extBridgeNode);
176                 if (extBridgeNode == null) {
177                     LOG.warn("External bridge is not created:{}", brExt);
178                     return;
179                 }
180                 //get internal bridge
181                 String brInt = configurationService.getIntegrationBridgeName();
182                 if (!addBridge(ovsdbNode, brExt, null)) {
183                     LOG.warn("Multiple External Bridge Creation failed");
184                     return;
185                 }
186                 configurationService.setExternalBridgeName(brExt);
187                 Node internalOvsdbNode = southbound.readConfigBridge(ovsdbNode, brInt);
188                 LOG.trace("Internal bridge details in config data store:internalOvsdbNode:{}", internalOvsdbNode);
189                 if (internalOvsdbNode == null) {
190                     LOG.warn("Internal Bridge is null in config datastore:{}", brInt);
191                     return;
192                 }
193                 //Processing an external bridge
194                 String portNameExt = null;
195                 if (brExt.contains("-")) {
196                     String[] brExt_Ex = brExt.split("-");
197                     portNameExt = Constants.MULTIPLE_NETWORK_L3_PATCH.concat("-").concat(brExt_Ex[1]);
198                 } else {
199                     portNameExt = Constants.MULTIPLE_NETWORK_L3_PATCH.concat("-").concat(brExt);
200                 }
201                 LOG.trace("prepareNode: portNameExt:{}", portNameExt);
202                 final String portNameInt = "patch-int";
203                 Preconditions.checkNotNull(portNameInt);
204                 Preconditions.checkNotNull(portNameExt);
205                 if (!addPatchPort(internalOvsdbNode, brInt, portNameExt, portNameInt)) {
206                     LOG.error("Add Port {} to Bridge {} failed", portNameInt, brInt);
207                     return;
208                 }
209                 configurationService.addPatchPortName(new ImmutablePair<>(brInt, brExt), portNameExt);
210                 if (!addPatchPort(extBridgeNode, brExt, portNameInt, portNameExt)) {
211                     LOG.error("Add Port {} to Bridge {} failed", portNameExt, brExt);
212                     return;
213                 }
214                 configurationService.addPatchPortName(new ImmutablePair<>(brExt, brInt), portNameInt);
215                 LOG.info("Multiple external bridge is successfully created:{}", brExt);
216             }
217         } catch (Exception e) {
218             LOG.error("Error creating External Bridge on {}", ovsdbNode, e);
219             return;
220         }
221         // this node is an ovsdb node so it doesn't have a bridge
222         // so either look up the bridges or just wait for the bridge update to come in
223         // and add the flows there.
224         //networkingProviderManager.getProvider(node).initializeFlowRules(node);
225     }
226
227     /**
228      * Check if the full network setup is available. If not, create it.
229      */
230     @Override
231     public boolean createLocalNetwork (Node bridgeNode, NeutronNetwork network) {
232         boolean isCreated = false;
233         Node ovsdbNode = southbound.readOvsdbNode(bridgeNode);
234         if (ovsdbNode == null) {
235             //this should never happen
236             LOG.error("createLocalNetwork could not find ovsdbNode from bridge node {}", bridgeNode);
237             return false;
238         }
239         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
240             if (!isNodeVlanReady(bridgeNode, ovsdbNode, network)) {
241                 try {
242                     isCreated = createBridges(bridgeNode, ovsdbNode, network);
243                 } catch (Exception e) {
244                     LOG.error("Error creating internal vlan net network {}--{}", bridgeNode, network, e);
245                 }
246             } else {
247                 isCreated = true;
248             }
249         } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
250                    network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
251             if (!isNodeTunnelReady(bridgeNode, ovsdbNode)) {
252                 try {
253                     isCreated = createBridges(bridgeNode, ovsdbNode, network);
254                 } catch (Exception e) {
255                     LOG.error("Error creating internal vxlan/gre net network {}--{}", bridgeNode, network, e);
256                 }
257             } else {
258                 isCreated = true;
259             }
260         }
261         return isCreated;
262     }
263
264
265
266     @Override
267     public String getExternalInterfaceName (Node node, String extNetwork) {
268         String phyIf = null;
269         String providerMaps = southbound.getOtherConfig(node, OvsdbTables.OPENVSWITCH,
270                 configurationService.getProviderMappingsKey());
271         if (providerMaps != null) {
272             for (String map : providerMaps.split(",")) {
273                 String[] pair = map.split(":");
274                 if (pair[0].equals(extNetwork)) {
275                     phyIf = pair[1];
276                     break;
277                 }
278             }
279         }
280         if (phyIf == null) {
281             LOG.error("External interface not found for Node: {}, Network {}",
282                     node, extNetwork);
283         }
284         else {
285             LOG.info("External interface found for Node: {}, Network {} is {}",node,extNetwork,phyIf);
286         }
287         return phyIf;
288     }
289
290
291
292     @Override
293     public String getPhysicalInterfaceName (Node node, String physicalNetwork) {
294         String phyIf = null;
295         String providerMaps = southbound.getOtherConfig(node, OvsdbTables.OPENVSWITCH,
296                 configurationService.getProviderMappingsKey());
297         if (providerMaps == null) {
298             providerMaps = configurationService.getDefaultProviderMapping();
299         }
300
301         if (providerMaps != null) {
302             for (String map : providerMaps.split(",")) {
303                 String[] pair = map.split(":");
304                 if (pair[0].equals(physicalNetwork)) {
305                     phyIf = pair[1];
306                     break;
307                 }
308             }
309         }
310
311         if (phyIf == null) {
312             LOG.error("Physical interface not found for Node: {}, Network {}",
313                     node, physicalNetwork);
314         }
315
316         return phyIf;
317     }
318
319     @Override
320     public List<String> getAllPhysicalInterfaceNames(Node node) {
321         List<String> phyIfNames = new ArrayList<>();
322         String providerMaps = southbound.getOtherConfig(node, OvsdbTables.OPENVSWITCH,
323                 configurationService.getProviderMappingsKey());
324         if (providerMaps == null) {
325             if (configurationService.isL3MultipleExternalNetworkEnabled()) {
326                 return phyIfNames;
327             }
328             providerMaps = configurationService.getDefaultProviderMapping();
329         }
330
331         if (providerMaps != null) {
332             for (String map : providerMaps.split(",")) {
333                 String[] pair = map.split(":");
334                 phyIfNames.add(pair[1]);
335             }
336         }
337
338         return phyIfNames;
339     }
340
341     /**
342      * Returns true if a patch port exists between the Integration Bridge and Network Bridge
343      */
344     private boolean isNetworkPatchCreated(Node intBridge, Node netBridge) {
345         Preconditions.checkNotNull(configurationService);
346
347         boolean isPatchCreated = false;
348
349         String portName = configurationService.getPatchPortName(new ImmutablePair<>(intBridge, netBridge));
350         if (isPortOnBridge(intBridge, portName)) {
351             portName = configurationService.getPatchPortName(new ImmutablePair<>(netBridge, intBridge));
352             if (isPortOnBridge(netBridge, portName)) {
353                 isPatchCreated = true;
354             }
355         }
356
357         return isPatchCreated;
358     }
359
360     /**
361      * Creates the Integration Bridge
362      */
363     private boolean createIntegrationBridge(Node ovsdbNode) {
364         Preconditions.checkNotNull(configurationService);
365
366         if (!addBridge(ovsdbNode, configurationService.getIntegrationBridgeName(),
367                                             intBridgeGenMac ? generateRandomMac() : null)) {
368             LOG.debug("Integration Bridge Creation failed");
369             return false;
370         }
371         return true;
372     }
373
374     private String generateRandomMac() {
375         byte[] macBytes = new byte[6];
376         random.nextBytes(macBytes);
377         macBytes[0] &= 0xfc; //the two low bits of the first byte need to be zero
378
379         StringBuilder stringBuilder = new StringBuilder();
380
381         int i = 0;
382         while(true) {
383             stringBuilder.append(String.format("%02x", macBytes[i++]));
384             if (i >= 6) {
385                 break;
386             }
387             stringBuilder.append(':');
388         }
389
390         return stringBuilder.toString();
391     }
392
393     private boolean createExternalBridge(Node ovsdbNode) {
394         Preconditions.checkNotNull(configurationService);
395
396         if (!addBridge(ovsdbNode, configurationService.getExternalBridgeName(), null)) {
397             LOG.debug("External Bridge Creation failed");
398             return false;
399         }
400         return true;
401     }
402
403     /**
404      * Create and configure bridges for all network types and OpenFlow versions.
405      *
406        OF 1.0 vlan:
407        Bridge br-int
408             Port patch-net
409                 Interface patch-net
410                     type: patch
411                     options: {peer=patch-int}
412             Port br-int
413                 Interface br-int
414                     type: internal
415        Bridge br-net
416             Port "eth1"
417                 Interface "eth1"
418             Port patch-int
419                 Interface patch-int
420                     type: patch
421                     options: {peer=patch-net}
422             Port br-net
423                 Interface br-net
424                     type: internal
425
426        OF 1.0 tunnel:
427        Bridge br-int
428             Port patch-net
429                 Interface patch-net
430                     type: patch
431                     options: {peer=patch-int}
432             Port br-int
433                 Interface br-int
434                     type: internal
435        Bridge "br-net"
436             Port patch-int
437                 Interface patch-int
438                     type: patch
439                     options: {peer=patch-net}
440             Port br-net
441                 Interface br-net
442                     type: internal
443
444        OF 1.3 vlan:
445        Bridge br-int
446             Port "eth1"
447                 Interface "eth1"
448             Port br-int
449                 Interface br-int
450                     type: internal
451
452        OF 1.3 tunnel:
453        Bridge br-int
454             Port br-int
455                 Interface br-int
456                     type: internal
457      */
458     private boolean createBridges(Node bridgeNode, Node ovsdbNode, NeutronNetwork network) {
459         Preconditions.checkNotNull(configurationService);
460         Preconditions.checkNotNull(networkingProviderManager);
461
462         LOG.debug("createBridges: node: {}, network type: {}", bridgeNode, network.getProviderNetworkType());
463
464         final String brInt = configurationService.getIntegrationBridgeName();
465         if (! createIntegrationBridge(ovsdbNode)) {
466             LOG.debug("{} Bridge creation failed", brInt);
467             return false;
468         }
469
470         if (configurationService.isL3ForwardingEnabled()) {
471             final String brExt = configurationService.getExternalBridgeName();
472             if (! createExternalBridge(ovsdbNode)) {
473                 LOG.error("{} Bridge creation failed", brExt);
474                 return false;
475             }
476
477             //get two patch port names
478             final String portNameInt = configurationService.getPatchPortName(new ImmutablePair<>(brInt, brExt));
479             final String portNameExt = configurationService.getPatchPortName(new ImmutablePair<>(brExt, brInt));
480             Preconditions.checkNotNull(portNameInt);
481             Preconditions.checkNotNull(portNameExt);
482
483             if (!addPatchPort(bridgeNode, brInt, portNameInt, portNameExt)) {
484                 LOG.error("Add Port {} to Bridge {} failed", portNameInt, brInt);
485                 return false;
486             }
487             Node extBridgeNode = southbound.readBridgeNode(ovsdbNode, brExt);
488             Preconditions.checkNotNull(extBridgeNode, "br-ex cannot be null or empty!");
489             if (!addPatchPort(extBridgeNode, brExt, portNameExt, portNameInt)) {
490                 LOG.error("Add Port {} to Bridge {} failed", portNameExt, brExt);
491                 return false;
492             }
493             String extNetName = getExternalInterfaceName(extBridgeNode, brExt);
494             if ( extNetName != null) {
495                 if (!addPortToBridge(extBridgeNode, brExt, extNetName)) {
496                     LOG.error("Add External Port {} to Bridge {} failed", extNetName, brExt);
497                     return false;
498                 }
499             LOG.info("Add External Port {} to Ext Bridge {} success", extNetName, brExt);
500             }
501         }
502         /* For vlan network types add physical port to br-int. */
503         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
504             String phyNetName = this.getPhysicalInterfaceName(bridgeNode, network.getProviderPhysicalNetwork());
505             if (!addPortToBridge(bridgeNode, brInt, phyNetName)) {
506                 LOG.debug("Add Port {} to Bridge {} failed", phyNetName, brInt);
507                 return false;
508             }
509         }
510
511         LOG.info("createBridges: node: {}, status: success", bridgeNode);
512         return true;
513     }
514
515     /**
516      * Add a Port to a Bridge
517      */
518     private boolean addPortToBridge (Node node, String bridgeName, String portName) {
519         boolean rv = true;
520
521         if (southbound.extractTerminationPointAugmentation(node, portName) == null) {
522             rv = southbound.addTerminationPoint(node, bridgeName, portName, null);
523
524             if (rv) {
525                 LOG.info("addPortToBridge: node: {}, bridge: {}, portname: {} status: success",
526                         node.getNodeId().getValue(), bridgeName, portName);
527             } else {
528                 LOG.error("addPortToBridge: node: {}, bridge: {}, portname: {} status: FAILED",
529                         node.getNodeId().getValue(), bridgeName, portName);
530             }
531         } else {
532             LOG.trace("addPortToBridge: node: {}, bridge: {}, portname: {} status: not_needed",
533                     node.getNodeId().getValue(), bridgeName, portName);
534         }
535
536         return rv;
537     }
538
539     /**
540      * Add a Patch Port to a Bridge
541      */
542     private boolean addPatchPort (Node node, String bridgeName, String portName, String peerPortName) {
543         boolean rv = true;
544         if (configurationService.isL3MultipleExternalNetworkEnabled() ||
545                 southbound.extractTerminationPointAugmentation(node, portName) == null) {
546             rv = southbound.addPatchTerminationPoint(node, bridgeName, portName, peerPortName);
547             if (rv) {
548                 LOG.info("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: success",
549                         node.getNodeId().getValue(), bridgeName, portName, peerPortName);
550             } else {
551                 LOG.error("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: FAILED",
552                         node.getNodeId().getValue(), bridgeName, portName, peerPortName);
553             }
554         } else {
555             LOG.trace("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: not_needed",
556                     node.getNodeId().getValue(), bridgeName, portName, peerPortName);
557         }
558         return rv;
559     }
560
561     /**
562      * Add Bridge to a Node
563      */
564     private boolean addBridge(Node ovsdbNode, String bridgeName, String mac) {
565         boolean rv = true;
566         boolean isBridgeInConfig = (southbound.getBridgeFromConfig(ovsdbNode, bridgeName) != null);
567         Node bridgeNode = southbound.readBridgeNode(ovsdbNode, bridgeName);
568
569         if (bridgeNode == null || !isBridgeInConfig) {
570             Class<? extends DatapathTypeBase> dpType = null;
571             if (configurationService.isUserSpaceEnabled()) {
572                 dpType = DatapathTypeNetdev.class;
573             }
574
575             // if the bridge is already on the OVS node, use the existing MAC address
576             // because changing the MAC causes the dpid to change on the switch, which
577             // in turn causes a connection flap (see bugs 6070, 6944)
578             rv = southbound.addBridge(ovsdbNode, bridgeName, getControllersFromOvsdbNode(ovsdbNode), dpType,
579                     bridgeNode == null ? mac : southbound.getOtherConfig(bridgeNode, OvsdbTables.BRIDGE, MdsalHelper.HWADDR));
580         }
581         return rv;
582     }
583
584     private String getControllerIPAddress() {
585         String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
586         if (addressString != null) {
587             try {
588                 if (InetAddress.getByName(addressString) != null) {
589                     return addressString;
590                 }
591             } catch (UnknownHostException e) {
592                 LOG.error("Host {} is invalid", addressString, e);
593             }
594         }
595
596         addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
597         if (addressString != null) {
598             try {
599                 if (InetAddress.getByName(addressString) != null) {
600                     return addressString;
601                 }
602             } catch (UnknownHostException e) {
603                 LOG.error("Host {} is invalid", addressString, e);
604             }
605         }
606
607         return null;
608     }
609
610     private short getControllerOFPort() {
611         short openFlowPort = Constants.OPENFLOW_PORT;
612         String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
613         if (portString != null) {
614             try {
615                 openFlowPort = Short.parseShort(portString);
616             } catch (NumberFormatException e) {
617                 LOG.warn("Invalid port:{}, use default({})", portString,
618                         openFlowPort, e);
619             }
620         }
621         return openFlowPort;
622     }
623
624     public List<String> getControllersFromOvsdbNode(Node node) {
625         List<String> controllersStr = new ArrayList<>();
626
627         String controllerIpStr = getControllerIPAddress();
628         if (controllerIpStr != null) {
629             // If codepath makes it here, the ip address to be used was explicitly provided.
630             // Being so, also fetch openflowPort provided via ConfigProperties.
631             controllersStr.add(Constants.OPENFLOW_CONNECTION_PROTOCOL
632                     + ":" + controllerIpStr + ":" + getControllerOFPort());
633         } else {
634             // Check if ovsdb node has manager entries
635             OvsdbNodeAugmentation ovsdbNodeAugmentation = southbound.extractOvsdbNode(node);
636             if (ovsdbNodeAugmentation != null) {
637                 List<ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
638                 if (managerEntries != null && !managerEntries.isEmpty()) {
639                     for (ManagerEntry managerEntry : managerEntries) {
640                         if (managerEntry == null || managerEntry.getTarget() == null) {
641                             continue;
642                         }
643                         String[] tokens = managerEntry.getTarget().getValue().split(":");
644                         if (tokens.length == 3 && tokens[0].equalsIgnoreCase("tcp")) {
645                             controllersStr.add(Constants.OPENFLOW_CONNECTION_PROTOCOL
646                                     + ":" + tokens[1] + ":" + getControllerOFPort());
647                         } else if (tokens[0].equalsIgnoreCase("ptcp")) {
648                             ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
649                             if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
650                                 controllerIpStr = String.valueOf(connectionInfo.getLocalIp().getValue());
651                                 controllersStr.add(Constants.OPENFLOW_CONNECTION_PROTOCOL
652                                         + ":" + controllerIpStr + ":" + Constants.OPENFLOW_PORT);
653                             } else {
654                                 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
655                             }
656                         } else {
657                             LOG.trace("Skipping manager entry {} for node {}",
658                                     managerEntry.getTarget(), node.getNodeId().getValue());
659                         }
660                     }
661                 } else {
662                     LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
663                 }
664             }
665         }
666
667         if (controllersStr.isEmpty()) {
668             // Neither user provided ip nor ovsdb node has manager entries. Lets use local machine ip address.
669             LOG.debug("Use local machine ip address as a OpenFlow Controller ip address");
670             controllerIpStr = getLocalControllerHostIpAddress();
671             if (controllerIpStr != null) {
672                 controllersStr.add(Constants.OPENFLOW_CONNECTION_PROTOCOL
673                         + ":" + controllerIpStr + ":" + Constants.OPENFLOW_PORT);
674             }
675         }
676
677         if (controllersStr.isEmpty()) {
678             LOG.warn("Failed to determine OpenFlow controller ip address");
679         } else if (LOG.isDebugEnabled()) {
680             LOG.debug("Found {} OpenFlow Controller(s): {}", controllersStr.size(),
681                     controllersStr.stream().collect(Collectors.joining(" ")));
682         }
683
684         return controllersStr;
685     }
686
687     private String getLocalControllerHostIpAddress() {
688         String ipaddress = null;
689         try{
690             for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();ifaces.hasMoreElements();){
691                 NetworkInterface iface = ifaces.nextElement();
692
693                 for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
694                     InetAddress inetAddr = inetAddrs.nextElement();
695                     if (!inetAddr.isLoopbackAddress() && inetAddr.isSiteLocalAddress()) {
696                         ipaddress = inetAddr.getHostAddress();
697                         break;
698                     }
699                 }
700             }
701         }catch (Exception e){
702             LOG.warn("Exception while fetching local host ip address ", e);
703         }
704         return ipaddress;
705     }
706
707     @Override
708     public void setDependencies(ServiceReference serviceReference) {
709         configurationService =
710                 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
711         networkingProviderManager =
712                 (NetworkingProviderManager) ServiceHelper.getGlobalInstance(NetworkingProviderManager.class, this);
713         southbound =
714                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
715     }
716
717     @Override
718     public void setDependencies(Object impl) {
719     }
720
721     @Override
722     public String getMultipleExternalBridge(Node ovsdbNode) {
723         String brExt = null;
724         List<String> phyIfNames = this.getAllPhysicalInterfaceNames(ovsdbNode);
725         LOG.debug("getMultipleExternalBridge phyIfName::{}", phyIfNames);
726         if (phyIfNames.size() > 0) {
727             brExt = phyIfNames.get(0);
728             LOG.debug("Provider Mapping: external bridge name:{}", brExt);
729         }
730         if (brExt == null || brExt.isEmpty()) {
731             LOG.warn("The provider mapping external network bridge name is null");
732             return null;
733         }
734         return brExt;
735     }
736 }