elanmanager dead code removal
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanBridgeManager.java
1 /*
2  * Copyright (c) 2016, 2017 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 package org.opendaylight.netvirt.elan.internal;
9
10 import com.google.common.base.Splitter;
11 import com.google.common.base.Strings;
12 import com.google.common.collect.Lists;
13 import java.math.BigInteger;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Optional;
20 import java.util.Random;
21 import javax.annotation.Nullable;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
27 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
28 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
29 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
30 import org.opendaylight.genius.itm.globals.ITMConstants;
31 import org.opendaylight.genius.mdsalutil.MDSALUtil;
32 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfig;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 /**
54  * This class provides functions for creating bridges via OVSDB, specifically the br-int bridge.
55  */
56 @Singleton
57 // Checkstyle expects the first sentence to end with a period, question marks don’t count
58 @SuppressWarnings("checkstyle:SummaryJavadoc")
59 public class ElanBridgeManager {
60     private static final Logger LOG = LoggerFactory.getLogger(ElanBridgeManager.class);
61
62     public static final String PROVIDER_MAPPINGS_KEY = "provider_mappings";
63     private static final String INTEGRATION_BRIDGE = "br-int";
64     private static final String INT_SIDE_PATCH_PORT_SUFFIX = "-patch";
65     private static final String EX_SIDE_PATCH_PORT_SUFFIX = "-int-patch";
66     private static final String OTHER_CONFIG_PARAMETERS_DELIMITER = ",";
67     private static final String OTHER_CONFIG_KEY_VALUE_DELIMITER = ":";
68     private static final int MAX_LINUX_INTERFACE_NAME_LENGTH = 15;
69     private static final String OTHER_CONFIG_DATAPATH_ID = "datapath-id";
70     private static final String OTHER_CONFIG_HWADDR = "hwaddr";
71     private static final String OTHER_CONFIG_DISABLE_IN_BAND = "disable-in-band";
72
73     private final DataBroker dataBroker;
74     private final IInterfaceManager interfaceManager;
75     private final SouthboundUtils southboundUtils;
76     private final Random random;
77     private final Long maxBackoff;
78     private final Long inactivityProbe;
79
80
81     /**
82      * Construct a new ElanBridgeManager.
83      * @param elanConfig the elan configuration
84      * @param interfaceManager InterfaceManager
85      * @param southboundUtils southboutUtils
86      * @param dataBroker DataBroker
87      */
88     @Inject
89     public ElanBridgeManager(ElanConfig elanConfig, IInterfaceManager interfaceManager,
90             SouthboundUtils southboundUtils, DataBroker dataBroker) {
91         //TODO: ClusterAware!!!??
92         this.dataBroker = dataBroker;
93         this.interfaceManager = interfaceManager;
94         this.southboundUtils = southboundUtils;
95         this.random = new Random(System.currentTimeMillis());
96         this.maxBackoff = elanConfig.getControllerMaxBackoff();
97         this.inactivityProbe = elanConfig.getControllerInactivityProbe();
98     }
99
100     /**
101      * Is OVS running in userspace mode?
102      * @return true if the ovsdb.userspace.enabled variable is set to true
103      */
104     public boolean isUserSpaceEnabled() {
105         final String enabledPropertyStr = System.getProperty("ovsdb.userspace.enabled", "no");
106         return enabledPropertyStr != null && enabledPropertyStr.equalsIgnoreCase("yes");
107     }
108
109     /**
110      * Is the Node object an OVSDB node.
111      * @param node unidentified node object
112      * @return true if the Node is an OVSDB node
113      */
114     public boolean isOvsdbNode(Node node) {
115         return southboundUtils.extractNodeAugmentation(node) != null;
116     }
117
118     /**
119      * Is this Node the integration bridge (br-int).
120      * @param node unidentified noe object
121      * @return true if the Node is a bridge and it is the integration bridge
122      */
123     public boolean isIntegrationBridge(Node node) {
124         if (!isBridgeNode(node)) {
125             return false;
126         }
127
128         String bridgeName = southboundUtils.extractBridgeName(node);
129         if (bridgeName == null) {
130             return false;
131         }
132
133         return bridgeName.equals(INTEGRATION_BRIDGE);
134     }
135
136     /**
137      * Is this node a bridge.
138      * @param node unidentified node object
139      * @return true if this node is a bridge
140      */
141     public boolean isBridgeNode(Node node) {
142         return southboundUtils.extractBridgeAugmentation(node) != null;
143     }
144
145     /**
146      * Advance the "preperation" of the OVSDB node. This re-entrant method advances the state of an OVSDB
147      * node towards the prepared state where all bridges and patch ports are created and active. This method
148      * should be invoked for the OVSDB node and the integration bridge node BUT IT IS SAFE TO INVOKE IT ON ANY NODE.
149      * @param node A node
150      * @param generateIntBridgeMac whether or not the int bridge's mac should be set to a random value
151      */
152     @SuppressWarnings("checkstyle:IllegalCatch")
153     public void processNodePrep(Node node, boolean generateIntBridgeMac) {
154         if (isOvsdbNode(node)) {
155             if (southboundUtils.readBridgeNode(node, INTEGRATION_BRIDGE) == null) {
156                 LOG.debug("OVSDB node in operational does not have br-int, create one {}", node.getNodeId().getValue());
157                 try {
158                     createIntegrationBridgeConfig(node, generateIntBridgeMac);
159                 } catch (RuntimeException e) {
160                     LOG.error("Error creating bridge on {}", node, e);
161                 }
162             }
163             return;
164         }
165
166         //Assume "node" is a bridge node, extract the OVSDB node from operational
167         Node ovsdbNode = southboundUtils.readOvsdbNode(node);
168         if (ovsdbNode == null) {
169             LOG.error("Node is neither bridge nor ovsdb {}", node);
170             return;
171         }
172
173         if (isIntegrationBridge(node)) {
174             prepareIntegrationBridge(ovsdbNode, node);
175         }
176
177     }
178
179     public void handleNewProviderNetBridges(Node originalNode, Node updatedNode) {
180         if (!isOvsdbNode(updatedNode)) {
181             return;
182         }
183
184         List<ManagedNodeEntry> originalManagedNodes = getManagedNodeEntries(originalNode);
185         if (originalManagedNodes == null) {
186             return;
187         }
188         List<ManagedNodeEntry> updatedManagedNodes = getManagedNodeEntries(updatedNode);
189         if (updatedManagedNodes == null) {
190             return;
191         }
192         updatedManagedNodes.removeAll(originalManagedNodes);
193         if (updatedManagedNodes.isEmpty()) {
194             return;
195         }
196         LOG.debug("handleNewProviderNetBridges checking if any of these are provider nets {}", updatedManagedNodes);
197
198         Node brInt = southboundUtils.readBridgeNode(updatedNode, INTEGRATION_BRIDGE);
199         if (brInt == null) {
200             LOG.info("handleNewProviderNetBridges, br-int not found");
201             return;
202         }
203
204         Collection<String> providerVals = getOpenvswitchOtherConfigMap(updatedNode, PROVIDER_MAPPINGS_KEY).values();
205         for (ManagedNodeEntry nodeEntry : updatedManagedNodes) {
206             String bridgeName = nodeEntry.getBridgeRef().getValue().firstKeyOf(Node.class).getNodeId().getValue();
207             bridgeName = bridgeName.substring(bridgeName.lastIndexOf('/') + 1);
208             if (bridgeName.equals(INTEGRATION_BRIDGE)) {
209                 continue;
210             }
211             if (providerVals.contains(bridgeName)) {
212                 patchBridgeToBrInt(brInt, southboundUtils.readBridgeNode(updatedNode, bridgeName), bridgeName);
213             }
214         }
215
216
217     }
218
219     @Nullable
220     private List<ManagedNodeEntry> getManagedNodeEntries(Node node) {
221         OvsdbNodeAugmentation ovsdbNode = southboundUtils.extractNodeAugmentation(node);
222         if (ovsdbNode == null) {
223             return null;
224         }
225
226         return ovsdbNode.getManagedNodeEntry();
227     }
228
229     private void prepareIntegrationBridge(Node ovsdbNode, Node brIntNode) {
230         if (southboundUtils.getBridgeFromConfig(ovsdbNode, INTEGRATION_BRIDGE) == null) {
231             LOG.debug("br-int in operational but not config, copying into config");
232             copyBridgeToConfig(brIntNode);
233         }
234
235         Map<String, String> providerMappings = getOpenvswitchOtherConfigMap(ovsdbNode, PROVIDER_MAPPINGS_KEY);
236
237         for (String value : providerMappings.values()) {
238             if (southboundUtils.extractTerminationPointAugmentation(brIntNode, value) != null) {
239                 LOG.debug("prepareIntegrationBridge: port {} already exists on {}", value, INTEGRATION_BRIDGE);
240                 continue;
241             }
242
243             Node exBridgeNode = southboundUtils.readBridgeNode(ovsdbNode, value);
244             if (exBridgeNode != null) {
245                 LOG.debug("prepareIntegrationBridge: bridge {} found. Patching to {}", value, INTEGRATION_BRIDGE);
246                 patchBridgeToBrInt(brIntNode, exBridgeNode, value);
247             } else {
248                 LOG.debug("prepareIntegrationBridge: adding interface {} to {}", value, INTEGRATION_BRIDGE);
249                 if (!addPortToBridge(brIntNode, INTEGRATION_BRIDGE, value)) {
250                     LOG.error("Failed to add {} port to {}", value, brIntNode);
251                 }
252             }
253
254         }
255
256         if (!addControllerToBridge(ovsdbNode, INTEGRATION_BRIDGE)) {
257             LOG.error("Failed to set controller to existing integration bridge {}", brIntNode);
258         }
259
260     }
261
262     private void copyBridgeToConfig(Node brIntNode) {
263         NodeBuilder bridgeNodeBuilder = new NodeBuilder(brIntNode);
264         bridgeNodeBuilder.setTerminationPoint(null);
265         InstanceIdentifier<Node> brNodeIid = SouthboundUtils.createInstanceIdentifier(brIntNode.getNodeId());
266         try {
267             SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
268                 brNodeIid, bridgeNodeBuilder.build());
269         } catch (TransactionCommitFailedException e) {
270             LOG.error("Failed to copy Bridge {} to config", brNodeIid, e);
271         }
272     }
273
274     private void patchBridgeToBrInt(Node intBridgeNode, Node exBridgeNode, String physnetBridgeName) {
275
276         String portNameInt = getIntSidePatchPortName(physnetBridgeName);
277         String portNameExt = getExSidePatchPortName(physnetBridgeName);
278         if (!addPatchPort(intBridgeNode, INTEGRATION_BRIDGE, portNameInt, portNameExt)) {
279             LOG.error("Failed to add patch port {} to {}", portNameInt, intBridgeNode);
280             return;
281         }
282
283         if (!addPatchPort(exBridgeNode, physnetBridgeName, portNameExt, portNameInt)) {
284             LOG.error("Failed to add patch port {} to {}", portNameExt, exBridgeNode);
285             return;
286         }
287     }
288
289     private boolean createIntegrationBridgeConfig(Node ovsdbNode, boolean generateIntBridgeMac) {
290         // Make sure iface-type exist in Open_vSwitch table prior to br-int creation
291         // in order to allow mixed topology of both DPDK and non-DPDK OVS nodes
292         if (!ifaceTypesExist(ovsdbNode)) {
293             LOG.debug("Skipping integration bridge creation as if-types has not been initialized");
294             return false;
295         }
296
297         LOG.debug("ElanBridgeManager.createIntegrationBridgeConfig, skipping if exists");
298         if (!addBridge(ovsdbNode, INTEGRATION_BRIDGE,
299                 generateIntBridgeMac ? generateRandomMac() : null)) {
300             LOG.warn("Integration Bridge Creation failed");
301             return false;
302         }
303         return true;
304     }
305
306     private boolean ifaceTypesExist(Node ovsdbNode) {
307         OvsdbNodeAugmentation ovsdbNodeAugmentation = southboundUtils.extractNodeAugmentation(ovsdbNode);
308         return ovsdbNodeAugmentation != null && ovsdbNodeAugmentation.getInterfaceTypeEntry() != null
309                 && !ovsdbNodeAugmentation.getInterfaceTypeEntry().isEmpty();
310     }
311
312     /**
313      * Add a bridge to the OVSDB node but check that it does not exist in the
314      * CONFIGURATION. If it already exists in OPERATIONAL, update it with all
315      * configurable parameters but make sure to maintain the same datapath-id.
316      *
317      * @param ovsdbNode Which OVSDB node
318      * @param bridgeName Name of the bridge
319      * @param mac mac address to set on the bridge or null
320      * @return true if no errors occurred
321      */
322     public boolean addBridge(Node ovsdbNode, String bridgeName, @Nullable String mac) {
323         boolean rv = true;
324         if (southboundUtils.getBridgeFromConfig(ovsdbNode, bridgeName) == null) {
325             Class<? extends DatapathTypeBase> dpType = null;
326             if (isUserSpaceEnabled()) {
327                 dpType = DatapathTypeNetdev.class;
328             }
329
330             List<BridgeOtherConfigs> otherConfigs = buildBridgeOtherConfigs(ovsdbNode, bridgeName, mac);
331
332             rv = southboundUtils.addBridge(ovsdbNode, bridgeName,
333                     southboundUtils.getControllersFromOvsdbNode(ovsdbNode), dpType, otherConfigs,
334                     maxBackoff, inactivityProbe);
335         }
336         return rv;
337     }
338
339     private List<BridgeOtherConfigs> buildBridgeOtherConfigs(Node ovsdbNode, String bridgeName, String mac) {
340         // First attempt to extract the bridge augmentation from operational...
341         Node bridgeNode = southboundUtils.getBridgeNode(ovsdbNode, bridgeName);
342         OvsdbBridgeAugmentation bridgeAug = null;
343         if (bridgeNode != null) {
344             bridgeAug = southboundUtils.extractBridgeAugmentation(bridgeNode);
345         }
346
347         // ...if present, it means this bridge already exists and we need to take
348         // care not to change the datapath id. We do this by explicitly setting
349         // other_config:datapath-id to the value reported in the augmentation.
350         List<BridgeOtherConfigs> otherConfigs;
351         if (bridgeAug != null) {
352             DatapathId dpId = bridgeAug.getDatapathId();
353             if (dpId != null) {
354                 otherConfigs = bridgeAug.getBridgeOtherConfigs();
355                 if (otherConfigs == null) {
356                     otherConfigs = Lists.newArrayList();
357                 }
358
359                 if (otherConfigs.stream().noneMatch(otherConfig ->
360                             otherConfig.getBridgeOtherConfigKey().equals(OTHER_CONFIG_DATAPATH_ID))) {
361                     String dpIdVal = dpId.getValue().replace(":", "");
362                     otherConfigs.add(new BridgeOtherConfigsBuilder()
363                                     .setBridgeOtherConfigKey(OTHER_CONFIG_DATAPATH_ID)
364                                     .setBridgeOtherConfigValue(dpIdVal).build());
365                 }
366             } else {
367                 otherConfigs = Lists.newArrayList();
368             }
369         } else  {
370             otherConfigs = Lists.newArrayList();
371             if (mac != null) {
372                 otherConfigs.add(new BridgeOtherConfigsBuilder()
373                                 .setBridgeOtherConfigKey(OTHER_CONFIG_HWADDR)
374                                 .setBridgeOtherConfigValue(mac).build());
375             }
376         }
377
378         if (otherConfigs.stream().noneMatch(otherConfig ->
379                 otherConfig.getBridgeOtherConfigKey().equals(OTHER_CONFIG_DISABLE_IN_BAND))) {
380             otherConfigs.add(new BridgeOtherConfigsBuilder()
381                             .setBridgeOtherConfigKey(OTHER_CONFIG_DISABLE_IN_BAND)
382                             .setBridgeOtherConfigValue("true").build());
383         }
384
385         return otherConfigs;
386     }
387
388     private boolean addControllerToBridge(Node ovsdbNode,String bridgeName) {
389         return southboundUtils.setBridgeController(ovsdbNode,
390                 bridgeName, southboundUtils.getControllersFromOvsdbNode(ovsdbNode),
391                 maxBackoff, inactivityProbe);
392     }
393
394     /**
395      * {@inheritDoc}.
396      */
397     public Map<String, String> getOpenvswitchOtherConfigMap(Node node, String key) {
398         String otherConfigVal = southboundUtils.getOpenvswitchOtherConfig(node, key);
399         return getMultiValueMap(otherConfigVal);
400     }
401
402     /**
403      * Get the OVS node physical interface name from provider mappings.
404      * @param node OVSDB node
405      * @param physicalNetworkName name of physical network
406      * @return physical network name
407      */
408     @Nullable
409     public String getProviderMappingValue(Node node, String physicalNetworkName) {
410         Map<String, String> providerMappings = getOpenvswitchOtherConfigMap(node, PROVIDER_MAPPINGS_KEY);
411         String providerMappingValue = providerMappings.get(physicalNetworkName);
412         if (providerMappingValue == null) {
413             LOG.trace("Physical network {} not found in {}", physicalNetworkName, PROVIDER_MAPPINGS_KEY);
414         }
415
416         return providerMappingValue;
417     }
418
419     /**
420      * Get the name of the port in br-int for the given provider-mapping value. This is either a patch port to a bridge
421      * with providerMappingValue - patch-&lt;providerMappingValue&gt; or simply a port with the same name as
422      * providerMappingValue
423      * @param bridgeNode br-int Node
424      * @param providerMappingValue this is the last part of provider_mappings=net_name:THIS
425      * @return the name of the port on br-int
426      */
427     public String getIntBridgePortNameFor(Node bridgeNode, String providerMappingValue) {
428         String res = providerMappingValue;
429         Node managingNode = southboundUtils.readOvsdbNode(bridgeNode);
430         if (managingNode != null && southboundUtils.isBridgeOnOvsdbNode(managingNode, providerMappingValue)) {
431             res = getIntSidePatchPortName(providerMappingValue);
432         }
433
434         return res;
435     }
436
437     /**
438      * Get the name of the patch-port which is patched to the bridge containing
439      * interfaceName. Patch port name is truncated to the maximum allowed characters
440      *
441      * @param interfaceName The external interface
442      * @return interface name
443      */
444     public String getIntSidePatchPortName(String interfaceName) {
445         String patchPortName = interfaceName + INT_SIDE_PATCH_PORT_SUFFIX;
446         if (patchPortName.length() <= MAX_LINUX_INTERFACE_NAME_LENGTH) {
447             return patchPortName;
448         }
449
450         LOG.debug("Patch port {} exceeds maximum allowed length. Truncating to {} characters",
451                 patchPortName, MAX_LINUX_INTERFACE_NAME_LENGTH);
452         return patchPortName.substring(0, MAX_LINUX_INTERFACE_NAME_LENGTH - 1);
453     }
454
455     private String getExSidePatchPortName(String physicalInterfaceName) {
456         return physicalInterfaceName + EX_SIDE_PATCH_PORT_SUFFIX;
457     }
458
459     /**
460      * Add a port to a bridge.
461      * @param node the bridge node
462      * @param bridgeName name of the bridge
463      * @param portName name of port to add
464      * @return true if successful in writing to mdsal
465      */
466     public boolean addPortToBridge(Node node, String bridgeName, String portName) {
467         boolean rv = true;
468
469         if (southboundUtils.extractTerminationPointAugmentation(node, portName) == null) {
470             rv = southboundUtils.addTerminationPoint(node, bridgeName, portName, null);
471
472             if (rv) {
473                 LOG.debug("addPortToBridge: node: {}, bridge: {}, portname: {} status: success",
474                         node.getNodeId().getValue(), bridgeName, portName);
475             } else {
476                 LOG.error("addPortToBridge: node: {}, bridge: {}, portname: {} status: FAILED",
477                         node.getNodeId().getValue(), bridgeName, portName);
478             }
479         } else {
480             LOG.trace("addPortToBridge: node: {}, bridge: {}, portname: {} status: not_needed",
481                     node.getNodeId().getValue(), bridgeName, portName);
482         }
483
484         return rv;
485     }
486
487     /**
488      * Add a patch port to a bridge.
489      * @param node the bridge node
490      * @param bridgeName name of the bridge
491      * @param portName name of the port
492      * @param peerPortName name of the port's peer (the other side)
493      * @return true if successful
494      */
495     public boolean addPatchPort(Node node, String bridgeName, String portName, String peerPortName) {
496         boolean rv = true;
497
498         if (southboundUtils.extractTerminationPointAugmentation(node, portName) == null) {
499             rv = southboundUtils.addPatchTerminationPoint(node, bridgeName, portName, peerPortName);
500
501             if (rv) {
502                 LOG.info("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: success",
503                         node.getNodeId().getValue(), bridgeName, portName, peerPortName);
504             } else {
505                 LOG.error("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: FAILED",
506                         node.getNodeId().getValue(), bridgeName, portName, peerPortName);
507             }
508         } else {
509             LOG.trace("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: not_needed",
510                     node.getNodeId().getValue(), bridgeName, portName, peerPortName);
511         }
512
513         return rv;
514     }
515
516     public Optional<BigInteger> getDpIdFromManagerNodeId(String managerNodeId) {
517         InstanceIdentifier<Node> identifier = getIntegrationBridgeIdentifier(managerNodeId);
518         OvsdbBridgeAugmentation integrationBridgeAugmentation = interfaceManager.getOvsdbBridgeForNodeIid(identifier);
519         if (integrationBridgeAugmentation == null) {
520             LOG.debug("Failed to get OvsdbBridgeAugmentation for node {}", managerNodeId);
521             return Optional.empty();
522         }
523
524         return Optional.ofNullable(integrationBridgeAugmentation.getDatapathId())
525                 .map(datapathId -> MDSALUtil.getDpnId(datapathId.getValue()));
526     }
527
528     private InstanceIdentifier<Node> getIntegrationBridgeIdentifier(String managerNodeId) {
529         NodeId brNodeId = new NodeId(
530                 managerNodeId + "/" + ITMConstants.BRIDGE_URI_PREFIX + "/" + ITMConstants.DEFAULT_BRIDGE_NAME);
531         return InstanceIdentifier.create(NetworkTopology.class)
532                 .child(Topology.class, new TopologyKey(IfmConstants.OVSDB_TOPOLOGY_ID))
533                 .child(Node.class, new NodeKey(brNodeId));
534     }
535
536     private String generateRandomMac() {
537         byte[] macBytes = new byte[6];
538         random.nextBytes(macBytes);
539         macBytes[0] &= 0xfc; //the two low bits of the first byte need to be zero
540
541         StringBuilder stringBuilder = new StringBuilder();
542
543         int index = 0;
544         while (true) {
545             stringBuilder.append(String.format("%02x", macBytes[index++]));
546             if (index >= 6) {
547                 break;
548             }
549             stringBuilder.append(':');
550         }
551
552         return stringBuilder.toString();
553     }
554
555     private Map<String, String> getMultiValueMap(String multiKeyValueStr) {
556         if (Strings.isNullOrEmpty(multiKeyValueStr)) {
557             return Collections.emptyMap();
558         }
559
560         Map<String, String> valueMap = new HashMap<>();
561         Splitter splitter = Splitter.on(OTHER_CONFIG_PARAMETERS_DELIMITER);
562         for (String keyValue : splitter.split(multiKeyValueStr)) {
563             String[] split = keyValue.split(OTHER_CONFIG_KEY_VALUE_DELIMITER, 2);
564             if (split.length == 2) {
565                 valueMap.put(split[0], split[1]);
566             }
567         }
568
569         return valueMap;
570     }
571
572     /**
573      * {@inheritDoc}.
574      */
575     @Nullable
576     private Node getBridgeNode(BigInteger dpId) {
577         List<Node> ovsdbNodes = southboundUtils.getOvsdbNodes();
578         if (null == ovsdbNodes) {
579             LOG.debug("Could not find any (?) ovsdb nodes");
580             return null;
581         }
582
583         for (Node node : ovsdbNodes) {
584             if (!isIntegrationBridge(node)) {
585                 continue;
586             }
587
588             long nodeDpid = southboundUtils.getDataPathId(node);
589             if (dpId.equals(BigInteger.valueOf(nodeDpid))) {
590                 return node;
591             }
592         }
593
594         return null;
595     }
596
597     @Nullable
598     public String getProviderInterfaceName(BigInteger dpId, String physicalNetworkName) {
599         Node brNode;
600
601         brNode = getBridgeNode(dpId);
602         if (brNode == null) {
603             LOG.debug("Could not find bridge node for {}", dpId);
604             return null;
605         }
606
607         return getProviderInterfaceName(brNode, physicalNetworkName);
608     }
609
610     @Nullable
611     public String getProviderInterfaceName(Node bridgeNode, String physicalNetworkName) {
612         if (physicalNetworkName == null) {
613             return null;
614         }
615
616         String providerMappingValue = getProviderMappingValue(bridgeNode, physicalNetworkName);
617         if (providerMappingValue == null) {
618             LOG.trace("No provider mapping found for physicalNetworkName {} node {}", physicalNetworkName,
619                     bridgeNode.getNodeId().getValue());
620             return null;
621         }
622
623         long dataPathId = southboundUtils.getDataPathId(bridgeNode);
624         if (dataPathId < 1) {
625             LOG.info("No DatapathID for node {} with physicalNetworkName {}",
626                     bridgeNode.getNodeId().getValue(), physicalNetworkName);
627             return null;
628         }
629
630         String portName = getIntBridgePortNameFor(bridgeNode, providerMappingValue);
631         String dpIdStr = String.valueOf(dataPathId);
632         return interfaceManager.getPortNameForInterface(dpIdStr, portName);
633     }
634
635     public boolean hasDatapathID(Node node) {
636         return southboundUtils.getDataPathId(node) > 0;
637     }
638
639     public boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgename) {
640         return southboundUtils.isBridgeOnOvsdbNode(ovsdbNode, bridgename);
641     }
642
643     public String getIntegrationBridgeName() {
644         return INTEGRATION_BRIDGE;
645     }
646
647     public BigInteger getDatapathId(Node node) {
648         return BigInteger.valueOf(southboundUtils.getDataPathId(node));
649     }
650 }