Merge "Bug 5951 - Termination point config reconciliation"
[ovsdb.git] / utils / southbound-utils / src / main / java / org / opendaylight / ovsdb / utils / southbound / utils / SouthboundUtils.java
1 /*
2  * Copyright (c) 2015 - 2016 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.ovsdb.utils.southbound.utils;
10
11 import java.math.BigInteger;
12 import java.net.Inet4Address;
13 import java.net.Inet6Address;
14 import java.net.InetAddress;
15 import java.net.NetworkInterface;
16 import java.net.UnknownHostException;
17 import java.security.InvalidParameterException;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.Enumeration;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.ovsdb.utils.config.ConfigProperties;
27 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdk;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkr;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhost;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhostuser;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGeneve;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre64;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeInternal;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre64;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeLisp;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypePatch;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeSystem;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeTap;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlanGpe;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow10;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow11;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow12;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow13;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow14;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow15;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeSecure;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeStandalone;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntry;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsKey;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
91 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
92 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
93 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
94 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
95 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
99 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
100 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
102 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
103 import org.slf4j.Logger;
104 import org.slf4j.LoggerFactory;
105
106 import com.google.common.collect.ImmutableBiMap;
107
108 public class SouthboundUtils {
109     private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
110     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
111     public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
112     private final MdsalUtils mdsalUtils;
113     public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
114     public static short OPENFLOW_PORT = 6653;
115     public static final String OVSDB_URI_PREFIX = "ovsdb";
116     public static final String BRIDGE_URI_PREFIX = "bridge";
117     private static final String DISABLE_IN_BAND = "disable-in-band";
118     private static final String PATCH_PORT_TYPE = "patch";
119
120     public SouthboundUtils(MdsalUtils mdsalUtils) {
121         this.mdsalUtils = mdsalUtils;
122     }
123
124     public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
125             = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
126             .put("internal", InterfaceTypeInternal.class)
127             .put("vxlan", InterfaceTypeVxlan.class)
128             .put("vxlan-gpe", InterfaceTypeVxlanGpe.class)
129             .put("patch", InterfaceTypePatch.class)
130             .put("system", InterfaceTypeSystem.class)
131             .put("tap", InterfaceTypeTap.class)
132             .put("geneve", InterfaceTypeGeneve.class)
133             .put("gre", InterfaceTypeGre.class)
134             .put("ipsec_gre", InterfaceTypeIpsecGre.class)
135             .put("gre64", InterfaceTypeGre64.class)
136             .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
137             .put("lisp", InterfaceTypeLisp.class)
138             .put("dpdk", InterfaceTypeDpdk.class)
139             .put("dpdkr", InterfaceTypeDpdkr.class)
140             .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
141             .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
142             .build();
143
144     public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>,String> OVSDB_PROTOCOL_MAP
145             = new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>,String>()
146             .put(OvsdbBridgeProtocolOpenflow10.class,"OpenFlow10")
147             .put(OvsdbBridgeProtocolOpenflow11.class,"OpenFlow11")
148             .put(OvsdbBridgeProtocolOpenflow12.class,"OpenFlow12")
149             .put(OvsdbBridgeProtocolOpenflow13.class,"OpenFlow13")
150             .put(OvsdbBridgeProtocolOpenflow14.class,"OpenFlow14")
151             .put(OvsdbBridgeProtocolOpenflow15.class,"OpenFlow15")
152             .build();
153
154     private static final ImmutableBiMap<Class<? extends OvsdbFailModeBase>,String> OVSDB_FAIL_MODE_MAP
155             = new ImmutableBiMap.Builder<Class<? extends OvsdbFailModeBase>,String>()
156             .put(OvsdbFailModeStandalone.class,"standalone")
157             .put(OvsdbFailModeSecure.class,"secure")
158             .build();
159
160     public static NodeId createNodeId(IpAddress ip, PortNumber port) {
161         String uriString = OVSDB_URI_PREFIX + "://"
162                 + String.valueOf(ip.getValue()) + ":" + port.getValue();
163         Uri uri = new Uri(uriString);
164         return new NodeId(uri);
165     }
166
167     public static Node createNode(ConnectionInfo key) {
168         NodeBuilder nodeBuilder = new NodeBuilder();
169         nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()));
170         nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
171         return nodeBuilder.build();
172     }
173
174     public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
175         OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
176         ovsdbNodeBuilder.setConnectionInfo(key);
177         return ovsdbNodeBuilder.build();
178     }
179
180     public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
181         return InstanceIdentifier
182                 .create(NetworkTopology.class)
183                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
184                 .child(Node.class,new NodeKey(nodeId));
185     }
186
187     public static InstanceIdentifier<Node> createInstanceIdentifier(NodeKey ovsdbNodeKey, String bridgeName) {
188         return createInstanceIdentifier(createManagedNodeId(ovsdbNodeKey.getNodeId(), bridgeName));
189     }
190
191     public static NodeId createManagedNodeId(NodeId ovsdbNodeId, String bridgeName) {
192         return new NodeId(ovsdbNodeId.getValue()
193                 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName);
194     }
195
196     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
197         return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
198     }
199
200     public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
201         InstanceIdentifier<Node> path = InstanceIdentifier
202                 .create(NetworkTopology.class)
203                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
204                 .child(Node.class,createNodeKey(ip,port));
205         LOG.debug("Created ovsdb path: {}",path);
206         return path;
207     }
208
209     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key,OvsdbBridgeName bridgeName) {
210         return createInstanceIdentifier(createManagedNodeId(key, bridgeName));
211     }
212
213     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, String bridgeName) {
214         return createInstanceIdentifier(key, new OvsdbBridgeName(bridgeName));
215     }
216
217     public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName){
218
219         InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
220                 .create(NetworkTopology.class)
221                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
222                 .child(Node.class,node.getKey())
223                 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
224
225         LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
226         return terminationPointPath;
227     }
228
229     public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
230         return new NodeKey(createNodeId(ip, port));
231     }
232
233     public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
234         return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
235     }
236
237     public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
238         return new NodeId(createNodeId(ip,port).getValue()
239                 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
240     }
241
242     public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
243         NodeKey nodeKey = iid.firstKeyOf(Node.class);
244         return nodeKey.getNodeId();
245     }
246
247     public ConnectionInfo getConnectionInfo(Node ovsdbNode) {
248         ConnectionInfo connectionInfo = null;
249         OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(ovsdbNode);
250         if (ovsdbNodeAugmentation != null) {
251             connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
252         }
253         return connectionInfo;
254     }
255
256     public OvsdbNodeAugmentation extractOvsdbNode(Node node) {
257         return node.getAugmentation(OvsdbNodeAugmentation.class);
258     }
259
260     public static IpAddress createIpAddress(InetAddress address) {
261         IpAddress ip = null;
262         if (address instanceof Inet4Address) {
263             ip = createIpAddress((Inet4Address)address);
264         } else if (address instanceof Inet6Address) {
265             ip = createIpAddress((Inet6Address)address);
266         }
267         return ip;
268     }
269
270     public static IpAddress createIpAddress(Inet4Address address) {
271         return IetfInetUtil.INSTANCE.ipAddressFor(address);
272     }
273
274     public static IpAddress createIpAddress(Inet6Address address) {
275         Ipv6Address ipv6 = new Ipv6Address(address.getHostAddress());
276         return new IpAddress(ipv6);
277     }
278
279     public static ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
280         InetAddress inetAddress = null;
281         try {
282             inetAddress = InetAddress.getByName(addressStr);
283         } catch (UnknownHostException e) {
284             LOG.warn("Could not allocate InetAddress", e);
285         }
286
287         IpAddress address = createIpAddress(inetAddress);
288         PortNumber port = new PortNumber(Integer.parseInt(portStr));
289
290         LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
291                 .setRemoteIp(address)
292                 .setRemotePort(port)
293                 .build());
294         return new ConnectionInfoBuilder()
295                 .setRemoteIp(address)
296                 .setRemotePort(port)
297                 .build();
298     }
299
300     public static String connectionInfoToString(final ConnectionInfo connectionInfo) {
301         return String.valueOf(
302                 connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
303     }
304
305     public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
306         return addOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
307     }
308
309     public boolean addOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
310         boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
311                 createInstanceIdentifier(connectionInfo),
312                 createNode(connectionInfo));
313         if (timeout != 0) {
314             try {
315                 Thread.sleep(timeout);
316             } catch (InterruptedException e) {
317                 LOG.warn("Interrupted while waiting after adding OVSDB node {}",
318                         connectionInfoToString(connectionInfo), e);
319             }
320         }
321         return result;
322     }
323
324     public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
325         return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
326                 createInstanceIdentifier(connectionInfo));
327     }
328
329     public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
330         return deleteOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
331     }
332
333     public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
334         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
335                 createInstanceIdentifier(connectionInfo));
336         if (timeout != 0) {
337             try {
338                 Thread.sleep(timeout);
339             } catch (InterruptedException e) {
340                 LOG.warn("Interrupted while waiting after deleting OVSDB node {}",
341                         connectionInfoToString(connectionInfo), e);
342             }
343         }
344         return result;
345     }
346
347     public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
348         return connectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
349     }
350
351     public Node connectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
352         addOvsdbNode(connectionInfo, timeout);
353         Node node = getOvsdbNode(connectionInfo);
354         LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
355         return node;
356     }
357
358     public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
359         return disconnectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
360     }
361
362     public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
363         deleteOvsdbNode(connectionInfo, timeout);
364         LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
365         return true;
366     }
367
368     public List<ControllerEntry> createControllerEntry(String controllerTarget) {
369         List<ControllerEntry> controllerEntriesList = new ArrayList<>();
370         controllerEntriesList.add(new ControllerEntryBuilder()
371                 .setTarget(new Uri(controllerTarget))
372                 .build());
373         return controllerEntriesList;
374     }
375
376     /**
377      * Extract the <code>store</code> type data store contents for the particular bridge identified by
378      * <code>bridgeName</code>.
379      *
380      * @param connectionInfo address for the node
381      * @param bridgeName name of the bridge
382      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
383      * @return <code>store</code> type data store contents
384      */
385     public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
386                                               LogicalDatastoreType store) {
387         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
388         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
389         if (bridgeNode != null) {
390             ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
391         }
392         return ovsdbBridgeAugmentation;
393     }
394
395     /**
396      * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
397      * identified by <code>bridgeName</code>
398      *
399      * @param connectionInfo address for the node
400      * @param bridgeName name of the bridge
401      * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
402      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
403      */
404     public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
405         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
406     }
407
408     /**
409      * Extract the node contents from <code>store</code> type data store for the
410      * bridge identified by <code>bridgeName</code>.
411      *
412      * @param connectionInfo address for the node
413      * @param bridgeName name of the bridge
414      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
415      * @return <code>store</code> type data store contents
416      */
417     public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
418         InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
419         return mdsalUtils.read(store, bridgeIid);
420     }
421
422     public Node getBridgeNode(Node node, String bridgeName) {
423         OvsdbBridgeAugmentation bridge = extractBridgeAugmentation(node);
424         if (bridge != null && bridge.getBridgeName().getValue().equals(bridgeName)) {
425             return node;
426         } else {
427             return readBridgeNode(node, bridgeName);
428         }
429     }
430
431     public Node readBridgeNode(Node node, String name) {
432         Node ovsdbNode = node;
433         if (extractNodeAugmentation(ovsdbNode) == null) {
434             ovsdbNode = readOvsdbNode(node);
435             if (ovsdbNode == null) {
436                 return null;
437             }
438         }
439         Node bridgeNode = null;
440         ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
441         if (connectionInfo != null) {
442             InstanceIdentifier<Node> bridgeIid =
443                     createInstanceIdentifier(node.getKey(), name);
444             bridgeNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
445         }
446         return bridgeNode;
447     }
448
449     public OvsdbNodeAugmentation extractNodeAugmentation(Node node) {
450         return node.getAugmentation(OvsdbNodeAugmentation.class);
451     }
452
453     public OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
454         if (node == null) {
455             return null;
456         }
457         return node.getAugmentation(OvsdbBridgeAugmentation.class);
458     }
459
460     public Node readOvsdbNode(Node bridgeNode) {
461         Node ovsdbNode = null;
462         OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
463         if (bridgeAugmentation != null) {
464             InstanceIdentifier<Node> ovsdbNodeIid =
465                     (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
466             ovsdbNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
467         }else{
468             LOG.debug("readOvsdbNode: Provided node is not a bridge node : {}",bridgeNode);
469         }
470         return ovsdbNode;
471     }
472
473     public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
474         return deleteBridge(connectionInfo, bridgeName, OVSDB_UPDATE_TIMEOUT);
475     }
476
477     public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName, long timeout) {
478         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
479                 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
480         if (timeout != 0) {
481             try {
482                 Thread.sleep(timeout);
483             } catch (InterruptedException e) {
484                 LOG.warn("Interrupted while waiting after deleting bridge {}", bridgeName, e);
485             }
486         }
487         return result;
488     }
489
490     public List<ProtocolEntry> createMdsalProtocols() {
491         List<ProtocolEntry> protocolList = new ArrayList<>();
492         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
493                 OVSDB_PROTOCOL_MAP.inverse();
494         protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
495         return protocolList;
496     }
497
498     public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
499                              final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
500                              final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
501                              final Class<? extends DatapathTypeBase> dpType,
502                              final List<BridgeExternalIds> externalIds,
503                              final List<ControllerEntry> controllerEntries,
504                              final List<BridgeOtherConfigs> otherConfigs,
505                              final String dpid) throws InterruptedException {
506         return addBridge(connectionInfo, bridgeIid, bridgeName, bridgeNodeId, setProtocolEntries, failMode,
507                 setManagedBy, dpType, externalIds, controllerEntries, otherConfigs, dpid);
508     }
509
510     /*
511      * base method for adding test bridges.  Other helper methods used to create bridges should utilize this method.
512      *
513      * @param connectionInfo
514      * @param bridgeIid if passed null, one is created
515      * @param bridgeName cannot be null
516      * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
517      * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
518      * @param failMode toggles whether default fail mode is set for the bridge
519      * @param setManagedBy toggles whether to setManagedBy for the bridge
520      * @param dpType if passed null, this parameter is ignored
521      * @param externalIds if passed null, this parameter is ignored
522      * @param otherConfig if passed null, this parameter is ignored
523      * @return success of bridge addition
524      * @throws InterruptedException
525      */
526     public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
527                              final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
528                              final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
529                              final Class<? extends DatapathTypeBase> dpType,
530                              final List<BridgeExternalIds> externalIds,
531                              final List<ControllerEntry> controllerEntries,
532                              final List<BridgeOtherConfigs> otherConfigs,
533                              final String dpid, long timeout) throws InterruptedException {
534
535         NodeBuilder bridgeNodeBuilder = new NodeBuilder();
536         if (bridgeIid == null) {
537             bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
538         }
539         if (bridgeNodeId == null) {
540             bridgeNodeId = createManagedNodeId(bridgeIid);
541         }
542         bridgeNodeBuilder.setNodeId(bridgeNodeId);
543         OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
544         ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
545         if (setProtocolEntries) {
546             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
547         }
548         if (failMode != null) {
549             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
550         }
551         if (setManagedBy) {
552             setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
553         }
554         if (dpType != null) {
555             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
556         }
557         if (externalIds != null) {
558             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
559         }
560         if (controllerEntries != null) {
561             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
562         }
563         if (otherConfigs != null) {
564             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
565         }
566         if (dpid != null && !dpid.isEmpty()) {
567             DatapathId datapathId = new DatapathId(dpid);
568             ovsdbBridgeAugmentationBuilder.setDatapathId(datapathId);
569         }
570         bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
571         LOG.debug("Built with the intent to store bridge data {}",
572                 ovsdbBridgeAugmentationBuilder.toString());
573         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
574                 bridgeIid, bridgeNodeBuilder.build());
575         if (timeout != 0) {
576             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
577         }
578         return result;
579     }
580
581     /**
582      * Set the controllers of an existing bridge node
583      * @param ovsdbNode where the bridge is
584      * @param bridgeNode The bridge node itself
585      * @param bridgeName Name of the bridge
586      * @param controllers controller strings
587      * @return success if the write to md-sal was successful
588      */
589     public boolean setBridgeController(Node ovsdbNode, Node bridgeNode, String bridgeName, List<String> controllers) {
590         LOG.debug("setBridgeController: ovsdbNode: {}, bridgeNode: {}, controller(s): {}",
591                 ovsdbNode, bridgeNode, controllers);
592
593         OvsdbBridgeAugmentation bridgeAug = extractBridgeAugmentation(bridgeNode);
594         NodeBuilder nodeBuilder = new NodeBuilder(bridgeNode);
595         OvsdbBridgeAugmentationBuilder augBuilder = new OvsdbBridgeAugmentationBuilder(bridgeAug);
596         augBuilder.setControllerEntry(createControllerEntries(controllers));
597         nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, augBuilder.build());
598         InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.getKey(), bridgeName);
599
600         return mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, nodeBuilder.build());
601     }
602
603     public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
604                              final Class<? extends DatapathTypeBase> dpType, String mac) {
605         boolean result;
606
607         LOG.info("addBridge: node: {}, bridgeName: {}, controller(s): {}", ovsdbNode, bridgeName, controllersStr);
608         ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
609         if (connectionInfo != null) {
610             NodeBuilder bridgeNodeBuilder = new NodeBuilder();
611             InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.getKey(), bridgeName);
612             NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
613             bridgeNodeBuilder.setNodeId(bridgeNodeId);
614             OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
615             ovsdbBridgeAugmentationBuilder.setControllerEntry(createControllerEntries(controllersStr));
616             ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
617             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
618             ovsdbBridgeAugmentationBuilder.setFailMode( OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
619             BridgeOtherConfigsBuilder bridgeOtherConfigsBuilder = new BridgeOtherConfigsBuilder();
620             bridgeOtherConfigsBuilder.setBridgeOtherConfigKey(DISABLE_IN_BAND);
621             bridgeOtherConfigsBuilder.setBridgeOtherConfigValue("true");
622             List<BridgeOtherConfigs> bridgeOtherConfigsList = new ArrayList<>();
623             bridgeOtherConfigsList.add(bridgeOtherConfigsBuilder.build());
624             if (mac != null) {
625                 BridgeOtherConfigsBuilder macOtherConfigBuilder = new BridgeOtherConfigsBuilder();
626                 macOtherConfigBuilder.setBridgeOtherConfigKey("hwaddr");
627                 macOtherConfigBuilder.setBridgeOtherConfigValue(mac);
628                 bridgeOtherConfigsList.add(macOtherConfigBuilder.build());
629             }
630             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(bridgeOtherConfigsList);
631             setManagedByForBridge(ovsdbBridgeAugmentationBuilder, ovsdbNode.getKey());
632             if (dpType != null) {
633                 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
634             }
635             if (isOvsdbNodeDpdk(ovsdbNode)) {
636                 ovsdbBridgeAugmentationBuilder.setDatapathType(DatapathTypeNetdev.class);
637             }
638             bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
639
640             Node node = bridgeNodeBuilder.build();
641             result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, bridgeIid, node);
642             LOG.info("addBridge: result: {}", result);
643         } else {
644             throw new InvalidParameterException("Could not find ConnectionInfo");
645         }
646         return result;
647     }
648
649
650     private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
651                               final ConnectionInfo connectionInfo) {
652         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
653         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
654     }
655
656     public boolean addTerminationPoint(
657             Node bridgeNode, String portName, String type, Map<String, String> options,
658             Map<String, String> externalIds) {
659         return addTerminationPoint(bridgeNode, portName, type, options, externalIds, null);
660     }
661
662     public boolean addTerminationPoint(
663             Node bridgeNode, String portName, String type, Map<String, String> options, Map<String, String> externalIds,
664             Long ofPort) {
665         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
666         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
667
668         tpAugmentationBuilder.setName(portName);
669         tpAugmentationBuilder.setOfport(ofPort);
670         if (type != null) {
671             tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
672         }
673
674         if (options != null && options.size() > 0) {
675             List<Options> optionsList = new ArrayList<>();
676             for (Map.Entry<String, String> entry : options.entrySet()) {
677                 OptionsBuilder optionsBuilder = new OptionsBuilder();
678                 optionsBuilder.setKey(new OptionsKey(entry.getKey()));
679                 optionsBuilder.setOption(entry.getKey());
680                 optionsBuilder.setValue(entry.getValue());
681                 optionsList.add(optionsBuilder.build());
682             }
683             tpAugmentationBuilder.setOptions(optionsList);
684         }
685
686         if (externalIds != null && externalIds.size() > 0) {
687             List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
688             for (Map.Entry<String, String> entry : externalIds.entrySet()) {
689                 InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
690                 interfaceExternalIdsBuilder.setKey(new InterfaceExternalIdsKey(entry.getKey()));
691                 interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
692                 interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
693                 externalIdsList.add(interfaceExternalIdsBuilder.build());
694             }
695             tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
696         }
697
698         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
699         tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
700         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
701         /* TODO SB_MIGRATION should this be merge or mdsalUtils.put */
702         return mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
703     }
704
705     public Boolean addTerminationPoint(Node bridgeNode, String portName, String type) {
706         return addTerminationPoint(bridgeNode, portName, type, Collections.EMPTY_MAP, null);
707     }
708
709     public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
710                                        String type, Map<String, String> options) {
711         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
712                 bridgeNode, portName);
713         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
714
715         tpAugmentationBuilder.setName(portName);
716         if (type != null) {
717             tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
718         }
719
720         List<Options> optionsList = new ArrayList<>();
721         for (Map.Entry<String, String> entry : options.entrySet()) {
722             OptionsBuilder optionsBuilder = new OptionsBuilder();
723             optionsBuilder.setKey(new OptionsKey(entry.getKey()));
724             optionsBuilder.setOption(entry.getKey());
725             optionsBuilder.setValue(entry.getValue());
726             optionsList.add(optionsBuilder.build());
727         }
728         tpAugmentationBuilder.setOptions(optionsList);
729
730         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
731         tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
732         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
733         /* TODO SB_MIGRATION should this be merge or mdsalUtils.put */
734         return mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
735     }
736
737     public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
738         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
739         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
740                 new OvsdbTerminationPointAugmentationBuilder();
741
742         tpAugmentationBuilder.setName(portName);
743         if (type != null) {
744             tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
745         }
746         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
747         tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
748         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
749         return mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
750     }
751
752     public Boolean addPatchTerminationPoint(Node node, String bridgeName, String portName, String peerPortName) {
753         Map<String, String> option = new HashMap<>();
754         option.put("peer", peerPortName);
755         return addTerminationPoint(node, bridgeName, portName, PATCH_PORT_TYPE, option);
756     }
757
758     private String getControllerIPAddress() {
759         String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
760         if (addressString != null) {
761             try {
762                 if (InetAddress.getByName(addressString) != null) {
763                     return addressString;
764                 }
765             } catch (UnknownHostException e) {
766                 LOG.error("Host {} is invalid", addressString, e);
767             }
768         }
769
770         addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
771         if (addressString != null) {
772             try {
773                 if (InetAddress.getByName(addressString) != null) {
774                     return addressString;
775                 }
776             } catch (UnknownHostException e) {
777                 LOG.error("Host {} is invalid", addressString, e);
778             }
779         }
780
781         return null;
782     }
783
784     private short getControllerOFPort() {
785         short openFlowPort = OPENFLOW_PORT;
786         String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
787         if (portString != null) {
788             try {
789                 openFlowPort = Short.parseShort(portString);
790             } catch (NumberFormatException e) {
791                 LOG.warn("Invalid port:{}, use default({})", portString,
792                         openFlowPort, e);
793             }
794         }
795         return openFlowPort;
796     }
797
798     public List<String> getControllersFromOvsdbNode(Node node) {
799         List<String> controllersStr = new ArrayList<>();
800
801         String controllerIpStr = getControllerIPAddress();
802         if (controllerIpStr != null) {
803             // If codepath makes it here, the ip address to be used was explicitly provided.
804             // Being so, also fetch openflowPort provided via ConfigProperties.
805             controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
806                     + ":" + controllerIpStr + ":" + getControllerOFPort());
807         } else {
808             // Check if ovsdb node has manager entries
809             OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(node);
810             if (ovsdbNodeAugmentation != null) {
811                 List<ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
812                 if (managerEntries != null && !managerEntries.isEmpty()) {
813                     for (ManagerEntry managerEntry : managerEntries) {
814                         if (managerEntry == null || managerEntry.getTarget() == null) {
815                             continue;
816                         }
817                         String[] tokens = managerEntry.getTarget().getValue().split(":");
818                         if (tokens.length == 3 && tokens[0].equalsIgnoreCase("tcp")) {
819                             controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
820                                     + ":" + tokens[1] + ":" + getControllerOFPort());
821                         } else if (tokens[0].equalsIgnoreCase("ptcp")) {
822                             ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
823                             if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
824                                 controllerIpStr = String.valueOf(connectionInfo.getLocalIp().getValue());
825                                 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
826                                         + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
827                             } else {
828                                 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
829                             }
830                         } else {
831                             LOG.trace("Skipping manager entry {} for node {}",
832                                     managerEntry.getTarget(), node.getNodeId().getValue());
833                         }
834                     }
835                 } else {
836                     LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
837                 }
838             }
839         }
840
841         if (controllersStr.isEmpty()) {
842             // Neither user provided ip nor ovsdb node has manager entries. Lets use local machine ip address.
843             LOG.debug("Use local machine ip address as a OpenFlow Controller ip address");
844             controllerIpStr = getLocalControllerHostIpAddress();
845             if (controllerIpStr != null) {
846                 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
847                         + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
848             }
849         }
850
851         if (controllersStr.isEmpty()) {
852             LOG.warn("Failed to determine OpenFlow controller ip address");
853         } else if (LOG.isDebugEnabled()) {
854             controllerIpStr = "";
855             for (String currControllerIpStr : controllersStr) {
856                 controllerIpStr += " " + currControllerIpStr;
857             }
858             LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(), controllerIpStr);
859         }
860
861         return controllersStr;
862     }
863
864     private String getLocalControllerHostIpAddress() {
865         String ipaddress = null;
866         try{
867             for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();){
868                 NetworkInterface iface = ifaces.nextElement();
869
870                 for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
871                     InetAddress inetAddr = inetAddrs.nextElement();
872                     if (!inetAddr.isLoopbackAddress() && inetAddr.isSiteLocalAddress()) {
873                         ipaddress = inetAddr.getHostAddress();
874                         break;
875                     }
876                 }
877             }
878         }catch (Exception e){
879             LOG.warn("Exception while fetching local host ip address ", e);
880         }
881         return ipaddress;
882     }
883
884     public long getDataPathId(Node node) {
885         long dpid = 0L;
886         String datapathId = getDatapathId(node);
887         if (datapathId != null) {
888             dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
889         }
890         return dpid;
891     }
892
893     public String getDatapathId(Node node) {
894         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.getAugmentation(OvsdbBridgeAugmentation.class);
895         return getDatapathId(ovsdbBridgeAugmentation);
896     }
897
898     public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
899         String datapathId = null;
900         if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
901             datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
902         }
903         return datapathId;
904     }
905
906     public String extractBridgeName(Node node) {
907         return node.getAugmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
908     }
909
910     public boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgeName) {
911         boolean found = false;
912         OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
913         if (ovsdbNodeAugmentation != null) {
914             List<ManagedNodeEntry> managedNodes = ovsdbNodeAugmentation.getManagedNodeEntry();
915             if (managedNodes != null) {
916                 for (ManagedNodeEntry managedNode : managedNodes) {
917                     InstanceIdentifier<?> bridgeIid = managedNode.getBridgeRef().getValue();
918                     if (bridgeIid.toString().contains(bridgeName)) {
919                         found = true;
920                         break;
921                     }
922                 }
923             }
924         }
925         return found;
926     }
927
928     public OvsdbBridgeAugmentation getBridgeFromConfig(Node node, String bridge) {
929         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
930         InstanceIdentifier<Node> bridgeIid =
931                 createInstanceIdentifier(node.getKey(), bridge);
932         Node bridgeNode = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, bridgeIid);
933         if (bridgeNode != null) {
934             ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
935         }
936         return ovsdbBridgeAugmentation;
937     }
938
939     private void setManagedByForBridge(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
940                                        NodeKey ovsdbNodeKey) {
941         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(ovsdbNodeKey.getNodeId());
942         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
943     }
944
945     public boolean isOvsdbNodeDpdk(Node ovsdbNode) {
946         boolean found = false;
947         OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
948         if (ovsdbNodeAugmentation != null) {
949             List<InterfaceTypeEntry> ifTypes = ovsdbNodeAugmentation.getInterfaceTypeEntry();
950             if (ifTypes != null) {
951                 for (InterfaceTypeEntry ifType : ifTypes) {
952                     if (ifType.getInterfaceType().equals(InterfaceTypeDpdk.class)) {
953                         found = true;
954                         break;
955                     }
956                 }
957             }
958         }
959         return found;
960     }
961
962     private List<ControllerEntry> createControllerEntries(List<String> controllersStr) {
963         List<ControllerEntry> controllerEntries = new ArrayList<>();
964         if (controllersStr != null) {
965             for (String controllerStr : controllersStr) {
966                 ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
967                 controllerEntryBuilder.setTarget(new Uri(controllerStr));
968                 controllerEntries.add(controllerEntryBuilder.build());
969             }
970         }
971         return controllerEntries;
972     }
973
974     public OvsdbTerminationPointAugmentation extractTerminationPointAugmentation(Node bridgeNode, String portName) {
975         if (bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class) != null) {
976             List<OvsdbTerminationPointAugmentation> tpAugmentations = extractTerminationPointAugmentations(bridgeNode);
977             for (OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation : tpAugmentations) {
978                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
979                     return ovsdbTerminationPointAugmentation;
980                 }
981             }
982         }
983         return null;
984     }
985
986     public List<OvsdbTerminationPointAugmentation> extractTerminationPointAugmentations( Node node ) {
987         List<OvsdbTerminationPointAugmentation> tpAugmentations = new ArrayList<>();
988         if (node == null) {
989             LOG.error("extractTerminationPointAugmentations: Node value is null");
990             return Collections.<OvsdbTerminationPointAugmentation>emptyList();
991         }
992         List<TerminationPoint> terminationPoints = node.getTerminationPoint();
993         if(terminationPoints != null && !terminationPoints.isEmpty()){
994             for(TerminationPoint tp : terminationPoints){
995                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
996                         tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
997                 if (ovsdbTerminationPointAugmentation != null) {
998                     tpAugmentations.add(ovsdbTerminationPointAugmentation);
999                 }
1000             }
1001         }
1002         return tpAugmentations;
1003     }
1004
1005     /**
1006      * Extract the <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code> identified by
1007      * <code>portName</code>.
1008      *
1009      * @param node
1010      * @param portName
1011      * @return
1012      */
1013     public OvsdbTerminationPointAugmentation getTerminationPointOfBridge(Node node, String portName) {
1014         OvsdbTerminationPointAugmentation tpAugmentation = extractTerminationPointAugmentation(node,portName);
1015         if(tpAugmentation == null){
1016             List<OvsdbTerminationPointAugmentation> tpAugmentations = readTerminationPointAugmentations(node);
1017             if(tpAugmentations != null){
1018                 for(OvsdbTerminationPointAugmentation ovsdbTpAugmentation : tpAugmentations){
1019                     if(ovsdbTpAugmentation.getName().equals(portName)){
1020                         return ovsdbTpAugmentation;
1021                     }
1022                 }
1023             }
1024         }
1025         return tpAugmentation;
1026     }
1027
1028     /**
1029      * read the list of <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code>.
1030      *
1031      * @param node
1032      * @return
1033      */
1034     public List<OvsdbTerminationPointAugmentation> readTerminationPointAugmentations(Node node) {
1035         if (node == null) {
1036             LOG.error("readTerminationPointAugmentations: Node value is null");
1037             return Collections.<OvsdbTerminationPointAugmentation>emptyList();
1038         }
1039         Node operNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier
1040                 .create(NetworkTopology.class)
1041                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
1042                 .child(Node.class, new NodeKey(node.getNodeId())));
1043         if (operNode != null) {
1044             return extractTerminationPointAugmentations(operNode);
1045         }
1046         return new ArrayList<>();
1047     }
1048
1049     /**
1050      * Get all OVSDB nodes from topology.
1051      * @return a list of nodes or null if the topology could not found
1052      */
1053     public List<Node> getOvsdbNodes() {
1054         InstanceIdentifier<Topology> inst = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
1055                 new TopologyKey(OVSDB_TOPOLOGY_ID));
1056         Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, inst);
1057         return topology != null ? topology.getNode() : null;
1058     }
1059
1060     /**
1061      * Get OpenvSwitch other-config by key.
1062      * @param node OVSDB node
1063      * @param key key to extract from other-config
1064      * @return the value for key or null if key not found
1065      */
1066     public String getOpenvswitchOtherConfig(Node node, String key) {
1067         OvsdbNodeAugmentation ovsdbNode = node.getAugmentation(OvsdbNodeAugmentation.class);
1068         if (ovsdbNode == null) {
1069             Node nodeFromReadOvsdbNode = readOvsdbNode(node);
1070             if (nodeFromReadOvsdbNode != null) {
1071                 ovsdbNode = nodeFromReadOvsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
1072             }
1073         }
1074
1075         if (ovsdbNode != null && ovsdbNode.getOpenvswitchOtherConfigs() != null) {
1076             for (OpenvswitchOtherConfigs openvswitchOtherConfigs : ovsdbNode.getOpenvswitchOtherConfigs()) {
1077                 if (openvswitchOtherConfigs.getOtherConfigKey().equals(key)) {
1078                     return openvswitchOtherConfigs.getOtherConfigValue();
1079                 }
1080             }
1081         }
1082
1083         return null;
1084     }
1085 }