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.MdsalUtils;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdk;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkr;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhost;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhostuser;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhostuserclient;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGeneve;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre64;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeInternal;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre64;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeLisp;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypePatch;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeSystem;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeTap;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlanGpe;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow10;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow11;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow12;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow13;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow14;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow15;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeSecure;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeStandalone;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryKey;
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.InterfaceTypeEntryKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntryKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntryKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
104 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
105 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
106 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
107 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
108 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
109 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
110 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
111 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
112 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
113 import org.opendaylight.yangtools.yang.binding.DataObject;
114 import org.opendaylight.yangtools.yang.binding.Identifier;
115 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
116 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
117 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
118 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
119 import org.slf4j.Logger;
120 import org.slf4j.LoggerFactory;
122 public class SouthboundUtils {
123 private abstract static class UtilsProvider {
125 abstract <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path);
127 abstract boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path);
129 abstract <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path,
132 abstract <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data);
135 private static final class MdsalUtilsProvider extends UtilsProvider {
136 private final MdsalUtils mdsalUtils;
138 MdsalUtilsProvider(final MdsalUtils mdsalUtils) {
139 this.mdsalUtils = requireNonNull(mdsalUtils);
143 <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path) {
144 return mdsalUtils.read(store, path);
148 <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
149 return mdsalUtils.put(store, path, data);
153 boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
154 return mdsalUtils.delete(store, path);
158 <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
159 return mdsalUtils.merge(store, path, data);
163 private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
164 private static final int OVSDB_UPDATE_TIMEOUT = 1000;
165 public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
166 public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
167 public static final String OPENFLOW_SECURE_PROTOCOL = "ssl";
168 public static final short OPENFLOW_PORT = 6653;
169 public static final String OVSDB_URI_PREFIX = "ovsdb";
170 public static final String BRIDGE_URI_PREFIX = "bridge";
171 private static final String DISABLE_IN_BAND = "disable-in-band";
172 private static final String PATCH_PORT_TYPE = "patch";
173 // External ID key used for mapping between an OVSDB port and an interface name
174 private static final InterfaceExternalIdsKey EXTERNAL_INTERFACE_ID_KEY = new InterfaceExternalIdsKey("iface-id");
175 private static final String CREATED_BY = "created_by";
176 private static final String ODL = "odl";
177 private static final String FORMAT = "(\\d+)\\.(\\d+)\\.(\\d+)";
178 private static final Pattern PATTERN = Pattern.compile(FORMAT);
179 // DPDK interface type
180 private static final InterfaceTypeEntryKey DPDK_IFACE_KEY = new InterfaceTypeEntryKey(InterfaceTypeDpdk.class);
182 private final UtilsProvider provider;
184 public SouthboundUtils(MdsalUtils mdsalUtils) {
185 provider = new MdsalUtilsProvider(mdsalUtils);
188 public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
189 = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
190 .put("internal", InterfaceTypeInternal.class)
191 .put("vxlan", InterfaceTypeVxlan.class)
192 .put("vxlan-gpe", InterfaceTypeVxlanGpe.class)
193 .put("patch", InterfaceTypePatch.class)
194 .put("system", InterfaceTypeSystem.class)
195 .put("tap", InterfaceTypeTap.class)
196 .put("geneve", InterfaceTypeGeneve.class)
197 .put("gre", InterfaceTypeGre.class)
198 .put("ipsec_gre", InterfaceTypeIpsecGre.class)
199 .put("gre64", InterfaceTypeGre64.class)
200 .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
201 .put("lisp", InterfaceTypeLisp.class)
202 .put("dpdk", InterfaceTypeDpdk.class)
203 .put("dpdkr", InterfaceTypeDpdkr.class)
204 .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
205 .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
206 .put("dpdkvhostuserclient", InterfaceTypeDpdkvhostuserclient.class)
209 public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>,String> OVSDB_PROTOCOL_MAP
210 = new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>,String>()
211 .put(OvsdbBridgeProtocolOpenflow10.class,"OpenFlow10")
212 .put(OvsdbBridgeProtocolOpenflow11.class,"OpenFlow11")
213 .put(OvsdbBridgeProtocolOpenflow12.class,"OpenFlow12")
214 .put(OvsdbBridgeProtocolOpenflow13.class,"OpenFlow13")
215 .put(OvsdbBridgeProtocolOpenflow14.class,"OpenFlow14")
216 .put(OvsdbBridgeProtocolOpenflow15.class,"OpenFlow15")
219 private static final ImmutableBiMap<Class<? extends OvsdbFailModeBase>,String> OVSDB_FAIL_MODE_MAP
220 = new ImmutableBiMap.Builder<Class<? extends OvsdbFailModeBase>,String>()
221 .put(OvsdbFailModeStandalone.class,"standalone")
222 .put(OvsdbFailModeSecure.class,"secure")
225 public static NodeId createNodeId(IpAddress ip, PortNumber port) {
226 String uriString = OVSDB_URI_PREFIX + "://" + ip.stringValue() + ":" + port.getValue();
227 Uri uri = new Uri(uriString);
228 return new NodeId(uri);
231 public static Node createNode(ConnectionInfo key) {
232 return new NodeBuilder()
233 .setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()))
234 .addAugmentation(createOvsdbAugmentation(key))
238 public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
239 return new OvsdbNodeAugmentationBuilder().setConnectionInfo(key).build();
242 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
243 return InstanceIdentifier
244 .create(NetworkTopology.class)
245 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
246 .child(Node.class,new NodeKey(nodeId));
249 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeKey ovsdbNodeKey, String bridgeName) {
250 return createInstanceIdentifier(createManagedNodeId(ovsdbNodeKey.getNodeId(), bridgeName));
253 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
254 return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
257 public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
258 InstanceIdentifier<Node> path = InstanceIdentifier
259 .create(NetworkTopology.class)
260 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
261 .child(Node.class,createNodeKey(ip,port));
262 LOG.debug("Created ovsdb path: {}",path);
266 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, OvsdbBridgeName bridgeName) {
267 return createInstanceIdentifier(createManagedNodeId(key, bridgeName));
270 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, String bridgeName) {
271 return createInstanceIdentifier(key, new OvsdbBridgeName(bridgeName));
274 public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName) {
276 InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
277 .create(NetworkTopology.class)
278 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
279 .child(Node.class,node.key())
280 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
282 LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
283 return terminationPointPath;
286 public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
287 return new NodeKey(createNodeId(ip, port));
290 public static NodeId createManagedNodeId(NodeId ovsdbNodeId, String bridgeName) {
291 return new NodeId(ovsdbNodeId.getValue()
292 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName);
295 public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
296 return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
299 public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
300 return new NodeId(createNodeId(ip,port).getValue()
301 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
304 public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
305 NodeKey nodeKey = iid.firstKeyOf(Node.class);
306 return nodeKey.getNodeId();
309 public OvsdbNodeAugmentation extractOvsdbNode(Node node) {
310 return node.augmentation(OvsdbNodeAugmentation.class);
313 public static IpAddress createIpAddress(InetAddress address) {
315 if (address instanceof Inet4Address) {
316 ip = createIpAddress((Inet4Address)address);
317 } else if (address instanceof Inet6Address) {
318 ip = createIpAddress((Inet6Address)address);
323 public static IpAddress createIpAddress(Inet4Address address) {
324 return IetfInetUtil.INSTANCE.ipAddressFor(address);
327 public static IpAddress createIpAddress(Inet6Address address) {
328 Ipv6Address ipv6 = new Ipv6Address(address.getHostAddress());
329 return new IpAddress(ipv6);
332 public ConnectionInfo getConnectionInfo(Node ovsdbNode) {
333 ConnectionInfo connectionInfo = null;
334 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(ovsdbNode);
335 if (ovsdbNodeAugmentation != null) {
336 connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
338 return connectionInfo;
341 public static ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
342 InetAddress inetAddress = null;
344 inetAddress = InetAddress.getByName(addressStr);
345 } catch (UnknownHostException e) {
346 LOG.warn("Could not allocate InetAddress", e);
349 IpAddress address = createIpAddress(inetAddress);
350 PortNumber port = new PortNumber(Integer.parseInt(portStr));
352 LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
353 .setRemoteIp(address)
356 return new ConnectionInfoBuilder()
357 .setRemoteIp(address)
362 public static String connectionInfoToString(final ConnectionInfo connectionInfo) {
363 return connectionInfo.getRemoteIp().stringValue() + ":" + connectionInfo.getRemotePort().getValue();
366 public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
367 return addOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
370 public boolean addOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
371 boolean result = provider.put(LogicalDatastoreType.CONFIGURATION,
372 createInstanceIdentifier(connectionInfo),
373 createNode(connectionInfo));
376 Thread.sleep(timeout);
377 } catch (InterruptedException e) {
378 LOG.warn("Interrupted while waiting after adding OVSDB node {}",
379 connectionInfoToString(connectionInfo), e);
385 public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
386 return provider.read(LogicalDatastoreType.OPERATIONAL,
387 createInstanceIdentifier(connectionInfo));
390 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
391 return deleteOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
394 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
395 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
396 createInstanceIdentifier(connectionInfo));
399 Thread.sleep(timeout);
400 } catch (InterruptedException e) {
401 LOG.warn("Interrupted while waiting after deleting OVSDB node {}",
402 connectionInfoToString(connectionInfo), e);
408 public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
409 return connectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
412 public Node connectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
413 addOvsdbNode(connectionInfo, timeout);
414 Node node = getOvsdbNode(connectionInfo);
415 LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
419 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
420 return disconnectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
423 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
424 deleteOvsdbNode(connectionInfo, timeout);
425 LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
429 public List<ControllerEntry> createControllerEntry(String controllerTarget) {
430 List<ControllerEntry> controllerEntriesList = new ArrayList<>();
431 controllerEntriesList.add(new ControllerEntryBuilder()
432 .setTarget(new Uri(controllerTarget))
434 return controllerEntriesList;
438 * Extract the <code>store</code> type data store contents for the particular bridge identified by
439 * <code>bridgeName</code>.
441 * @param connectionInfo address for the node
442 * @param bridgeName name of the bridge
443 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
444 * @return <code>store</code> type data store contents
446 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
447 LogicalDatastoreType store) {
448 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
449 Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
450 if (bridgeNode != null) {
451 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
453 return ovsdbBridgeAugmentation;
457 * Extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
458 * identified by <code>bridgeName</code>.
460 * @param connectionInfo address for the node
461 * @param bridgeName name of the bridge
462 * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
463 * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
465 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
466 return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
470 * Extract the node contents from <code>store</code> type data store for the
471 * bridge identified by <code>bridgeName</code>.
473 * @param connectionInfo address for the node
474 * @param bridgeName name of the bridge
475 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
476 * @return <code>store</code> type data store contents
478 public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
479 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
480 return provider.read(store, bridgeIid);
483 public Node getBridgeNode(Node node, String bridgeName) {
484 OvsdbBridgeAugmentation bridge = extractBridgeAugmentation(node);
485 if (bridge != null && bridge.getBridgeName().getValue().equals(bridgeName)) {
488 return readBridgeNode(node, bridgeName);
492 public Node readBridgeNode(Node node, String name) {
493 Node ovsdbNode = node;
494 if (extractNodeAugmentation(ovsdbNode) == null) {
495 ovsdbNode = readOvsdbNode(node);
496 if (ovsdbNode == null) {
500 Node bridgeNode = null;
501 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
502 if (connectionInfo != null) {
503 InstanceIdentifier<Node> bridgeIid =
504 createInstanceIdentifier(node.key(), name);
505 bridgeNode = provider.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
510 public OvsdbNodeAugmentation extractNodeAugmentation(Node node) {
511 return node.augmentation(OvsdbNodeAugmentation.class);
514 public OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
518 return node.augmentation(OvsdbBridgeAugmentation.class);
521 public Node readOvsdbNode(Node bridgeNode) {
522 Node ovsdbNode = null;
523 OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
524 if (bridgeAugmentation != null) {
525 InstanceIdentifier<Node> ovsdbNodeIid =
526 (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
527 ovsdbNode = provider.read(LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
529 LOG.debug("readOvsdbNode: Provided node is not a bridge node : {}",bridgeNode);
534 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
535 return deleteBridge(connectionInfo, bridgeName, OVSDB_UPDATE_TIMEOUT);
538 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName, long timeout) {
539 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
540 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
543 Thread.sleep(timeout);
544 } catch (InterruptedException e) {
545 LOG.warn("Interrupted while waiting after deleting bridge {}", bridgeName, e);
551 public List<ProtocolEntry> createMdsalProtocols() {
552 List<ProtocolEntry> protocolList = new ArrayList<>();
553 ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
554 OVSDB_PROTOCOL_MAP.inverse();
555 protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
560 * base method for adding test bridges. Other helper methods used to create bridges should utilize this method.
562 * @param connectionInfo
563 * @param bridgeIid if passed null, one is created
564 * @param bridgeName cannot be null
565 * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
566 * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
567 * @param failMode toggles whether default fail mode is set for the bridge
568 * @param setManagedBy toggles whether to setManagedBy for the bridge
569 * @param dpType if passed null, this parameter is ignored
570 * @param externalIds if passed null, this parameter is ignored
571 * @param otherConfig if passed null, this parameter is ignored
572 * @return success of bridge addition
573 * @throws InterruptedException
575 public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
576 final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
577 final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
578 final Class<? extends DatapathTypeBase> dpType,
579 final List<BridgeExternalIds> externalIds,
580 final List<ControllerEntry> controllerEntries,
581 final List<BridgeOtherConfigs> otherConfigs,
582 final String dpid, long timeout) throws InterruptedException {
584 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
585 if (bridgeIid == null) {
586 bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
588 if (bridgeNodeId == null) {
589 bridgeNodeId = createManagedNodeId(bridgeIid);
591 bridgeNodeBuilder.setNodeId(bridgeNodeId);
592 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
593 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
594 if (setProtocolEntries) {
595 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
597 if (failMode != null) {
598 ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
601 setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
603 if (dpType != null) {
604 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
606 if (externalIds != null) {
607 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
609 if (controllerEntries != null) {
610 ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
612 if (otherConfigs != null) {
613 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
615 if (dpid != null && !dpid.isEmpty()) {
616 DatapathId datapathId = new DatapathId(dpid);
617 ovsdbBridgeAugmentationBuilder.setDatapathId(datapathId);
619 bridgeNodeBuilder.addAugmentation(ovsdbBridgeAugmentationBuilder.build());
620 LOG.debug("Built with the intent to store bridge data {}",
621 ovsdbBridgeAugmentationBuilder.toString());
622 boolean result = provider.merge(LogicalDatastoreType.CONFIGURATION,
623 bridgeIid, bridgeNodeBuilder.build());
625 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
630 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
631 final Class<? extends DatapathTypeBase> dpType, String mac) {
632 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, mac, null, null);
635 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
636 final Class<? extends DatapathTypeBase> dpType, String mac,
637 Long maxBackoff, Long inactivityProbe) {
638 List<BridgeOtherConfigs> otherConfigs = new ArrayList<>();
640 BridgeOtherConfigsBuilder macOtherConfigBuilder = new BridgeOtherConfigsBuilder();
641 macOtherConfigBuilder.setBridgeOtherConfigKey("hwaddr");
642 macOtherConfigBuilder.setBridgeOtherConfigValue(mac);
643 otherConfigs.add(macOtherConfigBuilder.build());
646 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, otherConfigs, null, null);
649 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
650 final Class<? extends DatapathTypeBase> dpType,
651 List<BridgeOtherConfigs> otherConfigs,
652 Long maxBackoff, Long inactivityProbe) {
655 LOG.info("addBridge: node: {}, bridgeName: {}, controller(s): {}", ovsdbNode, bridgeName, controllersStr);
656 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
657 if (connectionInfo != null) {
658 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
659 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
660 NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
661 bridgeNodeBuilder.setNodeId(bridgeNodeId);
662 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
663 ovsdbBridgeAugmentationBuilder.setControllerEntry(createControllerEntries(
664 controllersStr, maxBackoff, inactivityProbe));
665 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
666 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
667 ovsdbBridgeAugmentationBuilder.setFailMode(OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
668 // TODO: Currently netvirt relies on this function to set disabled-in-band=true. However,
669 // TODO (cont): a better design would be to have netvirt pass that in. That way this function
670 // TODO (cont): can take a null otherConfigs to erase other_configs.
671 if (otherConfigs == null) {
672 otherConfigs = new ArrayList<>();
674 BridgeOtherConfigsBuilder bridgeOtherConfigsBuilder = new BridgeOtherConfigsBuilder();
675 bridgeOtherConfigsBuilder.setBridgeOtherConfigKey(DISABLE_IN_BAND);
676 bridgeOtherConfigsBuilder.setBridgeOtherConfigValue("true");
677 otherConfigs.add(bridgeOtherConfigsBuilder.build());
678 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
679 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(setBridgeExternalIds());
680 setManagedByForBridge(ovsdbBridgeAugmentationBuilder, ovsdbNode.key());
681 if (dpType != null) {
682 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
684 if (isOvsdbNodeDpdk(ovsdbNode)) {
685 ovsdbBridgeAugmentationBuilder.setDatapathType(DatapathTypeNetdev.class);
687 bridgeNodeBuilder.addAugmentation(ovsdbBridgeAugmentationBuilder.build());
689 Node node = bridgeNodeBuilder.build();
690 result = provider.put(LogicalDatastoreType.CONFIGURATION, bridgeIid, node);
691 LOG.info("addBridge: result: {}", result);
693 throw new InvalidParameterException("Could not find ConnectionInfo");
699 * Set the controllers of an existing bridge node.
701 * @param ovsdbNode where the bridge is
702 * @param bridgeName Name of the bridge
703 * @param controllers controller strings
704 * @return success if the write to md-sal was successful
706 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers) {
707 return setBridgeController(ovsdbNode, bridgeName, controllers, null, null);
711 * Set the controllers of an existing bridge node.
713 * @param ovsdbNode where the bridge is
714 * @param bridgeName Name of the bridge
715 * @param controllers controller strings
716 * @param maxBackoff Max backoff in milliseconds
717 * @param inactivityProbe inactivity probe in milliseconds
718 * @return success if the write to md-sal was successful
720 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers,
721 Long maxBackoff, Long inactivityProbe) {
722 LOG.debug("setBridgeController: ovsdbNode: {}, bridgeNode: {}, controller(s): {}",
723 ovsdbNode, bridgeName, controllers);
725 InstanceIdentifier<Node> bridgeNodeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
726 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid);
727 if (bridgeNode == null) {
728 LOG.info("setBridgeController could not find bridge in configuration {}", bridgeNodeIid);
732 OvsdbBridgeAugmentation bridgeAug = extractBridgeAugmentation(bridgeNode);
734 //Only add controller entries that do not already exist on this bridge
735 Map<ControllerEntryKey, ControllerEntry> existingControllerEntries = bridgeAug.getControllerEntry();
736 List<ControllerEntry> newControllerEntries = new ArrayList<>();
737 if (existingControllerEntries != null) {
739 for (ControllerEntry newEntry : createControllerEntries(controllers, maxBackoff, inactivityProbe)) {
740 for (ControllerEntry existingEntry : existingControllerEntries.values()) {
741 if (newEntry.getTarget().equals(existingEntry.getTarget())) {
742 continue NEW_ENTRY_LOOP;
745 newControllerEntries.add(newEntry);
748 newControllerEntries = createControllerEntries(controllers,maxBackoff, inactivityProbe);
751 if (newControllerEntries.isEmpty()) {
755 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
756 return provider.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, new NodeBuilder(bridgeNode)
757 .addAugmentation(new OvsdbBridgeAugmentationBuilder(bridgeAug)
758 .setControllerEntry(newControllerEntries)
763 private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
764 final ConnectionInfo connectionInfo) {
765 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
766 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
769 public boolean addTerminationPoint(
770 Node bridgeNode, String portName, String type, Map<String, String> options,
771 Map<String, String> externalIds) {
772 return addTerminationPoint(bridgeNode, portName, type, options, externalIds, null);
775 public boolean addTerminationPoint(
776 Node bridgeNode, String portName, String type, Map<String, String> options, Map<String, String> externalIds,
778 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
780 tpAugmentationBuilder.setName(portName);
781 tpAugmentationBuilder.setOfport(ofPort);
783 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
786 if (options != null && options.size() > 0) {
787 List<Options> optionsList = new ArrayList<>();
788 for (Map.Entry<String, String> entry : options.entrySet()) {
789 OptionsBuilder optionsBuilder = new OptionsBuilder();
790 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
791 optionsBuilder.setOption(entry.getKey());
792 optionsBuilder.setValue(entry.getValue());
793 optionsList.add(optionsBuilder.build());
795 tpAugmentationBuilder.setOptions(optionsList);
798 if (externalIds != null && externalIds.size() > 0) {
799 List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
800 for (Map.Entry<String, String> entry : externalIds.entrySet()) {
801 InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
802 interfaceExternalIdsBuilder.withKey(new InterfaceExternalIdsKey(entry.getKey()));
803 interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
804 interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
805 externalIdsList.add(interfaceExternalIdsBuilder.build());
807 tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
810 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
811 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, new TerminationPointBuilder()
812 .withKey(InstanceIdentifier.keyOf(tpIid))
813 .addAugmentation(tpAugmentationBuilder.build())
817 public Boolean addTerminationPoint(Node bridgeNode, String portName, String type) {
818 return addTerminationPoint(bridgeNode, portName, type, Collections.EMPTY_MAP, null);
821 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
822 String type, Map<String, String> options) {
823 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
825 tpAugmentationBuilder.setName(portName);
827 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
830 List<Options> optionsList = new ArrayList<>();
831 for (Map.Entry<String, String> entry : options.entrySet()) {
832 OptionsBuilder optionsBuilder = new OptionsBuilder();
833 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
834 optionsBuilder.setOption(entry.getKey());
835 optionsBuilder.setValue(entry.getValue());
836 optionsList.add(optionsBuilder.build());
838 tpAugmentationBuilder.setOptions(optionsList);
840 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
841 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, new TerminationPointBuilder()
842 .withKey(InstanceIdentifier.keyOf(tpIid))
843 .addAugmentation(tpAugmentationBuilder.build())
847 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
848 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
849 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
850 new OvsdbTerminationPointAugmentationBuilder();
852 tpAugmentationBuilder.setName(portName);
854 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
856 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, new TerminationPointBuilder()
857 .withKey(InstanceIdentifier.keyOf(tpIid))
858 .addAugmentation(tpAugmentationBuilder.build())
862 public Boolean addPatchTerminationPoint(Node node, String bridgeName, String portName, String peerPortName) {
863 Map<String, String> option = new HashMap<>();
864 option.put("peer", peerPortName);
865 return addTerminationPoint(node, bridgeName, portName, PATCH_PORT_TYPE, option);
868 private String getControllerIPAddress() {
869 String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
870 if (addressString != null) {
872 if (InetAddress.getByName(addressString) != null) {
873 return addressString;
875 } catch (UnknownHostException e) {
876 LOG.error("Host {} is invalid", addressString, e);
880 addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
881 if (addressString != null) {
883 if (InetAddress.getByName(addressString) != null) {
884 return addressString;
886 } catch (UnknownHostException e) {
887 LOG.error("Host {} is invalid", addressString, e);
894 private short getControllerOFPort() {
895 short openFlowPort = OPENFLOW_PORT;
896 String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
897 if (portString != null) {
899 openFlowPort = Short.parseShort(portString);
900 } catch (NumberFormatException e) {
901 LOG.warn("Invalid port:{}, use default({})", portString,
908 public List<String> getControllersFromOvsdbNode(Node node) {
909 List<String> controllersStr = new ArrayList<>();
911 String controllerIpStr = getControllerIPAddress();
912 if (controllerIpStr != null) {
913 // If codepath makes it here, the ip address to be used was explicitly provided.
914 // Being so, also fetch openflowPort provided via ConfigProperties.
915 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
916 + ":" + controllerIpStr + ":" + getControllerOFPort());
918 // Check if ovsdb node has manager entries
919 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(node);
920 if (ovsdbNodeAugmentation != null) {
921 Map<ManagerEntryKey, ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
922 if (managerEntries != null && !managerEntries.isEmpty()) {
923 for (ManagerEntry managerEntry : managerEntries.values()) {
924 if (managerEntry == null || managerEntry.getTarget() == null) {
927 String managerStr = managerEntry.getTarget().getValue().toLowerCase(Locale.ROOT);
928 int firstColonIdx = managerStr.indexOf(':');
929 int lastColonIdx = managerStr.lastIndexOf(':');
930 if (lastColonIdx <= firstColonIdx) {
933 controllerIpStr = managerStr.substring(firstColonIdx + 1, lastColonIdx);
934 if (managerStr.startsWith("tcp")) {
935 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL + ":" + controllerIpStr + ":"
936 + getControllerOFPort());
937 } else if (managerStr.startsWith("ssl")) {
938 controllersStr.add(OPENFLOW_SECURE_PROTOCOL + ":" + controllerIpStr + ":"
939 + getControllerOFPort());
940 } else if (managerStr.startsWith("ptcp")) {
941 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
942 /* If we're connected to switch ptcp, only then use connection info
943 to configure controller. Ptcp is configured as:
944 Manager "ptcp:<port>:<ip>"
947 String managerPortStr = managerStr.split(":", 3)[1];
948 if (connectionInfo != null && connectionInfo.getLocalIp() != null
949 && connectionInfo.getRemotePort() != null
950 && managerPortStr.equals(connectionInfo.getRemotePort().toString())) {
951 IpAddress controllerIp = connectionInfo.getLocalIp();
952 if (controllerIp.getIpv6Address() != null) {
953 controllerIpStr = "[" + connectionInfo.getLocalIp().stringValue() + "]";
955 controllerIpStr = connectionInfo.getLocalIp().stringValue();
957 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
958 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
960 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
962 } else if (managerStr.startsWith("pssl")) {
963 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
964 if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
965 controllerIpStr = connectionInfo.getLocalIp().stringValue();
966 controllersStr.add(OPENFLOW_SECURE_PROTOCOL
967 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
969 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
972 LOG.trace("Skipping manager entry {} for node {}",
973 managerEntry.getTarget(), node.getNodeId().getValue());
977 LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
982 if (controllersStr.isEmpty()) {
983 LOG.warn("Failed to determine OpenFlow controller ip address");
984 } else if (LOG.isDebugEnabled()) {
985 LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(),
986 controllersStr.stream().collect(Collectors.joining(" ")));
988 return controllersStr;
991 public long getDataPathId(Node node) {
993 String datapathId = getDatapathId(node);
994 if (datapathId != null) {
995 dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
1000 public String getDataPathIdStr(final Node node) {
1002 long dpId = getDataPathId(node);
1004 return String.valueOf(dpId);
1011 public String getDatapathId(Node node) {
1012 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.augmentation(OvsdbBridgeAugmentation.class);
1013 return getDatapathId(ovsdbBridgeAugmentation);
1016 public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
1017 String datapathId = null;
1018 if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
1019 datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
1024 public String extractBridgeName(Node node) {
1025 return node.augmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
1028 public boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgeName) {
1029 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1030 if (ovsdbNodeAugmentation != null) {
1031 Map<ManagedNodeEntryKey, ManagedNodeEntry> managedNodes = ovsdbNodeAugmentation.getManagedNodeEntry();
1032 if (managedNodes != null) {
1033 for (ManagedNodeEntry managedNode : managedNodes.values()) {
1034 if (matchesBridgeName(managedNode, bridgeName)) {
1043 // see OVSDB-470 for background
1044 private static boolean matchesBridgeName(ManagedNodeEntry managedNode, String bridgeName) {
1045 InstanceIdentifier<?> bridgeIid = managedNode.getBridgeRef().getValue();
1046 for (PathArgument bridgeIidPathArg : bridgeIid.getPathArguments()) {
1047 if (bridgeIidPathArg instanceof IdentifiableItem<?, ?>) {
1048 IdentifiableItem<?, ?> identifiableItem = (IdentifiableItem<?, ?>) bridgeIidPathArg;
1049 Identifier<?> key = identifiableItem.getKey();
1050 if (key instanceof NodeKey) {
1051 // Do not combine the above if with that below, we want to
1052 // avoid the toString() call in the else if this is a NodeKey
1053 NodeKey nodeKey = (NodeKey) key;
1054 if (nodeKey.getNodeId().getValue().contains(bridgeName)) {
1057 } else if (key.toString().contains(bridgeName)) {
1060 } else if (bridgeIidPathArg instanceof Item<?>) {
1061 if (((Item<?>) bridgeIidPathArg).getType().getName().contains(bridgeName)) {
1065 throw new IllegalArgumentException("Unknown kind of PathArgument: " + bridgeIidPathArg);
1071 public OvsdbBridgeAugmentation getBridgeFromConfig(Node node, String bridge) {
1072 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
1073 InstanceIdentifier<Node> bridgeIid =
1074 createInstanceIdentifier(node.key(), bridge);
1075 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeIid);
1076 if (bridgeNode != null) {
1077 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
1079 return ovsdbBridgeAugmentation;
1082 private static void setManagedByForBridge(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
1083 NodeKey ovsdbNodeKey) {
1084 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(ovsdbNodeKey.getNodeId());
1085 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
1088 public boolean isOvsdbNodeDpdk(Node ovsdbNode) {
1089 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1090 if (ovsdbNodeAugmentation != null) {
1091 Map<InterfaceTypeEntryKey, InterfaceTypeEntry> ifTypes = ovsdbNodeAugmentation.getInterfaceTypeEntry();
1092 if (ifTypes != null) {
1093 if (ifTypes.containsKey(DPDK_IFACE_KEY)) {
1101 private static List<ControllerEntry> createControllerEntries(List<String> controllersStr,
1102 Long maxBackoff, Long inactivityProbe) {
1103 List<ControllerEntry> controllerEntries = new ArrayList<>();
1104 if (controllersStr != null) {
1105 for (String controllerStr : controllersStr) {
1106 ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
1107 controllerEntryBuilder.setTarget(new Uri(controllerStr));
1108 if (maxBackoff != null) {
1109 controllerEntryBuilder.setMaxBackoff(maxBackoff);
1111 if (inactivityProbe != null) {
1112 controllerEntryBuilder.setInactivityProbe(inactivityProbe);
1114 controllerEntries.add(controllerEntryBuilder.build());
1117 return controllerEntries;
1120 public OvsdbTerminationPointAugmentation extractTerminationPointAugmentation(Node bridgeNode, String portName) {
1121 if (bridgeNode.augmentation(OvsdbBridgeAugmentation.class) != null) {
1122 List<OvsdbTerminationPointAugmentation> tpAugmentations = extractTerminationPointAugmentations(bridgeNode);
1123 for (OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation : tpAugmentations) {
1124 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1125 return ovsdbTerminationPointAugmentation;
1132 public List<OvsdbTerminationPointAugmentation> extractTerminationPointAugmentations(Node node) {
1133 List<OvsdbTerminationPointAugmentation> tpAugmentations = new ArrayList<>();
1135 LOG.error("extractTerminationPointAugmentations: Node value is null");
1136 return Collections.emptyList();
1138 Map<TerminationPointKey, TerminationPoint> terminationPoints = node.getTerminationPoint();
1139 if (terminationPoints != null && !terminationPoints.isEmpty()) {
1140 for (TerminationPoint tp : terminationPoints.values()) {
1141 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1142 tp.augmentation(OvsdbTerminationPointAugmentation.class);
1143 if (ovsdbTerminationPointAugmentation != null) {
1144 tpAugmentations.add(ovsdbTerminationPointAugmentation);
1148 return tpAugmentations;
1152 * Extract the <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code> identified by
1153 * <code>portName</code>.
1155 public OvsdbTerminationPointAugmentation getTerminationPointOfBridge(Node node, String portName) {
1156 OvsdbTerminationPointAugmentation tpAugmentation = extractTerminationPointAugmentation(node,portName);
1157 if (tpAugmentation == null) {
1158 List<OvsdbTerminationPointAugmentation> tpAugmentations = readTerminationPointAugmentations(node);
1159 if (tpAugmentations != null) {
1160 for (OvsdbTerminationPointAugmentation ovsdbTpAugmentation : tpAugmentations) {
1161 if (ovsdbTpAugmentation.getName().equals(portName)) {
1162 return ovsdbTpAugmentation;
1167 return tpAugmentation;
1171 * Read the list of <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code>.
1173 public List<OvsdbTerminationPointAugmentation> readTerminationPointAugmentations(Node node) {
1175 LOG.error("readTerminationPointAugmentations: Node value is null");
1176 return Collections.emptyList();
1178 Node operNode = provider.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier
1179 .create(NetworkTopology.class)
1180 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
1181 .child(Node.class, new NodeKey(node.getNodeId())));
1182 if (operNode != null) {
1183 return extractTerminationPointAugmentations(operNode);
1185 return new ArrayList<>();
1189 * Get all OVSDB nodes from topology.
1190 * @return a list of nodes or null if the topology could not found
1192 public Map<NodeKey, Node> getOvsdbNodes() {
1193 InstanceIdentifier<Topology> inst = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
1194 new TopologyKey(OVSDB_TOPOLOGY_ID));
1195 Topology topology = provider.read(LogicalDatastoreType.OPERATIONAL, inst);
1196 return topology != null ? topology.getNode() : null;
1200 * Get OpenvSwitch other-config by key.
1201 * @param node OVSDB node
1202 * @param key key to extract from other-config
1203 * @return the value for key or null if key not found
1205 public String getOpenvswitchOtherConfig(Node node, String key) {
1206 OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
1207 if (ovsdbNode == null) {
1208 Node nodeFromReadOvsdbNode = readOvsdbNode(node);
1209 if (nodeFromReadOvsdbNode != null) {
1210 ovsdbNode = nodeFromReadOvsdbNode.augmentation(OvsdbNodeAugmentation.class);
1214 if (ovsdbNode != null) {
1215 final OpenvswitchOtherConfigs found = ovsdbNode.nonnullOpenvswitchOtherConfigs()
1216 .get(new OpenvswitchOtherConfigsKey(key));
1217 if (found != null) {
1218 return found.getOtherConfigValue();
1225 public static TerminationPoint getTerminationPointByExternalId(final Node bridgeNode, final String interfaceName) {
1226 final Map<TerminationPointKey, TerminationPoint> tps = bridgeNode.getTerminationPoint();
1228 for (TerminationPoint tp : tps.values()) {
1229 OvsdbTerminationPointAugmentation ovsdbTp = tp.augmentation(OvsdbTerminationPointAugmentation.class);
1230 String externalIdValue = getExternalInterfaceIdValue(ovsdbTp);
1231 if (externalIdValue != null && externalIdValue.equals(interfaceName)) {
1232 LOG.debug("Found matching termination point with iface-id {} on bridgeNode {}, returning tp {}",
1233 interfaceName, bridgeNode, tp);
1241 // This utility shouldn't be called often, as it reads all OVSDB nodes each time - not good for scale
1242 public Node getNodeByTerminationPointExternalId(final String interfaceName) {
1243 Map<NodeKey, Node> nodes = getOvsdbNodes();
1244 if (nodes != null) {
1245 for (Node node : nodes.values()) {
1246 TerminationPoint tp = getTerminationPointByExternalId(node, interfaceName);
1255 public static String getExternalInterfaceIdValue(final OvsdbTerminationPointAugmentation ovsdbTp) {
1256 if (ovsdbTp != null) {
1257 Map<InterfaceExternalIdsKey, InterfaceExternalIds> ifaceExtIds = ovsdbTp.getInterfaceExternalIds();
1258 if (ifaceExtIds != null) {
1259 final InterfaceExternalIds entry = ifaceExtIds.get(EXTERNAL_INTERFACE_ID_KEY);
1260 if (entry != null) {
1261 return entry.getExternalIdValue();
1268 public String getDatapathIdFromNodeInstanceId(InstanceIdentifier<Node> nodeInstanceId) {
1269 Node node = provider.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
1270 String dpId = node != null ? getDataPathIdStr(node) : null;
1277 public static boolean compareDbVersionToMinVersion(final String dbVersion, final String minVersion) {
1278 if (dbVersion == null || minVersion == null) {
1279 LOG.error("Invalid DB version {} or minVersion {}", dbVersion, minVersion);
1282 final Matcher dbVersionMatcher = PATTERN.matcher(dbVersion);
1283 final Matcher minVersionMatcher = PATTERN.matcher(minVersion);
1284 LOG.debug("dbVersion {}, minVersion {}", dbVersion, minVersion);
1285 if (!dbVersionMatcher.find()) {
1286 LOG.error("Invalid DB version format {}", dbVersion);
1289 if (!minVersionMatcher.find()) {
1290 LOG.error("Invalid Min DB version format {}", minVersion);
1294 if (dbVersion != null && !dbVersion.isEmpty() && minVersion != null && !minVersion.isEmpty()) {
1295 final int dbVersionMatch1 = Integer.parseInt(dbVersionMatcher.group(1));
1296 final int dbVersionMatch2 = Integer.parseInt(dbVersionMatcher.group(2));
1297 final int dbVersionMatch3 = Integer.parseInt(dbVersionMatcher.group(3));
1298 final int minVersionMatch1 = Integer.parseInt(minVersionMatcher.group(1));
1299 final int minVersionMatch2 = Integer.parseInt(minVersionMatcher.group(2));
1300 final int minVersionMatch3 = Integer.parseInt(minVersionMatcher.group(3));
1301 if (dbVersionMatch1 == minVersionMatch1 && dbVersionMatch2 == minVersionMatch2
1302 && dbVersionMatch3 == minVersionMatch3) {
1306 if (dbVersionMatch1 > minVersionMatch1) {
1310 if (dbVersionMatch1 < minVersionMatch1) {
1314 // major version is equal
1315 if (dbVersionMatch2 > minVersionMatch2) {
1319 if (dbVersionMatch2 < minVersionMatch2) {
1323 if (dbVersionMatch3 > minVersionMatch3) {
1330 private static List<BridgeExternalIds> setBridgeExternalIds() {
1331 List<BridgeExternalIds> externalIdsList = new ArrayList<>();
1332 externalIdsList.add(new BridgeExternalIdsBuilder()
1333 .setBridgeExternalIdKey(CREATED_BY)
1334 .setBridgeExternalIdValue(ODL)
1336 return externalIdsList;