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