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(
142 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.fromMdsal(store), path);
146 <T extends DataObject> boolean put(LogicalDatastoreType store,
147 InstanceIdentifier<T> path, T data) {
148 return mdsalUtils.put(
149 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.fromMdsal(store), path, data);
153 boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
154 return mdsalUtils.delete(
155 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.fromMdsal(store), path);
159 <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
160 return mdsalUtils.merge(
161 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.fromMdsal(store), path, data);
165 private static final class MdsalUtilsProvider extends UtilsProvider {
166 private final MdsalUtils mdsalUtils;
168 MdsalUtilsProvider(final MdsalUtils mdsalUtils) {
169 this.mdsalUtils = requireNonNull(mdsalUtils);
173 <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path) {
174 return mdsalUtils.read(store, path);
178 <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
179 return mdsalUtils.put(store, path, data);
183 boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
184 return mdsalUtils.delete(store, path);
188 <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
189 return mdsalUtils.merge(store, path, data);
193 private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
194 private static final int OVSDB_UPDATE_TIMEOUT = 1000;
195 public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
196 public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
197 public static final String OPENFLOW_SECURE_PROTOCOL = "ssl";
198 public static final short OPENFLOW_PORT = 6653;
199 public static final String OVSDB_URI_PREFIX = "ovsdb";
200 public static final String BRIDGE_URI_PREFIX = "bridge";
201 private static final String DISABLE_IN_BAND = "disable-in-band";
202 private static final String PATCH_PORT_TYPE = "patch";
203 // External ID key used for mapping between an OVSDB port and an interface name
204 private static final String EXTERNAL_INTERFACE_ID_KEY = "iface-id";
205 private static final String CREATED_BY = "created_by";
206 private static final String ODL = "odl";
207 private static final String FORMAT = "(\\d+)\\.(\\d+)\\.(\\d+)";
208 private static final Pattern PATTERN = Pattern.compile(FORMAT);
210 private final UtilsProvider provider;
213 public SouthboundUtils(ControllerMdsalUtils mdsalUtils) {
214 provider = new ControllerUtilsProvider(mdsalUtils);
217 public SouthboundUtils(MdsalUtils mdsalUtils) {
218 provider = new MdsalUtilsProvider(mdsalUtils);
221 public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
222 = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
223 .put("internal", InterfaceTypeInternal.class)
224 .put("vxlan", InterfaceTypeVxlan.class)
225 .put("vxlan-gpe", InterfaceTypeVxlanGpe.class)
226 .put("patch", InterfaceTypePatch.class)
227 .put("system", InterfaceTypeSystem.class)
228 .put("tap", InterfaceTypeTap.class)
229 .put("geneve", InterfaceTypeGeneve.class)
230 .put("gre", InterfaceTypeGre.class)
231 .put("ipsec_gre", InterfaceTypeIpsecGre.class)
232 .put("gre64", InterfaceTypeGre64.class)
233 .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
234 .put("lisp", InterfaceTypeLisp.class)
235 .put("dpdk", InterfaceTypeDpdk.class)
236 .put("dpdkr", InterfaceTypeDpdkr.class)
237 .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
238 .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
239 .put("dpdkvhostuserclient", InterfaceTypeDpdkvhostuserclient.class)
242 public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>,String> OVSDB_PROTOCOL_MAP
243 = new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>,String>()
244 .put(OvsdbBridgeProtocolOpenflow10.class,"OpenFlow10")
245 .put(OvsdbBridgeProtocolOpenflow11.class,"OpenFlow11")
246 .put(OvsdbBridgeProtocolOpenflow12.class,"OpenFlow12")
247 .put(OvsdbBridgeProtocolOpenflow13.class,"OpenFlow13")
248 .put(OvsdbBridgeProtocolOpenflow14.class,"OpenFlow14")
249 .put(OvsdbBridgeProtocolOpenflow15.class,"OpenFlow15")
252 private static final ImmutableBiMap<Class<? extends OvsdbFailModeBase>,String> OVSDB_FAIL_MODE_MAP
253 = new ImmutableBiMap.Builder<Class<? extends OvsdbFailModeBase>,String>()
254 .put(OvsdbFailModeStandalone.class,"standalone")
255 .put(OvsdbFailModeSecure.class,"secure")
258 public static NodeId createNodeId(IpAddress ip, PortNumber port) {
259 String uriString = OVSDB_URI_PREFIX + "://" + ip.stringValue() + ":" + port.getValue();
260 Uri uri = new Uri(uriString);
261 return new NodeId(uri);
264 public static Node createNode(ConnectionInfo key) {
265 NodeBuilder nodeBuilder = new NodeBuilder();
266 nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()));
267 nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
268 return nodeBuilder.build();
271 public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
272 OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
273 ovsdbNodeBuilder.setConnectionInfo(key);
274 return ovsdbNodeBuilder.build();
277 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
278 return InstanceIdentifier
279 .create(NetworkTopology.class)
280 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
281 .child(Node.class,new NodeKey(nodeId));
284 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeKey ovsdbNodeKey, String bridgeName) {
285 return createInstanceIdentifier(createManagedNodeId(ovsdbNodeKey.getNodeId(), bridgeName));
288 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
289 return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
292 public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
293 InstanceIdentifier<Node> path = InstanceIdentifier
294 .create(NetworkTopology.class)
295 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
296 .child(Node.class,createNodeKey(ip,port));
297 LOG.debug("Created ovsdb path: {}",path);
301 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, OvsdbBridgeName bridgeName) {
302 return createInstanceIdentifier(createManagedNodeId(key, bridgeName));
305 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, String bridgeName) {
306 return createInstanceIdentifier(key, new OvsdbBridgeName(bridgeName));
309 public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName) {
311 InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
312 .create(NetworkTopology.class)
313 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
314 .child(Node.class,node.key())
315 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
317 LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
318 return terminationPointPath;
321 public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
322 return new NodeKey(createNodeId(ip, port));
325 public static NodeId createManagedNodeId(NodeId ovsdbNodeId, String bridgeName) {
326 return new NodeId(ovsdbNodeId.getValue()
327 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName);
330 public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
331 return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
334 public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
335 return new NodeId(createNodeId(ip,port).getValue()
336 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
339 public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
340 NodeKey nodeKey = iid.firstKeyOf(Node.class);
341 return nodeKey.getNodeId();
344 public OvsdbNodeAugmentation extractOvsdbNode(Node node) {
345 return node.augmentation(OvsdbNodeAugmentation.class);
348 public static IpAddress createIpAddress(InetAddress address) {
350 if (address instanceof Inet4Address) {
351 ip = createIpAddress((Inet4Address)address);
352 } else if (address instanceof Inet6Address) {
353 ip = createIpAddress((Inet6Address)address);
358 public static IpAddress createIpAddress(Inet4Address address) {
359 return IetfInetUtil.INSTANCE.ipAddressFor(address);
362 public static IpAddress createIpAddress(Inet6Address address) {
363 Ipv6Address ipv6 = new Ipv6Address(address.getHostAddress());
364 return new IpAddress(ipv6);
367 public ConnectionInfo getConnectionInfo(Node ovsdbNode) {
368 ConnectionInfo connectionInfo = null;
369 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(ovsdbNode);
370 if (ovsdbNodeAugmentation != null) {
371 connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
373 return connectionInfo;
376 public static ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
377 InetAddress inetAddress = null;
379 inetAddress = InetAddress.getByName(addressStr);
380 } catch (UnknownHostException e) {
381 LOG.warn("Could not allocate InetAddress", e);
384 IpAddress address = createIpAddress(inetAddress);
385 PortNumber port = new PortNumber(Integer.parseInt(portStr));
387 LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
388 .setRemoteIp(address)
391 return new ConnectionInfoBuilder()
392 .setRemoteIp(address)
397 public static String connectionInfoToString(final ConnectionInfo connectionInfo) {
398 return connectionInfo.getRemoteIp().stringValue() + ":" + connectionInfo.getRemotePort().getValue();
401 public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
402 return addOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
405 public boolean addOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
406 boolean result = provider.put(LogicalDatastoreType.CONFIGURATION,
407 createInstanceIdentifier(connectionInfo),
408 createNode(connectionInfo));
411 Thread.sleep(timeout);
412 } catch (InterruptedException e) {
413 LOG.warn("Interrupted while waiting after adding OVSDB node {}",
414 connectionInfoToString(connectionInfo), e);
420 public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
421 return provider.read(LogicalDatastoreType.OPERATIONAL,
422 createInstanceIdentifier(connectionInfo));
425 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
426 return deleteOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
429 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
430 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
431 createInstanceIdentifier(connectionInfo));
434 Thread.sleep(timeout);
435 } catch (InterruptedException e) {
436 LOG.warn("Interrupted while waiting after deleting OVSDB node {}",
437 connectionInfoToString(connectionInfo), e);
443 public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
444 return connectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
447 public Node connectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
448 addOvsdbNode(connectionInfo, timeout);
449 Node node = getOvsdbNode(connectionInfo);
450 LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
454 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
455 return disconnectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
458 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
459 deleteOvsdbNode(connectionInfo, timeout);
460 LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
464 public List<ControllerEntry> createControllerEntry(String controllerTarget) {
465 List<ControllerEntry> controllerEntriesList = new ArrayList<>();
466 controllerEntriesList.add(new ControllerEntryBuilder()
467 .setTarget(new Uri(controllerTarget))
469 return controllerEntriesList;
473 * Extract the <code>store</code> type data store contents for the particular bridge identified by
474 * <code>bridgeName</code>.
476 * @param connectionInfo address for the node
477 * @param bridgeName name of the bridge
478 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
479 * @return <code>store</code> type data store contents
482 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
483 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType store) {
484 return getBridge(connectionInfo, bridgeName, store.toMdsal());
488 * Extract the <code>store</code> type data store contents for the particular bridge identified by
489 * <code>bridgeName</code>.
491 * @param connectionInfo address for the node
492 * @param bridgeName name of the bridge
493 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
494 * @return <code>store</code> type data store contents
496 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
497 LogicalDatastoreType store) {
498 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
499 Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
500 if (bridgeNode != null) {
501 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
503 return ovsdbBridgeAugmentation;
507 * Extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
508 * identified by <code>bridgeName</code>.
510 * @param connectionInfo address for the node
511 * @param bridgeName name of the bridge
512 * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
513 * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
515 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
516 return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
520 * Extract the node contents from <code>store</code> type data store for the
521 * bridge identified by <code>bridgeName</code>.
523 * @param connectionInfo address for the node
524 * @param bridgeName name of the bridge
525 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
526 * @return <code>store</code> type data store contents
529 public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName,
530 org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType store) {
531 return getBridgeNode(connectionInfo, bridgeName, store.toMdsal());
535 * Extract the node contents from <code>store</code> type data store for the
536 * bridge identified by <code>bridgeName</code>.
538 * @param connectionInfo address for the node
539 * @param bridgeName name of the bridge
540 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
541 * @return <code>store</code> type data store contents
543 public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
544 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
545 return provider.read(store, bridgeIid);
548 public Node getBridgeNode(Node node, String bridgeName) {
549 OvsdbBridgeAugmentation bridge = extractBridgeAugmentation(node);
550 if (bridge != null && bridge.getBridgeName().getValue().equals(bridgeName)) {
553 return readBridgeNode(node, bridgeName);
557 public Node readBridgeNode(Node node, String name) {
558 Node ovsdbNode = node;
559 if (extractNodeAugmentation(ovsdbNode) == null) {
560 ovsdbNode = readOvsdbNode(node);
561 if (ovsdbNode == null) {
565 Node bridgeNode = null;
566 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
567 if (connectionInfo != null) {
568 InstanceIdentifier<Node> bridgeIid =
569 createInstanceIdentifier(node.key(), name);
570 bridgeNode = provider.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
575 public OvsdbNodeAugmentation extractNodeAugmentation(Node node) {
576 return node.augmentation(OvsdbNodeAugmentation.class);
579 public OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
583 return node.augmentation(OvsdbBridgeAugmentation.class);
586 public Node readOvsdbNode(Node bridgeNode) {
587 Node ovsdbNode = null;
588 OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
589 if (bridgeAugmentation != null) {
590 InstanceIdentifier<Node> ovsdbNodeIid =
591 (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
592 ovsdbNode = provider.read(LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
594 LOG.debug("readOvsdbNode: Provided node is not a bridge node : {}",bridgeNode);
599 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
600 return deleteBridge(connectionInfo, bridgeName, OVSDB_UPDATE_TIMEOUT);
603 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName, long timeout) {
604 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
605 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
608 Thread.sleep(timeout);
609 } catch (InterruptedException e) {
610 LOG.warn("Interrupted while waiting after deleting bridge {}", bridgeName, e);
616 public List<ProtocolEntry> createMdsalProtocols() {
617 List<ProtocolEntry> protocolList = new ArrayList<>();
618 ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
619 OVSDB_PROTOCOL_MAP.inverse();
620 protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
625 * base method for adding test bridges. Other helper methods used to create bridges should utilize this method.
627 * @param connectionInfo
628 * @param bridgeIid if passed null, one is created
629 * @param bridgeName cannot be null
630 * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
631 * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
632 * @param failMode toggles whether default fail mode is set for the bridge
633 * @param setManagedBy toggles whether to setManagedBy for the bridge
634 * @param dpType if passed null, this parameter is ignored
635 * @param externalIds if passed null, this parameter is ignored
636 * @param otherConfig if passed null, this parameter is ignored
637 * @return success of bridge addition
638 * @throws InterruptedException
640 public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
641 final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
642 final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
643 final Class<? extends DatapathTypeBase> dpType,
644 final List<BridgeExternalIds> externalIds,
645 final List<ControllerEntry> controllerEntries,
646 final List<BridgeOtherConfigs> otherConfigs,
647 final String dpid, long timeout) throws InterruptedException {
649 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
650 if (bridgeIid == null) {
651 bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
653 if (bridgeNodeId == null) {
654 bridgeNodeId = createManagedNodeId(bridgeIid);
656 bridgeNodeBuilder.setNodeId(bridgeNodeId);
657 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
658 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
659 if (setProtocolEntries) {
660 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
662 if (failMode != null) {
663 ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
666 setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
668 if (dpType != null) {
669 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
671 if (externalIds != null) {
672 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
674 if (controllerEntries != null) {
675 ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
677 if (otherConfigs != null) {
678 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
680 if (dpid != null && !dpid.isEmpty()) {
681 DatapathId datapathId = new DatapathId(dpid);
682 ovsdbBridgeAugmentationBuilder.setDatapathId(datapathId);
684 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
685 LOG.debug("Built with the intent to store bridge data {}",
686 ovsdbBridgeAugmentationBuilder.toString());
687 boolean result = provider.merge(LogicalDatastoreType.CONFIGURATION,
688 bridgeIid, bridgeNodeBuilder.build());
690 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
695 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
696 final Class<? extends DatapathTypeBase> dpType, String mac) {
697 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, mac, null, null);
700 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
701 final Class<? extends DatapathTypeBase> dpType, String mac,
702 Long maxBackoff, Long inactivityProbe) {
703 List<BridgeOtherConfigs> otherConfigs = new ArrayList<>();
705 BridgeOtherConfigsBuilder macOtherConfigBuilder = new BridgeOtherConfigsBuilder();
706 macOtherConfigBuilder.setBridgeOtherConfigKey("hwaddr");
707 macOtherConfigBuilder.setBridgeOtherConfigValue(mac);
708 otherConfigs.add(macOtherConfigBuilder.build());
711 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, otherConfigs, null, null);
714 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
715 final Class<? extends DatapathTypeBase> dpType,
716 List<BridgeOtherConfigs> otherConfigs,
717 Long maxBackoff, Long inactivityProbe) {
720 LOG.info("addBridge: node: {}, bridgeName: {}, controller(s): {}", ovsdbNode, bridgeName, controllersStr);
721 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
722 if (connectionInfo != null) {
723 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
724 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
725 NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
726 bridgeNodeBuilder.setNodeId(bridgeNodeId);
727 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
728 ovsdbBridgeAugmentationBuilder.setControllerEntry(createControllerEntries(
729 controllersStr, maxBackoff, inactivityProbe));
730 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
731 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
732 ovsdbBridgeAugmentationBuilder.setFailMode(OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
733 // TODO: Currently netvirt relies on this function to set disabled-in-band=true. However,
734 // TODO (cont): a better design would be to have netvirt pass that in. That way this function
735 // TODO (cont): can take a null otherConfigs to erase other_configs.
736 if (otherConfigs == null) {
737 otherConfigs = new ArrayList<>();
739 BridgeOtherConfigsBuilder bridgeOtherConfigsBuilder = new BridgeOtherConfigsBuilder();
740 bridgeOtherConfigsBuilder.setBridgeOtherConfigKey(DISABLE_IN_BAND);
741 bridgeOtherConfigsBuilder.setBridgeOtherConfigValue("true");
742 otherConfigs.add(bridgeOtherConfigsBuilder.build());
743 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
744 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(setBridgeExternalIds());
745 setManagedByForBridge(ovsdbBridgeAugmentationBuilder, ovsdbNode.key());
746 if (dpType != null) {
747 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
749 if (isOvsdbNodeDpdk(ovsdbNode)) {
750 ovsdbBridgeAugmentationBuilder.setDatapathType(DatapathTypeNetdev.class);
752 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
754 Node node = bridgeNodeBuilder.build();
755 result = provider.put(LogicalDatastoreType.CONFIGURATION, bridgeIid, node);
756 LOG.info("addBridge: result: {}", result);
758 throw new InvalidParameterException("Could not find ConnectionInfo");
764 * Set the controllers of an existing bridge node.
766 * @param ovsdbNode where the bridge is
767 * @param bridgeName Name of the bridge
768 * @param controllers controller strings
769 * @return success if the write to md-sal was successful
771 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers) {
772 return setBridgeController(ovsdbNode, bridgeName, controllers, null, null);
776 * Set the controllers of an existing bridge node.
778 * @param ovsdbNode where the bridge is
779 * @param bridgeName Name of the bridge
780 * @param controllers controller strings
781 * @param maxBackoff Max backoff in milliseconds
782 * @param inactivityProbe inactivity probe in milliseconds
783 * @return success if the write to md-sal was successful
785 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers,
786 Long maxBackoff, Long inactivityProbe) {
787 LOG.debug("setBridgeController: ovsdbNode: {}, bridgeNode: {}, controller(s): {}",
788 ovsdbNode, bridgeName, controllers);
790 InstanceIdentifier<Node> bridgeNodeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
791 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid);
792 if (bridgeNode == null) {
793 LOG.info("setBridgeController could not find bridge in configuration {}", bridgeNodeIid);
797 OvsdbBridgeAugmentation bridgeAug = extractBridgeAugmentation(bridgeNode);
799 //Only add controller entries that do not already exist on this bridge
800 List<ControllerEntry> existingControllerEntries = bridgeAug.getControllerEntry();
801 List<ControllerEntry> newControllerEntries = new ArrayList<>();
802 if (existingControllerEntries != null) {
804 for (ControllerEntry newEntry : createControllerEntries(controllers, maxBackoff, inactivityProbe)) {
805 for (ControllerEntry existingEntry : existingControllerEntries) {
806 if (newEntry.getTarget().equals(existingEntry.getTarget())) {
807 continue NEW_ENTRY_LOOP;
810 newControllerEntries.add(newEntry);
813 newControllerEntries = createControllerEntries(controllers,maxBackoff, inactivityProbe);
816 if (newControllerEntries.isEmpty()) {
820 NodeBuilder nodeBuilder = new NodeBuilder(bridgeNode);
821 OvsdbBridgeAugmentationBuilder augBuilder = new OvsdbBridgeAugmentationBuilder(bridgeAug);
823 augBuilder.setControllerEntry(newControllerEntries);
824 nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, augBuilder.build());
825 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
826 return provider.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, nodeBuilder.build());
829 private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
830 final ConnectionInfo connectionInfo) {
831 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
832 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
835 public boolean addTerminationPoint(
836 Node bridgeNode, String portName, String type, Map<String, String> options,
837 Map<String, String> externalIds) {
838 return addTerminationPoint(bridgeNode, portName, type, options, externalIds, null);
841 public boolean addTerminationPoint(
842 Node bridgeNode, String portName, String type, Map<String, String> options, Map<String, String> externalIds,
844 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
846 tpAugmentationBuilder.setName(portName);
847 tpAugmentationBuilder.setOfport(ofPort);
849 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
852 if (options != null && options.size() > 0) {
853 List<Options> optionsList = new ArrayList<>();
854 for (Map.Entry<String, String> entry : options.entrySet()) {
855 OptionsBuilder optionsBuilder = new OptionsBuilder();
856 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
857 optionsBuilder.setOption(entry.getKey());
858 optionsBuilder.setValue(entry.getValue());
859 optionsList.add(optionsBuilder.build());
861 tpAugmentationBuilder.setOptions(optionsList);
864 if (externalIds != null && externalIds.size() > 0) {
865 List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
866 for (Map.Entry<String, String> entry : externalIds.entrySet()) {
867 InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
868 interfaceExternalIdsBuilder.withKey(new InterfaceExternalIdsKey(entry.getKey()));
869 interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
870 interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
871 externalIdsList.add(interfaceExternalIdsBuilder.build());
873 tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
876 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
877 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
878 tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
879 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
880 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
883 public Boolean addTerminationPoint(Node bridgeNode, String portName, String type) {
884 return addTerminationPoint(bridgeNode, portName, type, Collections.EMPTY_MAP, null);
887 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
888 String type, Map<String, String> options) {
889 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
891 tpAugmentationBuilder.setName(portName);
893 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
896 List<Options> optionsList = new ArrayList<>();
897 for (Map.Entry<String, String> entry : options.entrySet()) {
898 OptionsBuilder optionsBuilder = new OptionsBuilder();
899 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
900 optionsBuilder.setOption(entry.getKey());
901 optionsBuilder.setValue(entry.getValue());
902 optionsList.add(optionsBuilder.build());
904 tpAugmentationBuilder.setOptions(optionsList);
906 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
907 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
908 tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
909 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
910 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
913 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
914 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
915 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
916 new OvsdbTerminationPointAugmentationBuilder();
918 tpAugmentationBuilder.setName(portName);
920 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
922 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
923 tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
924 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
925 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
928 public Boolean addPatchTerminationPoint(Node node, String bridgeName, String portName, String peerPortName) {
929 Map<String, String> option = new HashMap<>();
930 option.put("peer", peerPortName);
931 return addTerminationPoint(node, bridgeName, portName, PATCH_PORT_TYPE, option);
934 private String getControllerIPAddress() {
935 String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
936 if (addressString != null) {
938 if (InetAddress.getByName(addressString) != null) {
939 return addressString;
941 } catch (UnknownHostException e) {
942 LOG.error("Host {} is invalid", addressString, e);
946 addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
947 if (addressString != null) {
949 if (InetAddress.getByName(addressString) != null) {
950 return addressString;
952 } catch (UnknownHostException e) {
953 LOG.error("Host {} is invalid", addressString, e);
960 private short getControllerOFPort() {
961 short openFlowPort = OPENFLOW_PORT;
962 String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
963 if (portString != null) {
965 openFlowPort = Short.parseShort(portString);
966 } catch (NumberFormatException e) {
967 LOG.warn("Invalid port:{}, use default({})", portString,
974 public List<String> getControllersFromOvsdbNode(Node node) {
975 List<String> controllersStr = new ArrayList<>();
977 String controllerIpStr = getControllerIPAddress();
978 if (controllerIpStr != null) {
979 // If codepath makes it here, the ip address to be used was explicitly provided.
980 // Being so, also fetch openflowPort provided via ConfigProperties.
981 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
982 + ":" + controllerIpStr + ":" + getControllerOFPort());
984 // Check if ovsdb node has manager entries
985 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(node);
986 if (ovsdbNodeAugmentation != null) {
987 List<ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
988 if (managerEntries != null && !managerEntries.isEmpty()) {
989 for (ManagerEntry managerEntry : managerEntries) {
990 if (managerEntry == null || managerEntry.getTarget() == null) {
993 String managerStr = managerEntry.getTarget().getValue().toLowerCase(Locale.ROOT);
994 int firstColonIdx = managerStr.indexOf(':');
995 int lastColonIdx = managerStr.lastIndexOf(':');
996 if (lastColonIdx <= firstColonIdx) {
999 controllerIpStr = managerStr.substring(firstColonIdx + 1, lastColonIdx);
1000 if (managerStr.startsWith("tcp")) {
1001 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL + ":" + controllerIpStr + ":"
1002 + getControllerOFPort());
1003 } else if (managerStr.startsWith("ssl")) {
1004 controllersStr.add(OPENFLOW_SECURE_PROTOCOL + ":" + controllerIpStr + ":"
1005 + getControllerOFPort());
1006 } else if (managerStr.startsWith("ptcp")) {
1007 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
1008 /* If we're connected to switch ptcp, only then use connection info
1009 to configure controller. Ptcp is configured as:
1010 Manager "ptcp:<port>:<ip>"
1013 String managerPortStr = managerStr.split(":", 3)[1];
1014 if (connectionInfo != null && connectionInfo.getLocalIp() != null
1015 && connectionInfo.getRemotePort() != null
1016 && managerPortStr.equals(connectionInfo.getRemotePort().toString())) {
1017 IpAddress controllerIp = connectionInfo.getLocalIp();
1018 if (controllerIp.getIpv6Address() != null) {
1019 controllerIpStr = "[" + connectionInfo.getLocalIp().stringValue() + "]";
1021 controllerIpStr = connectionInfo.getLocalIp().stringValue();
1023 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
1024 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
1026 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
1028 } else if (managerStr.startsWith("pssl")) {
1029 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
1030 if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
1031 controllerIpStr = connectionInfo.getLocalIp().stringValue();
1032 controllersStr.add(OPENFLOW_SECURE_PROTOCOL
1033 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
1035 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
1038 LOG.trace("Skipping manager entry {} for node {}",
1039 managerEntry.getTarget(), node.getNodeId().getValue());
1043 LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
1048 if (controllersStr.isEmpty()) {
1049 LOG.warn("Failed to determine OpenFlow controller ip address");
1050 } else if (LOG.isDebugEnabled()) {
1051 LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(),
1052 controllersStr.stream().collect(Collectors.joining(" ")));
1054 return controllersStr;
1057 public long getDataPathId(Node node) {
1059 String datapathId = getDatapathId(node);
1060 if (datapathId != null) {
1061 dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
1066 public String getDataPathIdStr(final Node node) {
1068 long dpId = getDataPathId(node);
1070 return String.valueOf(dpId);
1077 public String getDatapathId(Node node) {
1078 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.augmentation(OvsdbBridgeAugmentation.class);
1079 return getDatapathId(ovsdbBridgeAugmentation);
1082 public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
1083 String datapathId = null;
1084 if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
1085 datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
1090 public String extractBridgeName(Node node) {
1091 return node.augmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
1094 public boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgeName) {
1095 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1096 if (ovsdbNodeAugmentation != null) {
1097 List<ManagedNodeEntry> managedNodes = ovsdbNodeAugmentation.getManagedNodeEntry();
1098 if (managedNodes != null) {
1099 for (ManagedNodeEntry managedNode : managedNodes) {
1100 if (matchesBridgeName(managedNode, bridgeName)) {
1109 // see OVSDB-470 for background
1110 private static boolean matchesBridgeName(ManagedNodeEntry managedNode, String bridgeName) {
1111 InstanceIdentifier<?> bridgeIid = managedNode.getBridgeRef().getValue();
1112 for (PathArgument bridgeIidPathArg : bridgeIid.getPathArguments()) {
1113 if (bridgeIidPathArg instanceof IdentifiableItem<?, ?>) {
1114 IdentifiableItem<?, ?> identifiableItem = (IdentifiableItem<?, ?>) bridgeIidPathArg;
1115 Identifier<?> key = identifiableItem.getKey();
1116 if (key instanceof NodeKey) {
1117 // Do not combine the above if with that below, we want to
1118 // avoid the toString() call in the else if this is a NodeKey
1119 NodeKey nodeKey = (NodeKey) key;
1120 if (nodeKey.getNodeId().getValue().contains(bridgeName)) {
1123 } else if (key.toString().contains(bridgeName)) {
1126 } else if (bridgeIidPathArg instanceof Item<?>) {
1127 if (((Item<?>) bridgeIidPathArg).getType().getName().contains(bridgeName)) {
1131 throw new IllegalArgumentException("Unknown kind of PathArgument: " + bridgeIidPathArg);
1137 public OvsdbBridgeAugmentation getBridgeFromConfig(Node node, String bridge) {
1138 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
1139 InstanceIdentifier<Node> bridgeIid =
1140 createInstanceIdentifier(node.key(), bridge);
1141 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeIid);
1142 if (bridgeNode != null) {
1143 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
1145 return ovsdbBridgeAugmentation;
1148 private static void setManagedByForBridge(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
1149 NodeKey ovsdbNodeKey) {
1150 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(ovsdbNodeKey.getNodeId());
1151 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
1154 public boolean isOvsdbNodeDpdk(Node ovsdbNode) {
1155 boolean found = false;
1156 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1157 if (ovsdbNodeAugmentation != null) {
1158 List<InterfaceTypeEntry> ifTypes = ovsdbNodeAugmentation.getInterfaceTypeEntry();
1159 if (ifTypes != null) {
1160 for (InterfaceTypeEntry ifType : ifTypes) {
1161 if (ifType.getInterfaceType().equals(InterfaceTypeDpdk.class)) {
1171 private static List<ControllerEntry> createControllerEntries(List<String> controllersStr,
1172 Long maxBackoff, Long inactivityProbe) {
1173 List<ControllerEntry> controllerEntries = new ArrayList<>();
1174 if (controllersStr != null) {
1175 for (String controllerStr : controllersStr) {
1176 ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
1177 controllerEntryBuilder.setTarget(new Uri(controllerStr));
1178 if (maxBackoff != null) {
1179 controllerEntryBuilder.setMaxBackoff(maxBackoff);
1181 if (inactivityProbe != null) {
1182 controllerEntryBuilder.setInactivityProbe(inactivityProbe);
1184 controllerEntries.add(controllerEntryBuilder.build());
1187 return controllerEntries;
1190 public OvsdbTerminationPointAugmentation extractTerminationPointAugmentation(Node bridgeNode, String portName) {
1191 if (bridgeNode.augmentation(OvsdbBridgeAugmentation.class) != null) {
1192 List<OvsdbTerminationPointAugmentation> tpAugmentations = extractTerminationPointAugmentations(bridgeNode);
1193 for (OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation : tpAugmentations) {
1194 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1195 return ovsdbTerminationPointAugmentation;
1202 public List<OvsdbTerminationPointAugmentation> extractTerminationPointAugmentations(Node node) {
1203 List<OvsdbTerminationPointAugmentation> tpAugmentations = new ArrayList<>();
1205 LOG.error("extractTerminationPointAugmentations: Node value is null");
1206 return Collections.emptyList();
1208 List<TerminationPoint> terminationPoints = node.getTerminationPoint();
1209 if (terminationPoints != null && !terminationPoints.isEmpty()) {
1210 for (TerminationPoint tp : terminationPoints) {
1211 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1212 tp.augmentation(OvsdbTerminationPointAugmentation.class);
1213 if (ovsdbTerminationPointAugmentation != null) {
1214 tpAugmentations.add(ovsdbTerminationPointAugmentation);
1218 return tpAugmentations;
1222 * Extract the <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code> identified by
1223 * <code>portName</code>.
1225 public OvsdbTerminationPointAugmentation getTerminationPointOfBridge(Node node, String portName) {
1226 OvsdbTerminationPointAugmentation tpAugmentation = extractTerminationPointAugmentation(node,portName);
1227 if (tpAugmentation == null) {
1228 List<OvsdbTerminationPointAugmentation> tpAugmentations = readTerminationPointAugmentations(node);
1229 if (tpAugmentations != null) {
1230 for (OvsdbTerminationPointAugmentation ovsdbTpAugmentation : tpAugmentations) {
1231 if (ovsdbTpAugmentation.getName().equals(portName)) {
1232 return ovsdbTpAugmentation;
1237 return tpAugmentation;
1241 * Read the list of <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code>.
1243 public List<OvsdbTerminationPointAugmentation> readTerminationPointAugmentations(Node node) {
1245 LOG.error("readTerminationPointAugmentations: Node value is null");
1246 return Collections.emptyList();
1248 Node operNode = provider.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier
1249 .create(NetworkTopology.class)
1250 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
1251 .child(Node.class, new NodeKey(node.getNodeId())));
1252 if (operNode != null) {
1253 return extractTerminationPointAugmentations(operNode);
1255 return new ArrayList<>();
1259 * Get all OVSDB nodes from topology.
1260 * @return a list of nodes or null if the topology could not found
1262 public List<Node> getOvsdbNodes() {
1263 InstanceIdentifier<Topology> inst = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
1264 new TopologyKey(OVSDB_TOPOLOGY_ID));
1265 Topology topology = provider.read(LogicalDatastoreType.OPERATIONAL, inst);
1266 return topology != null ? topology.getNode() : null;
1270 * Get OpenvSwitch other-config by key.
1271 * @param node OVSDB node
1272 * @param key key to extract from other-config
1273 * @return the value for key or null if key not found
1275 public String getOpenvswitchOtherConfig(Node node, String key) {
1276 OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
1277 if (ovsdbNode == null) {
1278 Node nodeFromReadOvsdbNode = readOvsdbNode(node);
1279 if (nodeFromReadOvsdbNode != null) {
1280 ovsdbNode = nodeFromReadOvsdbNode.augmentation(OvsdbNodeAugmentation.class);
1284 if (ovsdbNode != null && ovsdbNode.getOpenvswitchOtherConfigs() != null) {
1285 for (OpenvswitchOtherConfigs openvswitchOtherConfigs : ovsdbNode.getOpenvswitchOtherConfigs()) {
1286 if (openvswitchOtherConfigs.getOtherConfigKey().equals(key)) {
1287 return openvswitchOtherConfigs.getOtherConfigValue();
1295 public static TerminationPoint getTerminationPointByExternalId(final Node bridgeNode, final String interfaceName) {
1296 if (bridgeNode.getTerminationPoint() != null) {
1297 for (TerminationPoint tp : bridgeNode.getTerminationPoint()) {
1298 OvsdbTerminationPointAugmentation ovsdbTp = tp.augmentation(OvsdbTerminationPointAugmentation.class);
1299 String externalIdValue = getExternalInterfaceIdValue(ovsdbTp);
1300 if (externalIdValue != null && externalIdValue.equals(interfaceName)) {
1301 LOG.debug("Found matching termination point with iface-id {} on bridgeNode {}, returning tp {}",
1302 interfaceName, bridgeNode, tp);
1310 // This utility shouldn't be called often, as it reads all OVSDB nodes each time - not good for scale
1311 public Node getNodeByTerminationPointExternalId(final String interfaceName) {
1312 List<Node> nodes = getOvsdbNodes();
1313 if (nodes != null) {
1314 for (Node node : nodes) {
1315 TerminationPoint tp = getTerminationPointByExternalId(node, interfaceName);
1324 public static String getExternalInterfaceIdValue(final OvsdbTerminationPointAugmentation ovsdbTp) {
1325 if (ovsdbTp != null) {
1326 List<InterfaceExternalIds> ifaceExtIds = ovsdbTp.getInterfaceExternalIds();
1327 if (ifaceExtIds != null) {
1328 for (InterfaceExternalIds entry : ifaceExtIds) {
1329 if (entry.getExternalIdKey().equals(EXTERNAL_INTERFACE_ID_KEY)) {
1330 return entry.getExternalIdValue();
1338 public String getDatapathIdFromNodeInstanceId(InstanceIdentifier<Node> nodeInstanceId) {
1339 Node node = provider.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
1340 String dpId = node != null ? getDataPathIdStr(node) : null;
1347 public static boolean compareDbVersionToMinVersion(final String dbVersion, final String minVersion) {
1348 if (dbVersion == null || minVersion == null) {
1349 LOG.error("Invalid DB version {} or minVersion {}", dbVersion, minVersion);
1352 final Matcher dbVersionMatcher = PATTERN.matcher(dbVersion);
1353 final Matcher minVersionMatcher = PATTERN.matcher(minVersion);
1354 LOG.debug("dbVersion {}, minVersion {}", dbVersion, minVersion);
1355 if (!dbVersionMatcher.find()) {
1356 LOG.error("Invalid DB version format {}", dbVersion);
1359 if (!minVersionMatcher.find()) {
1360 LOG.error("Invalid Min DB version format {}", minVersion);
1364 if (dbVersion != null && !dbVersion.isEmpty() && minVersion != null && !minVersion.isEmpty()) {
1365 final int dbVersionMatch1 = Integer.parseInt(dbVersionMatcher.group(1));
1366 final int dbVersionMatch2 = Integer.parseInt(dbVersionMatcher.group(2));
1367 final int dbVersionMatch3 = Integer.parseInt(dbVersionMatcher.group(3));
1368 final int minVersionMatch1 = Integer.parseInt(minVersionMatcher.group(1));
1369 final int minVersionMatch2 = Integer.parseInt(minVersionMatcher.group(2));
1370 final int minVersionMatch3 = Integer.parseInt(minVersionMatcher.group(3));
1371 if (dbVersionMatch1 == minVersionMatch1 && dbVersionMatch2 == minVersionMatch2
1372 && dbVersionMatch3 == minVersionMatch3) {
1376 if (dbVersionMatch1 > minVersionMatch1) {
1380 if (dbVersionMatch1 < minVersionMatch1) {
1384 // major version is equal
1385 if (dbVersionMatch2 > minVersionMatch2) {
1389 if (dbVersionMatch2 < minVersionMatch2) {
1393 if (dbVersionMatch3 > minVersionMatch3) {
1400 private List<BridgeExternalIds> setBridgeExternalIds() {
1401 List<BridgeExternalIds> externalIdsList = new ArrayList<>();
1402 externalIdsList.add(new BridgeExternalIdsBuilder()
1403 .setBridgeExternalIdKey(CREATED_BY)
1404 .setBridgeExternalIdValue(ODL)
1406 return externalIdsList;