2 * Copyright (c) 2015, 2018 Red Hat, Inc. and others. All rights reserved.
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
9 package org.opendaylight.ovsdb.utils.southbound.utils;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.collect.ImmutableBiMap;
14 import java.math.BigInteger;
15 import java.net.Inet4Address;
16 import java.net.Inet6Address;
17 import java.net.InetAddress;
18 import java.net.UnknownHostException;
19 import java.security.InvalidParameterException;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Locale;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28 import java.util.stream.Collectors;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.ovsdb.utils.config.ConfigProperties;
31 import org.opendaylight.ovsdb.utils.mdsal.utils.ControllerMdsalUtils;
32 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdk;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkr;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhost;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhostuser;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhostuserclient;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGeneve;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre64;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeInternal;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre64;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeLisp;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypePatch;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeSystem;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeTap;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlanGpe;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow10;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow11;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow12;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow13;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow14;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow15;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeSecure;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeStandalone;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntry;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
99 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
100 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
104 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
105 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
106 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
107 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
108 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
109 import org.opendaylight.yangtools.yang.binding.DataObject;
110 import org.opendaylight.yangtools.yang.binding.Identifier;
111 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
112 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
113 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
114 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
115 import org.slf4j.Logger;
116 import org.slf4j.LoggerFactory;
118 public class SouthboundUtils {
119 private abstract static class UtilsProvider {
121 abstract <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path);
123 abstract boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path);
125 abstract <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path,
128 abstract <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data);
132 private static final class ControllerUtilsProvider extends UtilsProvider {
133 private final ControllerMdsalUtils mdsalUtils;
135 ControllerUtilsProvider(final ControllerMdsalUtils mdsalUtils) {
136 this.mdsalUtils = requireNonNull(mdsalUtils);
140 <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path) {
141 return mdsalUtils.read(store, path);
145 <T extends DataObject> boolean put(LogicalDatastoreType store,
146 InstanceIdentifier<T> path, T data) {
147 return mdsalUtils.put(store, path, data);
151 boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
152 return mdsalUtils.delete(store, path);
156 <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
157 return mdsalUtils.merge(store, path, data);
161 private static final class MdsalUtilsProvider extends UtilsProvider {
162 private final MdsalUtils mdsalUtils;
164 MdsalUtilsProvider(final MdsalUtils mdsalUtils) {
165 this.mdsalUtils = requireNonNull(mdsalUtils);
169 <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path) {
170 return mdsalUtils.read(store, path);
174 <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
175 return mdsalUtils.put(store, path, data);
179 boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
180 return mdsalUtils.delete(store, path);
184 <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
185 return mdsalUtils.merge(store, path, data);
189 private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
190 private static final int OVSDB_UPDATE_TIMEOUT = 1000;
191 public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
192 public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
193 public static final String OPENFLOW_SECURE_PROTOCOL = "ssl";
194 public static final short OPENFLOW_PORT = 6653;
195 public static final String OVSDB_URI_PREFIX = "ovsdb";
196 public static final String BRIDGE_URI_PREFIX = "bridge";
197 private static final String DISABLE_IN_BAND = "disable-in-band";
198 private static final String PATCH_PORT_TYPE = "patch";
199 // External ID key used for mapping between an OVSDB port and an interface name
200 private static final String EXTERNAL_INTERFACE_ID_KEY = "iface-id";
201 private static final String CREATED_BY = "created_by";
202 private static final String ODL = "odl";
203 private static final String FORMAT = "(\\d+)\\.(\\d+)\\.(\\d+)";
204 private static final Pattern PATTERN = Pattern.compile(FORMAT);
206 private final UtilsProvider provider;
209 public SouthboundUtils(ControllerMdsalUtils mdsalUtils) {
210 provider = new ControllerUtilsProvider(mdsalUtils);
213 public SouthboundUtils(MdsalUtils mdsalUtils) {
214 provider = new MdsalUtilsProvider(mdsalUtils);
217 public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
218 = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
219 .put("internal", InterfaceTypeInternal.class)
220 .put("vxlan", InterfaceTypeVxlan.class)
221 .put("vxlan-gpe", InterfaceTypeVxlanGpe.class)
222 .put("patch", InterfaceTypePatch.class)
223 .put("system", InterfaceTypeSystem.class)
224 .put("tap", InterfaceTypeTap.class)
225 .put("geneve", InterfaceTypeGeneve.class)
226 .put("gre", InterfaceTypeGre.class)
227 .put("ipsec_gre", InterfaceTypeIpsecGre.class)
228 .put("gre64", InterfaceTypeGre64.class)
229 .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
230 .put("lisp", InterfaceTypeLisp.class)
231 .put("dpdk", InterfaceTypeDpdk.class)
232 .put("dpdkr", InterfaceTypeDpdkr.class)
233 .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
234 .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
235 .put("dpdkvhostuserclient", InterfaceTypeDpdkvhostuserclient.class)
238 public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>,String> OVSDB_PROTOCOL_MAP
239 = new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>,String>()
240 .put(OvsdbBridgeProtocolOpenflow10.class,"OpenFlow10")
241 .put(OvsdbBridgeProtocolOpenflow11.class,"OpenFlow11")
242 .put(OvsdbBridgeProtocolOpenflow12.class,"OpenFlow12")
243 .put(OvsdbBridgeProtocolOpenflow13.class,"OpenFlow13")
244 .put(OvsdbBridgeProtocolOpenflow14.class,"OpenFlow14")
245 .put(OvsdbBridgeProtocolOpenflow15.class,"OpenFlow15")
248 private static final ImmutableBiMap<Class<? extends OvsdbFailModeBase>,String> OVSDB_FAIL_MODE_MAP
249 = new ImmutableBiMap.Builder<Class<? extends OvsdbFailModeBase>,String>()
250 .put(OvsdbFailModeStandalone.class,"standalone")
251 .put(OvsdbFailModeSecure.class,"secure")
254 public static NodeId createNodeId(IpAddress ip, PortNumber port) {
255 String uriString = OVSDB_URI_PREFIX + "://" + ip.stringValue() + ":" + port.getValue();
256 Uri uri = new Uri(uriString);
257 return new NodeId(uri);
260 public static Node createNode(ConnectionInfo key) {
261 NodeBuilder nodeBuilder = new NodeBuilder();
262 nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()));
263 nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
264 return nodeBuilder.build();
267 public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
268 OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
269 ovsdbNodeBuilder.setConnectionInfo(key);
270 return ovsdbNodeBuilder.build();
273 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
274 return InstanceIdentifier
275 .create(NetworkTopology.class)
276 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
277 .child(Node.class,new NodeKey(nodeId));
280 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeKey ovsdbNodeKey, String bridgeName) {
281 return createInstanceIdentifier(createManagedNodeId(ovsdbNodeKey.getNodeId(), bridgeName));
284 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
285 return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
288 public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
289 InstanceIdentifier<Node> path = InstanceIdentifier
290 .create(NetworkTopology.class)
291 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
292 .child(Node.class,createNodeKey(ip,port));
293 LOG.debug("Created ovsdb path: {}",path);
297 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, OvsdbBridgeName bridgeName) {
298 return createInstanceIdentifier(createManagedNodeId(key, bridgeName));
301 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, String bridgeName) {
302 return createInstanceIdentifier(key, new OvsdbBridgeName(bridgeName));
305 public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName) {
307 InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
308 .create(NetworkTopology.class)
309 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
310 .child(Node.class,node.key())
311 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
313 LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
314 return terminationPointPath;
317 public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
318 return new NodeKey(createNodeId(ip, port));
321 public static NodeId createManagedNodeId(NodeId ovsdbNodeId, String bridgeName) {
322 return new NodeId(ovsdbNodeId.getValue()
323 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName);
326 public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
327 return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
330 public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
331 return new NodeId(createNodeId(ip,port).getValue()
332 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
335 public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
336 NodeKey nodeKey = iid.firstKeyOf(Node.class);
337 return nodeKey.getNodeId();
340 public OvsdbNodeAugmentation extractOvsdbNode(Node node) {
341 return node.augmentation(OvsdbNodeAugmentation.class);
344 public static IpAddress createIpAddress(InetAddress address) {
346 if (address instanceof Inet4Address) {
347 ip = createIpAddress((Inet4Address)address);
348 } else if (address instanceof Inet6Address) {
349 ip = createIpAddress((Inet6Address)address);
354 public static IpAddress createIpAddress(Inet4Address address) {
355 return IetfInetUtil.INSTANCE.ipAddressFor(address);
358 public static IpAddress createIpAddress(Inet6Address address) {
359 Ipv6Address ipv6 = new Ipv6Address(address.getHostAddress());
360 return new IpAddress(ipv6);
363 public ConnectionInfo getConnectionInfo(Node ovsdbNode) {
364 ConnectionInfo connectionInfo = null;
365 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(ovsdbNode);
366 if (ovsdbNodeAugmentation != null) {
367 connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
369 return connectionInfo;
372 public static ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
373 InetAddress inetAddress = null;
375 inetAddress = InetAddress.getByName(addressStr);
376 } catch (UnknownHostException e) {
377 LOG.warn("Could not allocate InetAddress", e);
380 IpAddress address = createIpAddress(inetAddress);
381 PortNumber port = new PortNumber(Integer.parseInt(portStr));
383 LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
384 .setRemoteIp(address)
387 return new ConnectionInfoBuilder()
388 .setRemoteIp(address)
393 public static String connectionInfoToString(final ConnectionInfo connectionInfo) {
394 return connectionInfo.getRemoteIp().stringValue() + ":" + connectionInfo.getRemotePort().getValue();
397 public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
398 return addOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
401 public boolean addOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
402 boolean result = provider.put(LogicalDatastoreType.CONFIGURATION,
403 createInstanceIdentifier(connectionInfo),
404 createNode(connectionInfo));
407 Thread.sleep(timeout);
408 } catch (InterruptedException e) {
409 LOG.warn("Interrupted while waiting after adding OVSDB node {}",
410 connectionInfoToString(connectionInfo), e);
416 public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
417 return provider.read(LogicalDatastoreType.OPERATIONAL,
418 createInstanceIdentifier(connectionInfo));
421 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
422 return deleteOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
425 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
426 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
427 createInstanceIdentifier(connectionInfo));
430 Thread.sleep(timeout);
431 } catch (InterruptedException e) {
432 LOG.warn("Interrupted while waiting after deleting OVSDB node {}",
433 connectionInfoToString(connectionInfo), e);
439 public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
440 return connectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
443 public Node connectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
444 addOvsdbNode(connectionInfo, timeout);
445 Node node = getOvsdbNode(connectionInfo);
446 LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
450 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
451 return disconnectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
454 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
455 deleteOvsdbNode(connectionInfo, timeout);
456 LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
460 public List<ControllerEntry> createControllerEntry(String controllerTarget) {
461 List<ControllerEntry> controllerEntriesList = new ArrayList<>();
462 controllerEntriesList.add(new ControllerEntryBuilder()
463 .setTarget(new Uri(controllerTarget))
465 return controllerEntriesList;
469 * Extract the <code>store</code> type data store contents for the particular bridge identified by
470 * <code>bridgeName</code>.
472 * @param connectionInfo address for the node
473 * @param bridgeName name of the bridge
474 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
475 * @return <code>store</code> type data store contents
477 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
478 LogicalDatastoreType store) {
479 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
480 Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
481 if (bridgeNode != null) {
482 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
484 return ovsdbBridgeAugmentation;
488 * Extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
489 * identified by <code>bridgeName</code>.
491 * @param connectionInfo address for the node
492 * @param bridgeName name of the bridge
493 * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
494 * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
496 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
497 return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
501 * Extract the node contents from <code>store</code> type data store for the
502 * bridge identified by <code>bridgeName</code>.
504 * @param connectionInfo address for the node
505 * @param bridgeName name of the bridge
506 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
507 * @return <code>store</code> type data store contents
509 public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
510 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
511 return provider.read(store, bridgeIid);
514 public Node getBridgeNode(Node node, String bridgeName) {
515 OvsdbBridgeAugmentation bridge = extractBridgeAugmentation(node);
516 if (bridge != null && bridge.getBridgeName().getValue().equals(bridgeName)) {
519 return readBridgeNode(node, bridgeName);
523 public Node readBridgeNode(Node node, String name) {
524 Node ovsdbNode = node;
525 if (extractNodeAugmentation(ovsdbNode) == null) {
526 ovsdbNode = readOvsdbNode(node);
527 if (ovsdbNode == null) {
531 Node bridgeNode = null;
532 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
533 if (connectionInfo != null) {
534 InstanceIdentifier<Node> bridgeIid =
535 createInstanceIdentifier(node.key(), name);
536 bridgeNode = provider.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
541 public OvsdbNodeAugmentation extractNodeAugmentation(Node node) {
542 return node.augmentation(OvsdbNodeAugmentation.class);
545 public OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
549 return node.augmentation(OvsdbBridgeAugmentation.class);
552 public Node readOvsdbNode(Node bridgeNode) {
553 Node ovsdbNode = null;
554 OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
555 if (bridgeAugmentation != null) {
556 InstanceIdentifier<Node> ovsdbNodeIid =
557 (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
558 ovsdbNode = provider.read(LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
560 LOG.debug("readOvsdbNode: Provided node is not a bridge node : {}",bridgeNode);
565 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
566 return deleteBridge(connectionInfo, bridgeName, OVSDB_UPDATE_TIMEOUT);
569 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName, long timeout) {
570 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
571 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
574 Thread.sleep(timeout);
575 } catch (InterruptedException e) {
576 LOG.warn("Interrupted while waiting after deleting bridge {}", bridgeName, e);
582 public List<ProtocolEntry> createMdsalProtocols() {
583 List<ProtocolEntry> protocolList = new ArrayList<>();
584 ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
585 OVSDB_PROTOCOL_MAP.inverse();
586 protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
591 * base method for adding test bridges. Other helper methods used to create bridges should utilize this method.
593 * @param connectionInfo
594 * @param bridgeIid if passed null, one is created
595 * @param bridgeName cannot be null
596 * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
597 * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
598 * @param failMode toggles whether default fail mode is set for the bridge
599 * @param setManagedBy toggles whether to setManagedBy for the bridge
600 * @param dpType if passed null, this parameter is ignored
601 * @param externalIds if passed null, this parameter is ignored
602 * @param otherConfig if passed null, this parameter is ignored
603 * @return success of bridge addition
604 * @throws InterruptedException
606 public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
607 final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
608 final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
609 final Class<? extends DatapathTypeBase> dpType,
610 final List<BridgeExternalIds> externalIds,
611 final List<ControllerEntry> controllerEntries,
612 final List<BridgeOtherConfigs> otherConfigs,
613 final String dpid, long timeout) throws InterruptedException {
615 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
616 if (bridgeIid == null) {
617 bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
619 if (bridgeNodeId == null) {
620 bridgeNodeId = createManagedNodeId(bridgeIid);
622 bridgeNodeBuilder.setNodeId(bridgeNodeId);
623 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
624 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
625 if (setProtocolEntries) {
626 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
628 if (failMode != null) {
629 ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
632 setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
634 if (dpType != null) {
635 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
637 if (externalIds != null) {
638 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
640 if (controllerEntries != null) {
641 ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
643 if (otherConfigs != null) {
644 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
646 if (dpid != null && !dpid.isEmpty()) {
647 DatapathId datapathId = new DatapathId(dpid);
648 ovsdbBridgeAugmentationBuilder.setDatapathId(datapathId);
650 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
651 LOG.debug("Built with the intent to store bridge data {}",
652 ovsdbBridgeAugmentationBuilder.toString());
653 boolean result = provider.merge(LogicalDatastoreType.CONFIGURATION,
654 bridgeIid, bridgeNodeBuilder.build());
656 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
661 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
662 final Class<? extends DatapathTypeBase> dpType, String mac) {
663 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, mac, null, null);
666 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
667 final Class<? extends DatapathTypeBase> dpType, String mac,
668 Long maxBackoff, Long inactivityProbe) {
669 List<BridgeOtherConfigs> otherConfigs = new ArrayList<>();
671 BridgeOtherConfigsBuilder macOtherConfigBuilder = new BridgeOtherConfigsBuilder();
672 macOtherConfigBuilder.setBridgeOtherConfigKey("hwaddr");
673 macOtherConfigBuilder.setBridgeOtherConfigValue(mac);
674 otherConfigs.add(macOtherConfigBuilder.build());
677 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, otherConfigs, null, null);
680 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
681 final Class<? extends DatapathTypeBase> dpType,
682 List<BridgeOtherConfigs> otherConfigs,
683 Long maxBackoff, Long inactivityProbe) {
686 LOG.info("addBridge: node: {}, bridgeName: {}, controller(s): {}", ovsdbNode, bridgeName, controllersStr);
687 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
688 if (connectionInfo != null) {
689 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
690 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
691 NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
692 bridgeNodeBuilder.setNodeId(bridgeNodeId);
693 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
694 ovsdbBridgeAugmentationBuilder.setControllerEntry(createControllerEntries(
695 controllersStr, maxBackoff, inactivityProbe));
696 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
697 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
698 ovsdbBridgeAugmentationBuilder.setFailMode(OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
699 // TODO: Currently netvirt relies on this function to set disabled-in-band=true. However,
700 // TODO (cont): a better design would be to have netvirt pass that in. That way this function
701 // TODO (cont): can take a null otherConfigs to erase other_configs.
702 if (otherConfigs == null) {
703 otherConfigs = new ArrayList<>();
705 BridgeOtherConfigsBuilder bridgeOtherConfigsBuilder = new BridgeOtherConfigsBuilder();
706 bridgeOtherConfigsBuilder.setBridgeOtherConfigKey(DISABLE_IN_BAND);
707 bridgeOtherConfigsBuilder.setBridgeOtherConfigValue("true");
708 otherConfigs.add(bridgeOtherConfigsBuilder.build());
709 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
710 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(setBridgeExternalIds());
711 setManagedByForBridge(ovsdbBridgeAugmentationBuilder, ovsdbNode.key());
712 if (dpType != null) {
713 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
715 if (isOvsdbNodeDpdk(ovsdbNode)) {
716 ovsdbBridgeAugmentationBuilder.setDatapathType(DatapathTypeNetdev.class);
718 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
720 Node node = bridgeNodeBuilder.build();
721 result = provider.put(LogicalDatastoreType.CONFIGURATION, bridgeIid, node);
722 LOG.info("addBridge: result: {}", result);
724 throw new InvalidParameterException("Could not find ConnectionInfo");
730 * Set the controllers of an existing bridge node.
732 * @param ovsdbNode where the bridge is
733 * @param bridgeName Name of the bridge
734 * @param controllers controller strings
735 * @return success if the write to md-sal was successful
737 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers) {
738 return setBridgeController(ovsdbNode, bridgeName, controllers, null, null);
742 * Set the controllers of an existing bridge node.
744 * @param ovsdbNode where the bridge is
745 * @param bridgeName Name of the bridge
746 * @param controllers controller strings
747 * @param maxBackoff Max backoff in milliseconds
748 * @param inactivityProbe inactivity probe in milliseconds
749 * @return success if the write to md-sal was successful
751 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers,
752 Long maxBackoff, Long inactivityProbe) {
753 LOG.debug("setBridgeController: ovsdbNode: {}, bridgeNode: {}, controller(s): {}",
754 ovsdbNode, bridgeName, controllers);
756 InstanceIdentifier<Node> bridgeNodeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
757 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid);
758 if (bridgeNode == null) {
759 LOG.info("setBridgeController could not find bridge in configuration {}", bridgeNodeIid);
763 OvsdbBridgeAugmentation bridgeAug = extractBridgeAugmentation(bridgeNode);
765 //Only add controller entries that do not already exist on this bridge
766 List<ControllerEntry> existingControllerEntries = bridgeAug.getControllerEntry();
767 List<ControllerEntry> newControllerEntries = new ArrayList<>();
768 if (existingControllerEntries != null) {
770 for (ControllerEntry newEntry : createControllerEntries(controllers, maxBackoff, inactivityProbe)) {
771 for (ControllerEntry existingEntry : existingControllerEntries) {
772 if (newEntry.getTarget().equals(existingEntry.getTarget())) {
773 continue NEW_ENTRY_LOOP;
776 newControllerEntries.add(newEntry);
779 newControllerEntries = createControllerEntries(controllers,maxBackoff, inactivityProbe);
782 if (newControllerEntries.isEmpty()) {
786 NodeBuilder nodeBuilder = new NodeBuilder(bridgeNode);
787 OvsdbBridgeAugmentationBuilder augBuilder = new OvsdbBridgeAugmentationBuilder(bridgeAug);
789 augBuilder.setControllerEntry(newControllerEntries);
790 nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, augBuilder.build());
791 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
792 return provider.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, nodeBuilder.build());
795 private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
796 final ConnectionInfo connectionInfo) {
797 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
798 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
801 public boolean addTerminationPoint(
802 Node bridgeNode, String portName, String type, Map<String, String> options,
803 Map<String, String> externalIds) {
804 return addTerminationPoint(bridgeNode, portName, type, options, externalIds, null);
807 public boolean addTerminationPoint(
808 Node bridgeNode, String portName, String type, Map<String, String> options, Map<String, String> externalIds,
810 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
812 tpAugmentationBuilder.setName(portName);
813 tpAugmentationBuilder.setOfport(ofPort);
815 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
818 if (options != null && options.size() > 0) {
819 List<Options> optionsList = new ArrayList<>();
820 for (Map.Entry<String, String> entry : options.entrySet()) {
821 OptionsBuilder optionsBuilder = new OptionsBuilder();
822 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
823 optionsBuilder.setOption(entry.getKey());
824 optionsBuilder.setValue(entry.getValue());
825 optionsList.add(optionsBuilder.build());
827 tpAugmentationBuilder.setOptions(optionsList);
830 if (externalIds != null && externalIds.size() > 0) {
831 List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
832 for (Map.Entry<String, String> entry : externalIds.entrySet()) {
833 InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
834 interfaceExternalIdsBuilder.withKey(new InterfaceExternalIdsKey(entry.getKey()));
835 interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
836 interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
837 externalIdsList.add(interfaceExternalIdsBuilder.build());
839 tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
842 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
843 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
844 tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
845 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
846 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
849 public Boolean addTerminationPoint(Node bridgeNode, String portName, String type) {
850 return addTerminationPoint(bridgeNode, portName, type, Collections.EMPTY_MAP, null);
853 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
854 String type, Map<String, String> options) {
855 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
857 tpAugmentationBuilder.setName(portName);
859 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
862 List<Options> optionsList = new ArrayList<>();
863 for (Map.Entry<String, String> entry : options.entrySet()) {
864 OptionsBuilder optionsBuilder = new OptionsBuilder();
865 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
866 optionsBuilder.setOption(entry.getKey());
867 optionsBuilder.setValue(entry.getValue());
868 optionsList.add(optionsBuilder.build());
870 tpAugmentationBuilder.setOptions(optionsList);
872 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
873 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
874 tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
875 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
876 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
879 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
880 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
881 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
882 new OvsdbTerminationPointAugmentationBuilder();
884 tpAugmentationBuilder.setName(portName);
886 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
888 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
889 tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
890 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
891 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
894 public Boolean addPatchTerminationPoint(Node node, String bridgeName, String portName, String peerPortName) {
895 Map<String, String> option = new HashMap<>();
896 option.put("peer", peerPortName);
897 return addTerminationPoint(node, bridgeName, portName, PATCH_PORT_TYPE, option);
900 private String getControllerIPAddress() {
901 String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
902 if (addressString != null) {
904 if (InetAddress.getByName(addressString) != null) {
905 return addressString;
907 } catch (UnknownHostException e) {
908 LOG.error("Host {} is invalid", addressString, e);
912 addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
913 if (addressString != null) {
915 if (InetAddress.getByName(addressString) != null) {
916 return addressString;
918 } catch (UnknownHostException e) {
919 LOG.error("Host {} is invalid", addressString, e);
926 private short getControllerOFPort() {
927 short openFlowPort = OPENFLOW_PORT;
928 String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
929 if (portString != null) {
931 openFlowPort = Short.parseShort(portString);
932 } catch (NumberFormatException e) {
933 LOG.warn("Invalid port:{}, use default({})", portString,
940 public List<String> getControllersFromOvsdbNode(Node node) {
941 List<String> controllersStr = new ArrayList<>();
943 String controllerIpStr = getControllerIPAddress();
944 if (controllerIpStr != null) {
945 // If codepath makes it here, the ip address to be used was explicitly provided.
946 // Being so, also fetch openflowPort provided via ConfigProperties.
947 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
948 + ":" + controllerIpStr + ":" + getControllerOFPort());
950 // Check if ovsdb node has manager entries
951 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(node);
952 if (ovsdbNodeAugmentation != null) {
953 List<ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
954 if (managerEntries != null && !managerEntries.isEmpty()) {
955 for (ManagerEntry managerEntry : managerEntries) {
956 if (managerEntry == null || managerEntry.getTarget() == null) {
959 String managerStr = managerEntry.getTarget().getValue().toLowerCase(Locale.ROOT);
960 int firstColonIdx = managerStr.indexOf(':');
961 int lastColonIdx = managerStr.lastIndexOf(':');
962 if (lastColonIdx <= firstColonIdx) {
965 controllerIpStr = managerStr.substring(firstColonIdx + 1, lastColonIdx);
966 if (managerStr.startsWith("tcp")) {
967 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL + ":" + controllerIpStr + ":"
968 + getControllerOFPort());
969 } else if (managerStr.startsWith("ssl")) {
970 controllersStr.add(OPENFLOW_SECURE_PROTOCOL + ":" + controllerIpStr + ":"
971 + getControllerOFPort());
972 } else if (managerStr.startsWith("ptcp")) {
973 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
974 /* If we're connected to switch ptcp, only then use connection info
975 to configure controller. Ptcp is configured as:
976 Manager "ptcp:<port>:<ip>"
979 String managerPortStr = managerStr.split(":", 3)[1];
980 if (connectionInfo != null && connectionInfo.getLocalIp() != null
981 && connectionInfo.getRemotePort() != null
982 && managerPortStr.equals(connectionInfo.getRemotePort().toString())) {
983 IpAddress controllerIp = connectionInfo.getLocalIp();
984 if (controllerIp.getIpv6Address() != null) {
985 controllerIpStr = "[" + connectionInfo.getLocalIp().stringValue() + "]";
987 controllerIpStr = connectionInfo.getLocalIp().stringValue();
989 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
990 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
992 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
994 } else if (managerStr.startsWith("pssl")) {
995 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
996 if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
997 controllerIpStr = connectionInfo.getLocalIp().stringValue();
998 controllersStr.add(OPENFLOW_SECURE_PROTOCOL
999 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
1001 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
1004 LOG.trace("Skipping manager entry {} for node {}",
1005 managerEntry.getTarget(), node.getNodeId().getValue());
1009 LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
1014 if (controllersStr.isEmpty()) {
1015 LOG.warn("Failed to determine OpenFlow controller ip address");
1016 } else if (LOG.isDebugEnabled()) {
1017 LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(),
1018 controllersStr.stream().collect(Collectors.joining(" ")));
1020 return controllersStr;
1023 public long getDataPathId(Node node) {
1025 String datapathId = getDatapathId(node);
1026 if (datapathId != null) {
1027 dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
1032 public String getDataPathIdStr(final Node node) {
1034 long dpId = getDataPathId(node);
1036 return String.valueOf(dpId);
1043 public String getDatapathId(Node node) {
1044 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.augmentation(OvsdbBridgeAugmentation.class);
1045 return getDatapathId(ovsdbBridgeAugmentation);
1048 public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
1049 String datapathId = null;
1050 if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
1051 datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
1056 public String extractBridgeName(Node node) {
1057 return node.augmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
1060 public boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgeName) {
1061 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1062 if (ovsdbNodeAugmentation != null) {
1063 List<ManagedNodeEntry> managedNodes = ovsdbNodeAugmentation.getManagedNodeEntry();
1064 if (managedNodes != null) {
1065 for (ManagedNodeEntry managedNode : managedNodes) {
1066 if (matchesBridgeName(managedNode, bridgeName)) {
1075 // see OVSDB-470 for background
1076 private static boolean matchesBridgeName(ManagedNodeEntry managedNode, String bridgeName) {
1077 InstanceIdentifier<?> bridgeIid = managedNode.getBridgeRef().getValue();
1078 for (PathArgument bridgeIidPathArg : bridgeIid.getPathArguments()) {
1079 if (bridgeIidPathArg instanceof IdentifiableItem<?, ?>) {
1080 IdentifiableItem<?, ?> identifiableItem = (IdentifiableItem<?, ?>) bridgeIidPathArg;
1081 Identifier<?> key = identifiableItem.getKey();
1082 if (key instanceof NodeKey) {
1083 // Do not combine the above if with that below, we want to
1084 // avoid the toString() call in the else if this is a NodeKey
1085 NodeKey nodeKey = (NodeKey) key;
1086 if (nodeKey.getNodeId().getValue().contains(bridgeName)) {
1089 } else if (key.toString().contains(bridgeName)) {
1092 } else if (bridgeIidPathArg instanceof Item<?>) {
1093 if (((Item<?>) bridgeIidPathArg).getType().getName().contains(bridgeName)) {
1097 throw new IllegalArgumentException("Unknown kind of PathArgument: " + bridgeIidPathArg);
1103 public OvsdbBridgeAugmentation getBridgeFromConfig(Node node, String bridge) {
1104 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
1105 InstanceIdentifier<Node> bridgeIid =
1106 createInstanceIdentifier(node.key(), bridge);
1107 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeIid);
1108 if (bridgeNode != null) {
1109 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
1111 return ovsdbBridgeAugmentation;
1114 private static void setManagedByForBridge(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
1115 NodeKey ovsdbNodeKey) {
1116 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(ovsdbNodeKey.getNodeId());
1117 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
1120 public boolean isOvsdbNodeDpdk(Node ovsdbNode) {
1121 boolean found = false;
1122 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1123 if (ovsdbNodeAugmentation != null) {
1124 List<InterfaceTypeEntry> ifTypes = ovsdbNodeAugmentation.getInterfaceTypeEntry();
1125 if (ifTypes != null) {
1126 for (InterfaceTypeEntry ifType : ifTypes) {
1127 if (ifType.getInterfaceType().equals(InterfaceTypeDpdk.class)) {
1137 private static List<ControllerEntry> createControllerEntries(List<String> controllersStr,
1138 Long maxBackoff, Long inactivityProbe) {
1139 List<ControllerEntry> controllerEntries = new ArrayList<>();
1140 if (controllersStr != null) {
1141 for (String controllerStr : controllersStr) {
1142 ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
1143 controllerEntryBuilder.setTarget(new Uri(controllerStr));
1144 if (maxBackoff != null) {
1145 controllerEntryBuilder.setMaxBackoff(maxBackoff);
1147 if (inactivityProbe != null) {
1148 controllerEntryBuilder.setInactivityProbe(inactivityProbe);
1150 controllerEntries.add(controllerEntryBuilder.build());
1153 return controllerEntries;
1156 public OvsdbTerminationPointAugmentation extractTerminationPointAugmentation(Node bridgeNode, String portName) {
1157 if (bridgeNode.augmentation(OvsdbBridgeAugmentation.class) != null) {
1158 List<OvsdbTerminationPointAugmentation> tpAugmentations = extractTerminationPointAugmentations(bridgeNode);
1159 for (OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation : tpAugmentations) {
1160 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1161 return ovsdbTerminationPointAugmentation;
1168 public List<OvsdbTerminationPointAugmentation> extractTerminationPointAugmentations(Node node) {
1169 List<OvsdbTerminationPointAugmentation> tpAugmentations = new ArrayList<>();
1171 LOG.error("extractTerminationPointAugmentations: Node value is null");
1172 return Collections.emptyList();
1174 List<TerminationPoint> terminationPoints = node.getTerminationPoint();
1175 if (terminationPoints != null && !terminationPoints.isEmpty()) {
1176 for (TerminationPoint tp : terminationPoints) {
1177 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1178 tp.augmentation(OvsdbTerminationPointAugmentation.class);
1179 if (ovsdbTerminationPointAugmentation != null) {
1180 tpAugmentations.add(ovsdbTerminationPointAugmentation);
1184 return tpAugmentations;
1188 * Extract the <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code> identified by
1189 * <code>portName</code>.
1191 public OvsdbTerminationPointAugmentation getTerminationPointOfBridge(Node node, String portName) {
1192 OvsdbTerminationPointAugmentation tpAugmentation = extractTerminationPointAugmentation(node,portName);
1193 if (tpAugmentation == null) {
1194 List<OvsdbTerminationPointAugmentation> tpAugmentations = readTerminationPointAugmentations(node);
1195 if (tpAugmentations != null) {
1196 for (OvsdbTerminationPointAugmentation ovsdbTpAugmentation : tpAugmentations) {
1197 if (ovsdbTpAugmentation.getName().equals(portName)) {
1198 return ovsdbTpAugmentation;
1203 return tpAugmentation;
1207 * Read the list of <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code>.
1209 public List<OvsdbTerminationPointAugmentation> readTerminationPointAugmentations(Node node) {
1211 LOG.error("readTerminationPointAugmentations: Node value is null");
1212 return Collections.emptyList();
1214 Node operNode = provider.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier
1215 .create(NetworkTopology.class)
1216 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
1217 .child(Node.class, new NodeKey(node.getNodeId())));
1218 if (operNode != null) {
1219 return extractTerminationPointAugmentations(operNode);
1221 return new ArrayList<>();
1225 * Get all OVSDB nodes from topology.
1226 * @return a list of nodes or null if the topology could not found
1228 public List<Node> getOvsdbNodes() {
1229 InstanceIdentifier<Topology> inst = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
1230 new TopologyKey(OVSDB_TOPOLOGY_ID));
1231 Topology topology = provider.read(LogicalDatastoreType.OPERATIONAL, inst);
1232 return topology != null ? topology.getNode() : null;
1236 * Get OpenvSwitch other-config by key.
1237 * @param node OVSDB node
1238 * @param key key to extract from other-config
1239 * @return the value for key or null if key not found
1241 public String getOpenvswitchOtherConfig(Node node, String key) {
1242 OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
1243 if (ovsdbNode == null) {
1244 Node nodeFromReadOvsdbNode = readOvsdbNode(node);
1245 if (nodeFromReadOvsdbNode != null) {
1246 ovsdbNode = nodeFromReadOvsdbNode.augmentation(OvsdbNodeAugmentation.class);
1250 if (ovsdbNode != null && ovsdbNode.getOpenvswitchOtherConfigs() != null) {
1251 for (OpenvswitchOtherConfigs openvswitchOtherConfigs : ovsdbNode.getOpenvswitchOtherConfigs()) {
1252 if (openvswitchOtherConfigs.getOtherConfigKey().equals(key)) {
1253 return openvswitchOtherConfigs.getOtherConfigValue();
1261 public static TerminationPoint getTerminationPointByExternalId(final Node bridgeNode, final String interfaceName) {
1262 if (bridgeNode.getTerminationPoint() != null) {
1263 for (TerminationPoint tp : bridgeNode.getTerminationPoint()) {
1264 OvsdbTerminationPointAugmentation ovsdbTp = tp.augmentation(OvsdbTerminationPointAugmentation.class);
1265 String externalIdValue = getExternalInterfaceIdValue(ovsdbTp);
1266 if (externalIdValue != null && externalIdValue.equals(interfaceName)) {
1267 LOG.debug("Found matching termination point with iface-id {} on bridgeNode {}, returning tp {}",
1268 interfaceName, bridgeNode, tp);
1276 // This utility shouldn't be called often, as it reads all OVSDB nodes each time - not good for scale
1277 public Node getNodeByTerminationPointExternalId(final String interfaceName) {
1278 List<Node> nodes = getOvsdbNodes();
1279 if (nodes != null) {
1280 for (Node node : nodes) {
1281 TerminationPoint tp = getTerminationPointByExternalId(node, interfaceName);
1290 public static String getExternalInterfaceIdValue(final OvsdbTerminationPointAugmentation ovsdbTp) {
1291 if (ovsdbTp != null) {
1292 List<InterfaceExternalIds> ifaceExtIds = ovsdbTp.getInterfaceExternalIds();
1293 if (ifaceExtIds != null) {
1294 for (InterfaceExternalIds entry : ifaceExtIds) {
1295 if (entry.getExternalIdKey().equals(EXTERNAL_INTERFACE_ID_KEY)) {
1296 return entry.getExternalIdValue();
1304 public String getDatapathIdFromNodeInstanceId(InstanceIdentifier<Node> nodeInstanceId) {
1305 Node node = provider.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
1306 String dpId = node != null ? getDataPathIdStr(node) : null;
1313 public static boolean compareDbVersionToMinVersion(final String dbVersion, final String minVersion) {
1314 if (dbVersion == null || minVersion == null) {
1315 LOG.error("Invalid DB version {} or minVersion {}", dbVersion, minVersion);
1318 final Matcher dbVersionMatcher = PATTERN.matcher(dbVersion);
1319 final Matcher minVersionMatcher = PATTERN.matcher(minVersion);
1320 LOG.debug("dbVersion {}, minVersion {}", dbVersion, minVersion);
1321 if (!dbVersionMatcher.find()) {
1322 LOG.error("Invalid DB version format {}", dbVersion);
1325 if (!minVersionMatcher.find()) {
1326 LOG.error("Invalid Min DB version format {}", minVersion);
1330 if (dbVersion != null && !dbVersion.isEmpty() && minVersion != null && !minVersion.isEmpty()) {
1331 final int dbVersionMatch1 = Integer.parseInt(dbVersionMatcher.group(1));
1332 final int dbVersionMatch2 = Integer.parseInt(dbVersionMatcher.group(2));
1333 final int dbVersionMatch3 = Integer.parseInt(dbVersionMatcher.group(3));
1334 final int minVersionMatch1 = Integer.parseInt(minVersionMatcher.group(1));
1335 final int minVersionMatch2 = Integer.parseInt(minVersionMatcher.group(2));
1336 final int minVersionMatch3 = Integer.parseInt(minVersionMatcher.group(3));
1337 if (dbVersionMatch1 == minVersionMatch1 && dbVersionMatch2 == minVersionMatch2
1338 && dbVersionMatch3 == minVersionMatch3) {
1342 if (dbVersionMatch1 > minVersionMatch1) {
1346 if (dbVersionMatch1 < minVersionMatch1) {
1350 // major version is equal
1351 if (dbVersionMatch2 > minVersionMatch2) {
1355 if (dbVersionMatch2 < minVersionMatch2) {
1359 if (dbVersionMatch3 > minVersionMatch3) {
1366 private List<BridgeExternalIds> setBridgeExternalIds() {
1367 List<BridgeExternalIds> externalIdsList = new ArrayList<>();
1368 externalIdsList.add(new BridgeExternalIdsBuilder()
1369 .setBridgeExternalIdKey(CREATED_BY)
1370 .setBridgeExternalIdValue(ODL)
1372 return externalIdsList;