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.ControllerEntryKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntry;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntryKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntryKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
104 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
105 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
106 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
107 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
108 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
109 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
110 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
111 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
112 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
113 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
114 import org.opendaylight.yangtools.yang.binding.DataObject;
115 import org.opendaylight.yangtools.yang.binding.Identifier;
116 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
117 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
118 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
119 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
120 import org.slf4j.Logger;
121 import org.slf4j.LoggerFactory;
123 public class SouthboundUtils {
124 private abstract static class UtilsProvider {
126 abstract <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path);
128 abstract boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path);
130 abstract <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path,
133 abstract <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data);
137 private static final class ControllerUtilsProvider extends UtilsProvider {
138 private final ControllerMdsalUtils mdsalUtils;
140 ControllerUtilsProvider(final ControllerMdsalUtils mdsalUtils) {
141 this.mdsalUtils = requireNonNull(mdsalUtils);
145 <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path) {
146 return mdsalUtils.read(store, path);
150 <T extends DataObject> boolean put(LogicalDatastoreType store,
151 InstanceIdentifier<T> path, T data) {
152 return mdsalUtils.put(store, path, data);
156 boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
157 return mdsalUtils.delete(store, path);
161 <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
162 return mdsalUtils.merge(store, path, data);
166 private static final class MdsalUtilsProvider extends UtilsProvider {
167 private final MdsalUtils mdsalUtils;
169 MdsalUtilsProvider(final MdsalUtils mdsalUtils) {
170 this.mdsalUtils = requireNonNull(mdsalUtils);
174 <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path) {
175 return mdsalUtils.read(store, path);
179 <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
180 return mdsalUtils.put(store, path, data);
184 boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
185 return mdsalUtils.delete(store, path);
189 <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
190 return mdsalUtils.merge(store, path, data);
194 private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
195 private static final int OVSDB_UPDATE_TIMEOUT = 1000;
196 public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
197 public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
198 public static final String OPENFLOW_SECURE_PROTOCOL = "ssl";
199 public static final short OPENFLOW_PORT = 6653;
200 public static final String OVSDB_URI_PREFIX = "ovsdb";
201 public static final String BRIDGE_URI_PREFIX = "bridge";
202 private static final String DISABLE_IN_BAND = "disable-in-band";
203 private static final String PATCH_PORT_TYPE = "patch";
204 // External ID key used for mapping between an OVSDB port and an interface name
205 private static final InterfaceExternalIdsKey EXTERNAL_INTERFACE_ID_KEY = new InterfaceExternalIdsKey("iface-id");
206 private static final String CREATED_BY = "created_by";
207 private static final String ODL = "odl";
208 private static final String FORMAT = "(\\d+)\\.(\\d+)\\.(\\d+)";
209 private static final Pattern PATTERN = Pattern.compile(FORMAT);
210 // DPDK interface type
211 private static final InterfaceTypeEntryKey DPDK_IFACE_KEY = new InterfaceTypeEntryKey(InterfaceTypeDpdk.class);
213 private final UtilsProvider provider;
216 public SouthboundUtils(ControllerMdsalUtils mdsalUtils) {
217 provider = new ControllerUtilsProvider(mdsalUtils);
220 public SouthboundUtils(MdsalUtils mdsalUtils) {
221 provider = new MdsalUtilsProvider(mdsalUtils);
224 public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
225 = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
226 .put("internal", InterfaceTypeInternal.class)
227 .put("vxlan", InterfaceTypeVxlan.class)
228 .put("vxlan-gpe", InterfaceTypeVxlanGpe.class)
229 .put("patch", InterfaceTypePatch.class)
230 .put("system", InterfaceTypeSystem.class)
231 .put("tap", InterfaceTypeTap.class)
232 .put("geneve", InterfaceTypeGeneve.class)
233 .put("gre", InterfaceTypeGre.class)
234 .put("ipsec_gre", InterfaceTypeIpsecGre.class)
235 .put("gre64", InterfaceTypeGre64.class)
236 .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
237 .put("lisp", InterfaceTypeLisp.class)
238 .put("dpdk", InterfaceTypeDpdk.class)
239 .put("dpdkr", InterfaceTypeDpdkr.class)
240 .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
241 .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
242 .put("dpdkvhostuserclient", InterfaceTypeDpdkvhostuserclient.class)
245 public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>,String> OVSDB_PROTOCOL_MAP
246 = new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>,String>()
247 .put(OvsdbBridgeProtocolOpenflow10.class,"OpenFlow10")
248 .put(OvsdbBridgeProtocolOpenflow11.class,"OpenFlow11")
249 .put(OvsdbBridgeProtocolOpenflow12.class,"OpenFlow12")
250 .put(OvsdbBridgeProtocolOpenflow13.class,"OpenFlow13")
251 .put(OvsdbBridgeProtocolOpenflow14.class,"OpenFlow14")
252 .put(OvsdbBridgeProtocolOpenflow15.class,"OpenFlow15")
255 private static final ImmutableBiMap<Class<? extends OvsdbFailModeBase>,String> OVSDB_FAIL_MODE_MAP
256 = new ImmutableBiMap.Builder<Class<? extends OvsdbFailModeBase>,String>()
257 .put(OvsdbFailModeStandalone.class,"standalone")
258 .put(OvsdbFailModeSecure.class,"secure")
261 public static NodeId createNodeId(IpAddress ip, PortNumber port) {
262 String uriString = OVSDB_URI_PREFIX + "://" + ip.stringValue() + ":" + port.getValue();
263 Uri uri = new Uri(uriString);
264 return new NodeId(uri);
267 public static Node createNode(ConnectionInfo key) {
268 NodeBuilder nodeBuilder = new NodeBuilder();
269 nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()));
270 nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
271 return nodeBuilder.build();
274 public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
275 OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
276 ovsdbNodeBuilder.setConnectionInfo(key);
277 return ovsdbNodeBuilder.build();
280 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
281 return InstanceIdentifier
282 .create(NetworkTopology.class)
283 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
284 .child(Node.class,new NodeKey(nodeId));
287 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeKey ovsdbNodeKey, String bridgeName) {
288 return createInstanceIdentifier(createManagedNodeId(ovsdbNodeKey.getNodeId(), bridgeName));
291 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
292 return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
295 public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
296 InstanceIdentifier<Node> path = InstanceIdentifier
297 .create(NetworkTopology.class)
298 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
299 .child(Node.class,createNodeKey(ip,port));
300 LOG.debug("Created ovsdb path: {}",path);
304 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, OvsdbBridgeName bridgeName) {
305 return createInstanceIdentifier(createManagedNodeId(key, bridgeName));
308 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, String bridgeName) {
309 return createInstanceIdentifier(key, new OvsdbBridgeName(bridgeName));
312 public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName) {
314 InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
315 .create(NetworkTopology.class)
316 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
317 .child(Node.class,node.key())
318 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
320 LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
321 return terminationPointPath;
324 public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
325 return new NodeKey(createNodeId(ip, port));
328 public static NodeId createManagedNodeId(NodeId ovsdbNodeId, String bridgeName) {
329 return new NodeId(ovsdbNodeId.getValue()
330 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName);
333 public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
334 return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
337 public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
338 return new NodeId(createNodeId(ip,port).getValue()
339 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
342 public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
343 NodeKey nodeKey = iid.firstKeyOf(Node.class);
344 return nodeKey.getNodeId();
347 public OvsdbNodeAugmentation extractOvsdbNode(Node node) {
348 return node.augmentation(OvsdbNodeAugmentation.class);
351 public static IpAddress createIpAddress(InetAddress address) {
353 if (address instanceof Inet4Address) {
354 ip = createIpAddress((Inet4Address)address);
355 } else if (address instanceof Inet6Address) {
356 ip = createIpAddress((Inet6Address)address);
361 public static IpAddress createIpAddress(Inet4Address address) {
362 return IetfInetUtil.INSTANCE.ipAddressFor(address);
365 public static IpAddress createIpAddress(Inet6Address address) {
366 Ipv6Address ipv6 = new Ipv6Address(address.getHostAddress());
367 return new IpAddress(ipv6);
370 public ConnectionInfo getConnectionInfo(Node ovsdbNode) {
371 ConnectionInfo connectionInfo = null;
372 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(ovsdbNode);
373 if (ovsdbNodeAugmentation != null) {
374 connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
376 return connectionInfo;
379 public static ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
380 InetAddress inetAddress = null;
382 inetAddress = InetAddress.getByName(addressStr);
383 } catch (UnknownHostException e) {
384 LOG.warn("Could not allocate InetAddress", e);
387 IpAddress address = createIpAddress(inetAddress);
388 PortNumber port = new PortNumber(Integer.parseInt(portStr));
390 LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
391 .setRemoteIp(address)
394 return new ConnectionInfoBuilder()
395 .setRemoteIp(address)
400 public static String connectionInfoToString(final ConnectionInfo connectionInfo) {
401 return connectionInfo.getRemoteIp().stringValue() + ":" + connectionInfo.getRemotePort().getValue();
404 public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
405 return addOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
408 public boolean addOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
409 boolean result = provider.put(LogicalDatastoreType.CONFIGURATION,
410 createInstanceIdentifier(connectionInfo),
411 createNode(connectionInfo));
414 Thread.sleep(timeout);
415 } catch (InterruptedException e) {
416 LOG.warn("Interrupted while waiting after adding OVSDB node {}",
417 connectionInfoToString(connectionInfo), e);
423 public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
424 return provider.read(LogicalDatastoreType.OPERATIONAL,
425 createInstanceIdentifier(connectionInfo));
428 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
429 return deleteOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
432 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
433 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
434 createInstanceIdentifier(connectionInfo));
437 Thread.sleep(timeout);
438 } catch (InterruptedException e) {
439 LOG.warn("Interrupted while waiting after deleting OVSDB node {}",
440 connectionInfoToString(connectionInfo), e);
446 public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
447 return connectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
450 public Node connectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
451 addOvsdbNode(connectionInfo, timeout);
452 Node node = getOvsdbNode(connectionInfo);
453 LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
457 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
458 return disconnectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
461 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
462 deleteOvsdbNode(connectionInfo, timeout);
463 LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
467 public List<ControllerEntry> createControllerEntry(String controllerTarget) {
468 List<ControllerEntry> controllerEntriesList = new ArrayList<>();
469 controllerEntriesList.add(new ControllerEntryBuilder()
470 .setTarget(new Uri(controllerTarget))
472 return controllerEntriesList;
476 * Extract the <code>store</code> type data store contents for the particular bridge identified by
477 * <code>bridgeName</code>.
479 * @param connectionInfo address for the node
480 * @param bridgeName name of the bridge
481 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
482 * @return <code>store</code> type data store contents
484 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
485 LogicalDatastoreType store) {
486 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
487 Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
488 if (bridgeNode != null) {
489 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
491 return ovsdbBridgeAugmentation;
495 * Extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
496 * identified by <code>bridgeName</code>.
498 * @param connectionInfo address for the node
499 * @param bridgeName name of the bridge
500 * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
501 * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
503 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
504 return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
508 * Extract the node contents from <code>store</code> type data store for the
509 * bridge identified by <code>bridgeName</code>.
511 * @param connectionInfo address for the node
512 * @param bridgeName name of the bridge
513 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
514 * @return <code>store</code> type data store contents
516 public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
517 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
518 return provider.read(store, bridgeIid);
521 public Node getBridgeNode(Node node, String bridgeName) {
522 OvsdbBridgeAugmentation bridge = extractBridgeAugmentation(node);
523 if (bridge != null && bridge.getBridgeName().getValue().equals(bridgeName)) {
526 return readBridgeNode(node, bridgeName);
530 public Node readBridgeNode(Node node, String name) {
531 Node ovsdbNode = node;
532 if (extractNodeAugmentation(ovsdbNode) == null) {
533 ovsdbNode = readOvsdbNode(node);
534 if (ovsdbNode == null) {
538 Node bridgeNode = null;
539 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
540 if (connectionInfo != null) {
541 InstanceIdentifier<Node> bridgeIid =
542 createInstanceIdentifier(node.key(), name);
543 bridgeNode = provider.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
548 public OvsdbNodeAugmentation extractNodeAugmentation(Node node) {
549 return node.augmentation(OvsdbNodeAugmentation.class);
552 public OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
556 return node.augmentation(OvsdbBridgeAugmentation.class);
559 public Node readOvsdbNode(Node bridgeNode) {
560 Node ovsdbNode = null;
561 OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
562 if (bridgeAugmentation != null) {
563 InstanceIdentifier<Node> ovsdbNodeIid =
564 (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
565 ovsdbNode = provider.read(LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
567 LOG.debug("readOvsdbNode: Provided node is not a bridge node : {}",bridgeNode);
572 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
573 return deleteBridge(connectionInfo, bridgeName, OVSDB_UPDATE_TIMEOUT);
576 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName, long timeout) {
577 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
578 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
581 Thread.sleep(timeout);
582 } catch (InterruptedException e) {
583 LOG.warn("Interrupted while waiting after deleting bridge {}", bridgeName, e);
589 public List<ProtocolEntry> createMdsalProtocols() {
590 List<ProtocolEntry> protocolList = new ArrayList<>();
591 ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
592 OVSDB_PROTOCOL_MAP.inverse();
593 protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
598 * base method for adding test bridges. Other helper methods used to create bridges should utilize this method.
600 * @param connectionInfo
601 * @param bridgeIid if passed null, one is created
602 * @param bridgeName cannot be null
603 * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
604 * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
605 * @param failMode toggles whether default fail mode is set for the bridge
606 * @param setManagedBy toggles whether to setManagedBy for the bridge
607 * @param dpType if passed null, this parameter is ignored
608 * @param externalIds if passed null, this parameter is ignored
609 * @param otherConfig if passed null, this parameter is ignored
610 * @return success of bridge addition
611 * @throws InterruptedException
613 public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
614 final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
615 final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
616 final Class<? extends DatapathTypeBase> dpType,
617 final List<BridgeExternalIds> externalIds,
618 final List<ControllerEntry> controllerEntries,
619 final List<BridgeOtherConfigs> otherConfigs,
620 final String dpid, long timeout) throws InterruptedException {
622 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
623 if (bridgeIid == null) {
624 bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
626 if (bridgeNodeId == null) {
627 bridgeNodeId = createManagedNodeId(bridgeIid);
629 bridgeNodeBuilder.setNodeId(bridgeNodeId);
630 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
631 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
632 if (setProtocolEntries) {
633 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
635 if (failMode != null) {
636 ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
639 setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
641 if (dpType != null) {
642 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
644 if (externalIds != null) {
645 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
647 if (controllerEntries != null) {
648 ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
650 if (otherConfigs != null) {
651 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
653 if (dpid != null && !dpid.isEmpty()) {
654 DatapathId datapathId = new DatapathId(dpid);
655 ovsdbBridgeAugmentationBuilder.setDatapathId(datapathId);
657 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
658 LOG.debug("Built with the intent to store bridge data {}",
659 ovsdbBridgeAugmentationBuilder.toString());
660 boolean result = provider.merge(LogicalDatastoreType.CONFIGURATION,
661 bridgeIid, bridgeNodeBuilder.build());
663 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
668 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
669 final Class<? extends DatapathTypeBase> dpType, String mac) {
670 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, mac, null, null);
673 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
674 final Class<? extends DatapathTypeBase> dpType, String mac,
675 Long maxBackoff, Long inactivityProbe) {
676 List<BridgeOtherConfigs> otherConfigs = new ArrayList<>();
678 BridgeOtherConfigsBuilder macOtherConfigBuilder = new BridgeOtherConfigsBuilder();
679 macOtherConfigBuilder.setBridgeOtherConfigKey("hwaddr");
680 macOtherConfigBuilder.setBridgeOtherConfigValue(mac);
681 otherConfigs.add(macOtherConfigBuilder.build());
684 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, otherConfigs, null, null);
687 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
688 final Class<? extends DatapathTypeBase> dpType,
689 List<BridgeOtherConfigs> otherConfigs,
690 Long maxBackoff, Long inactivityProbe) {
693 LOG.info("addBridge: node: {}, bridgeName: {}, controller(s): {}", ovsdbNode, bridgeName, controllersStr);
694 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
695 if (connectionInfo != null) {
696 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
697 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
698 NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
699 bridgeNodeBuilder.setNodeId(bridgeNodeId);
700 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
701 ovsdbBridgeAugmentationBuilder.setControllerEntry(createControllerEntries(
702 controllersStr, maxBackoff, inactivityProbe));
703 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
704 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
705 ovsdbBridgeAugmentationBuilder.setFailMode(OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
706 // TODO: Currently netvirt relies on this function to set disabled-in-band=true. However,
707 // TODO (cont): a better design would be to have netvirt pass that in. That way this function
708 // TODO (cont): can take a null otherConfigs to erase other_configs.
709 if (otherConfigs == null) {
710 otherConfigs = new ArrayList<>();
712 BridgeOtherConfigsBuilder bridgeOtherConfigsBuilder = new BridgeOtherConfigsBuilder();
713 bridgeOtherConfigsBuilder.setBridgeOtherConfigKey(DISABLE_IN_BAND);
714 bridgeOtherConfigsBuilder.setBridgeOtherConfigValue("true");
715 otherConfigs.add(bridgeOtherConfigsBuilder.build());
716 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
717 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(setBridgeExternalIds());
718 setManagedByForBridge(ovsdbBridgeAugmentationBuilder, ovsdbNode.key());
719 if (dpType != null) {
720 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
722 if (isOvsdbNodeDpdk(ovsdbNode)) {
723 ovsdbBridgeAugmentationBuilder.setDatapathType(DatapathTypeNetdev.class);
725 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
727 Node node = bridgeNodeBuilder.build();
728 result = provider.put(LogicalDatastoreType.CONFIGURATION, bridgeIid, node);
729 LOG.info("addBridge: result: {}", result);
731 throw new InvalidParameterException("Could not find ConnectionInfo");
737 * Set the controllers of an existing bridge node.
739 * @param ovsdbNode where the bridge is
740 * @param bridgeName Name of the bridge
741 * @param controllers controller strings
742 * @return success if the write to md-sal was successful
744 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers) {
745 return setBridgeController(ovsdbNode, bridgeName, controllers, null, null);
749 * Set the controllers of an existing bridge node.
751 * @param ovsdbNode where the bridge is
752 * @param bridgeName Name of the bridge
753 * @param controllers controller strings
754 * @param maxBackoff Max backoff in milliseconds
755 * @param inactivityProbe inactivity probe in milliseconds
756 * @return success if the write to md-sal was successful
758 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers,
759 Long maxBackoff, Long inactivityProbe) {
760 LOG.debug("setBridgeController: ovsdbNode: {}, bridgeNode: {}, controller(s): {}",
761 ovsdbNode, bridgeName, controllers);
763 InstanceIdentifier<Node> bridgeNodeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
764 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid);
765 if (bridgeNode == null) {
766 LOG.info("setBridgeController could not find bridge in configuration {}", bridgeNodeIid);
770 OvsdbBridgeAugmentation bridgeAug = extractBridgeAugmentation(bridgeNode);
772 //Only add controller entries that do not already exist on this bridge
773 Map<ControllerEntryKey, ControllerEntry> existingControllerEntries = bridgeAug.getControllerEntry();
774 List<ControllerEntry> newControllerEntries = new ArrayList<>();
775 if (existingControllerEntries != null) {
777 for (ControllerEntry newEntry : createControllerEntries(controllers, maxBackoff, inactivityProbe)) {
778 for (ControllerEntry existingEntry : existingControllerEntries.values()) {
779 if (newEntry.getTarget().equals(existingEntry.getTarget())) {
780 continue NEW_ENTRY_LOOP;
783 newControllerEntries.add(newEntry);
786 newControllerEntries = createControllerEntries(controllers,maxBackoff, inactivityProbe);
789 if (newControllerEntries.isEmpty()) {
793 NodeBuilder nodeBuilder = new NodeBuilder(bridgeNode);
794 OvsdbBridgeAugmentationBuilder augBuilder = new OvsdbBridgeAugmentationBuilder(bridgeAug);
796 augBuilder.setControllerEntry(newControllerEntries);
797 nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, augBuilder.build());
798 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
799 return provider.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, nodeBuilder.build());
802 private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
803 final ConnectionInfo connectionInfo) {
804 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
805 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
808 public boolean addTerminationPoint(
809 Node bridgeNode, String portName, String type, Map<String, String> options,
810 Map<String, String> externalIds) {
811 return addTerminationPoint(bridgeNode, portName, type, options, externalIds, null);
814 public boolean addTerminationPoint(
815 Node bridgeNode, String portName, String type, Map<String, String> options, Map<String, String> externalIds,
817 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
819 tpAugmentationBuilder.setName(portName);
820 tpAugmentationBuilder.setOfport(ofPort);
822 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
825 if (options != null && options.size() > 0) {
826 List<Options> optionsList = new ArrayList<>();
827 for (Map.Entry<String, String> entry : options.entrySet()) {
828 OptionsBuilder optionsBuilder = new OptionsBuilder();
829 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
830 optionsBuilder.setOption(entry.getKey());
831 optionsBuilder.setValue(entry.getValue());
832 optionsList.add(optionsBuilder.build());
834 tpAugmentationBuilder.setOptions(optionsList);
837 if (externalIds != null && externalIds.size() > 0) {
838 List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
839 for (Map.Entry<String, String> entry : externalIds.entrySet()) {
840 InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
841 interfaceExternalIdsBuilder.withKey(new InterfaceExternalIdsKey(entry.getKey()));
842 interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
843 interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
844 externalIdsList.add(interfaceExternalIdsBuilder.build());
846 tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
849 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
850 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
851 tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
852 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
853 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
856 public Boolean addTerminationPoint(Node bridgeNode, String portName, String type) {
857 return addTerminationPoint(bridgeNode, portName, type, Collections.EMPTY_MAP, null);
860 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
861 String type, Map<String, String> options) {
862 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
864 tpAugmentationBuilder.setName(portName);
866 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
869 List<Options> optionsList = new ArrayList<>();
870 for (Map.Entry<String, String> entry : options.entrySet()) {
871 OptionsBuilder optionsBuilder = new OptionsBuilder();
872 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
873 optionsBuilder.setOption(entry.getKey());
874 optionsBuilder.setValue(entry.getValue());
875 optionsList.add(optionsBuilder.build());
877 tpAugmentationBuilder.setOptions(optionsList);
879 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
880 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
881 tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
882 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
883 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
886 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
887 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
888 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
889 new OvsdbTerminationPointAugmentationBuilder();
891 tpAugmentationBuilder.setName(portName);
893 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
895 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
896 tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
897 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
898 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
901 public Boolean addPatchTerminationPoint(Node node, String bridgeName, String portName, String peerPortName) {
902 Map<String, String> option = new HashMap<>();
903 option.put("peer", peerPortName);
904 return addTerminationPoint(node, bridgeName, portName, PATCH_PORT_TYPE, option);
907 private String getControllerIPAddress() {
908 String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
909 if (addressString != null) {
911 if (InetAddress.getByName(addressString) != null) {
912 return addressString;
914 } catch (UnknownHostException e) {
915 LOG.error("Host {} is invalid", addressString, e);
919 addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
920 if (addressString != null) {
922 if (InetAddress.getByName(addressString) != null) {
923 return addressString;
925 } catch (UnknownHostException e) {
926 LOG.error("Host {} is invalid", addressString, e);
933 private short getControllerOFPort() {
934 short openFlowPort = OPENFLOW_PORT;
935 String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
936 if (portString != null) {
938 openFlowPort = Short.parseShort(portString);
939 } catch (NumberFormatException e) {
940 LOG.warn("Invalid port:{}, use default({})", portString,
947 public List<String> getControllersFromOvsdbNode(Node node) {
948 List<String> controllersStr = new ArrayList<>();
950 String controllerIpStr = getControllerIPAddress();
951 if (controllerIpStr != null) {
952 // If codepath makes it here, the ip address to be used was explicitly provided.
953 // Being so, also fetch openflowPort provided via ConfigProperties.
954 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
955 + ":" + controllerIpStr + ":" + getControllerOFPort());
957 // Check if ovsdb node has manager entries
958 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(node);
959 if (ovsdbNodeAugmentation != null) {
960 Map<ManagerEntryKey, ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
961 if (managerEntries != null && !managerEntries.isEmpty()) {
962 for (ManagerEntry managerEntry : managerEntries.values()) {
963 if (managerEntry == null || managerEntry.getTarget() == null) {
966 String managerStr = managerEntry.getTarget().getValue().toLowerCase(Locale.ROOT);
967 int firstColonIdx = managerStr.indexOf(':');
968 int lastColonIdx = managerStr.lastIndexOf(':');
969 if (lastColonIdx <= firstColonIdx) {
972 controllerIpStr = managerStr.substring(firstColonIdx + 1, lastColonIdx);
973 if (managerStr.startsWith("tcp")) {
974 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL + ":" + controllerIpStr + ":"
975 + getControllerOFPort());
976 } else if (managerStr.startsWith("ssl")) {
977 controllersStr.add(OPENFLOW_SECURE_PROTOCOL + ":" + controllerIpStr + ":"
978 + getControllerOFPort());
979 } else if (managerStr.startsWith("ptcp")) {
980 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
981 /* If we're connected to switch ptcp, only then use connection info
982 to configure controller. Ptcp is configured as:
983 Manager "ptcp:<port>:<ip>"
986 String managerPortStr = managerStr.split(":", 3)[1];
987 if (connectionInfo != null && connectionInfo.getLocalIp() != null
988 && connectionInfo.getRemotePort() != null
989 && managerPortStr.equals(connectionInfo.getRemotePort().toString())) {
990 IpAddress controllerIp = connectionInfo.getLocalIp();
991 if (controllerIp.getIpv6Address() != null) {
992 controllerIpStr = "[" + connectionInfo.getLocalIp().stringValue() + "]";
994 controllerIpStr = connectionInfo.getLocalIp().stringValue();
996 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
997 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
999 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
1001 } else if (managerStr.startsWith("pssl")) {
1002 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
1003 if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
1004 controllerIpStr = connectionInfo.getLocalIp().stringValue();
1005 controllersStr.add(OPENFLOW_SECURE_PROTOCOL
1006 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
1008 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
1011 LOG.trace("Skipping manager entry {} for node {}",
1012 managerEntry.getTarget(), node.getNodeId().getValue());
1016 LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
1021 if (controllersStr.isEmpty()) {
1022 LOG.warn("Failed to determine OpenFlow controller ip address");
1023 } else if (LOG.isDebugEnabled()) {
1024 LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(),
1025 controllersStr.stream().collect(Collectors.joining(" ")));
1027 return controllersStr;
1030 public long getDataPathId(Node node) {
1032 String datapathId = getDatapathId(node);
1033 if (datapathId != null) {
1034 dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
1039 public String getDataPathIdStr(final Node node) {
1041 long dpId = getDataPathId(node);
1043 return String.valueOf(dpId);
1050 public String getDatapathId(Node node) {
1051 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.augmentation(OvsdbBridgeAugmentation.class);
1052 return getDatapathId(ovsdbBridgeAugmentation);
1055 public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
1056 String datapathId = null;
1057 if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
1058 datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
1063 public String extractBridgeName(Node node) {
1064 return node.augmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
1067 public boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgeName) {
1068 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1069 if (ovsdbNodeAugmentation != null) {
1070 Map<ManagedNodeEntryKey, ManagedNodeEntry> managedNodes = ovsdbNodeAugmentation.getManagedNodeEntry();
1071 if (managedNodes != null) {
1072 for (ManagedNodeEntry managedNode : managedNodes.values()) {
1073 if (matchesBridgeName(managedNode, bridgeName)) {
1082 // see OVSDB-470 for background
1083 private static boolean matchesBridgeName(ManagedNodeEntry managedNode, String bridgeName) {
1084 InstanceIdentifier<?> bridgeIid = managedNode.getBridgeRef().getValue();
1085 for (PathArgument bridgeIidPathArg : bridgeIid.getPathArguments()) {
1086 if (bridgeIidPathArg instanceof IdentifiableItem<?, ?>) {
1087 IdentifiableItem<?, ?> identifiableItem = (IdentifiableItem<?, ?>) bridgeIidPathArg;
1088 Identifier<?> key = identifiableItem.getKey();
1089 if (key instanceof NodeKey) {
1090 // Do not combine the above if with that below, we want to
1091 // avoid the toString() call in the else if this is a NodeKey
1092 NodeKey nodeKey = (NodeKey) key;
1093 if (nodeKey.getNodeId().getValue().contains(bridgeName)) {
1096 } else if (key.toString().contains(bridgeName)) {
1099 } else if (bridgeIidPathArg instanceof Item<?>) {
1100 if (((Item<?>) bridgeIidPathArg).getType().getName().contains(bridgeName)) {
1104 throw new IllegalArgumentException("Unknown kind of PathArgument: " + bridgeIidPathArg);
1110 public OvsdbBridgeAugmentation getBridgeFromConfig(Node node, String bridge) {
1111 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
1112 InstanceIdentifier<Node> bridgeIid =
1113 createInstanceIdentifier(node.key(), bridge);
1114 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeIid);
1115 if (bridgeNode != null) {
1116 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
1118 return ovsdbBridgeAugmentation;
1121 private static void setManagedByForBridge(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
1122 NodeKey ovsdbNodeKey) {
1123 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(ovsdbNodeKey.getNodeId());
1124 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
1127 public boolean isOvsdbNodeDpdk(Node ovsdbNode) {
1128 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1129 if (ovsdbNodeAugmentation != null) {
1130 Map<InterfaceTypeEntryKey, InterfaceTypeEntry> ifTypes = ovsdbNodeAugmentation.getInterfaceTypeEntry();
1131 if (ifTypes != null) {
1132 if (ifTypes.containsKey(DPDK_IFACE_KEY)) {
1140 private static List<ControllerEntry> createControllerEntries(List<String> controllersStr,
1141 Long maxBackoff, Long inactivityProbe) {
1142 List<ControllerEntry> controllerEntries = new ArrayList<>();
1143 if (controllersStr != null) {
1144 for (String controllerStr : controllersStr) {
1145 ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
1146 controllerEntryBuilder.setTarget(new Uri(controllerStr));
1147 if (maxBackoff != null) {
1148 controllerEntryBuilder.setMaxBackoff(maxBackoff);
1150 if (inactivityProbe != null) {
1151 controllerEntryBuilder.setInactivityProbe(inactivityProbe);
1153 controllerEntries.add(controllerEntryBuilder.build());
1156 return controllerEntries;
1159 public OvsdbTerminationPointAugmentation extractTerminationPointAugmentation(Node bridgeNode, String portName) {
1160 if (bridgeNode.augmentation(OvsdbBridgeAugmentation.class) != null) {
1161 List<OvsdbTerminationPointAugmentation> tpAugmentations = extractTerminationPointAugmentations(bridgeNode);
1162 for (OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation : tpAugmentations) {
1163 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1164 return ovsdbTerminationPointAugmentation;
1171 public List<OvsdbTerminationPointAugmentation> extractTerminationPointAugmentations(Node node) {
1172 List<OvsdbTerminationPointAugmentation> tpAugmentations = new ArrayList<>();
1174 LOG.error("extractTerminationPointAugmentations: Node value is null");
1175 return Collections.emptyList();
1177 Map<TerminationPointKey, TerminationPoint> terminationPoints = node.getTerminationPoint();
1178 if (terminationPoints != null && !terminationPoints.isEmpty()) {
1179 for (TerminationPoint tp : terminationPoints.values()) {
1180 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1181 tp.augmentation(OvsdbTerminationPointAugmentation.class);
1182 if (ovsdbTerminationPointAugmentation != null) {
1183 tpAugmentations.add(ovsdbTerminationPointAugmentation);
1187 return tpAugmentations;
1191 * Extract the <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code> identified by
1192 * <code>portName</code>.
1194 public OvsdbTerminationPointAugmentation getTerminationPointOfBridge(Node node, String portName) {
1195 OvsdbTerminationPointAugmentation tpAugmentation = extractTerminationPointAugmentation(node,portName);
1196 if (tpAugmentation == null) {
1197 List<OvsdbTerminationPointAugmentation> tpAugmentations = readTerminationPointAugmentations(node);
1198 if (tpAugmentations != null) {
1199 for (OvsdbTerminationPointAugmentation ovsdbTpAugmentation : tpAugmentations) {
1200 if (ovsdbTpAugmentation.getName().equals(portName)) {
1201 return ovsdbTpAugmentation;
1206 return tpAugmentation;
1210 * Read the list of <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code>.
1212 public List<OvsdbTerminationPointAugmentation> readTerminationPointAugmentations(Node node) {
1214 LOG.error("readTerminationPointAugmentations: Node value is null");
1215 return Collections.emptyList();
1217 Node operNode = provider.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier
1218 .create(NetworkTopology.class)
1219 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
1220 .child(Node.class, new NodeKey(node.getNodeId())));
1221 if (operNode != null) {
1222 return extractTerminationPointAugmentations(operNode);
1224 return new ArrayList<>();
1228 * Get all OVSDB nodes from topology.
1229 * @return a list of nodes or null if the topology could not found
1231 public Map<NodeKey, Node> getOvsdbNodes() {
1232 InstanceIdentifier<Topology> inst = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
1233 new TopologyKey(OVSDB_TOPOLOGY_ID));
1234 Topology topology = provider.read(LogicalDatastoreType.OPERATIONAL, inst);
1235 return topology != null ? topology.getNode() : null;
1239 * Get OpenvSwitch other-config by key.
1240 * @param node OVSDB node
1241 * @param key key to extract from other-config
1242 * @return the value for key or null if key not found
1244 public String getOpenvswitchOtherConfig(Node node, String key) {
1245 OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
1246 if (ovsdbNode == null) {
1247 Node nodeFromReadOvsdbNode = readOvsdbNode(node);
1248 if (nodeFromReadOvsdbNode != null) {
1249 ovsdbNode = nodeFromReadOvsdbNode.augmentation(OvsdbNodeAugmentation.class);
1253 if (ovsdbNode != null) {
1254 final OpenvswitchOtherConfigs found = ovsdbNode.nonnullOpenvswitchOtherConfigs()
1255 .get(new OpenvswitchOtherConfigsKey(key));
1256 if (found != null) {
1257 return found.getOtherConfigValue();
1264 public static TerminationPoint getTerminationPointByExternalId(final Node bridgeNode, final String interfaceName) {
1265 final Map<TerminationPointKey, TerminationPoint> tps = bridgeNode.getTerminationPoint();
1267 for (TerminationPoint tp : tps.values()) {
1268 OvsdbTerminationPointAugmentation ovsdbTp = tp.augmentation(OvsdbTerminationPointAugmentation.class);
1269 String externalIdValue = getExternalInterfaceIdValue(ovsdbTp);
1270 if (externalIdValue != null && externalIdValue.equals(interfaceName)) {
1271 LOG.debug("Found matching termination point with iface-id {} on bridgeNode {}, returning tp {}",
1272 interfaceName, bridgeNode, tp);
1280 // This utility shouldn't be called often, as it reads all OVSDB nodes each time - not good for scale
1281 public Node getNodeByTerminationPointExternalId(final String interfaceName) {
1282 Map<NodeKey, Node> nodes = getOvsdbNodes();
1283 if (nodes != null) {
1284 for (Node node : nodes.values()) {
1285 TerminationPoint tp = getTerminationPointByExternalId(node, interfaceName);
1294 public static String getExternalInterfaceIdValue(final OvsdbTerminationPointAugmentation ovsdbTp) {
1295 if (ovsdbTp != null) {
1296 Map<InterfaceExternalIdsKey, InterfaceExternalIds> ifaceExtIds = ovsdbTp.getInterfaceExternalIds();
1297 if (ifaceExtIds != null) {
1298 final InterfaceExternalIds entry = ifaceExtIds.get(EXTERNAL_INTERFACE_ID_KEY);
1299 if (entry != null) {
1300 return entry.getExternalIdValue();
1307 public String getDatapathIdFromNodeInstanceId(InstanceIdentifier<Node> nodeInstanceId) {
1308 Node node = provider.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
1309 String dpId = node != null ? getDataPathIdStr(node) : null;
1316 public static boolean compareDbVersionToMinVersion(final String dbVersion, final String minVersion) {
1317 if (dbVersion == null || minVersion == null) {
1318 LOG.error("Invalid DB version {} or minVersion {}", dbVersion, minVersion);
1321 final Matcher dbVersionMatcher = PATTERN.matcher(dbVersion);
1322 final Matcher minVersionMatcher = PATTERN.matcher(minVersion);
1323 LOG.debug("dbVersion {}, minVersion {}", dbVersion, minVersion);
1324 if (!dbVersionMatcher.find()) {
1325 LOG.error("Invalid DB version format {}", dbVersion);
1328 if (!minVersionMatcher.find()) {
1329 LOG.error("Invalid Min DB version format {}", minVersion);
1333 if (dbVersion != null && !dbVersion.isEmpty() && minVersion != null && !minVersion.isEmpty()) {
1334 final int dbVersionMatch1 = Integer.parseInt(dbVersionMatcher.group(1));
1335 final int dbVersionMatch2 = Integer.parseInt(dbVersionMatcher.group(2));
1336 final int dbVersionMatch3 = Integer.parseInt(dbVersionMatcher.group(3));
1337 final int minVersionMatch1 = Integer.parseInt(minVersionMatcher.group(1));
1338 final int minVersionMatch2 = Integer.parseInt(minVersionMatcher.group(2));
1339 final int minVersionMatch3 = Integer.parseInt(minVersionMatcher.group(3));
1340 if (dbVersionMatch1 == minVersionMatch1 && dbVersionMatch2 == minVersionMatch2
1341 && dbVersionMatch3 == minVersionMatch3) {
1345 if (dbVersionMatch1 > minVersionMatch1) {
1349 if (dbVersionMatch1 < minVersionMatch1) {
1353 // major version is equal
1354 if (dbVersionMatch2 > minVersionMatch2) {
1358 if (dbVersionMatch2 < minVersionMatch2) {
1362 if (dbVersionMatch3 > minVersionMatch3) {
1369 private List<BridgeExternalIds> setBridgeExternalIds() {
1370 List<BridgeExternalIds> externalIdsList = new ArrayList<>();
1371 externalIdsList.add(new BridgeExternalIdsBuilder()
1372 .setBridgeExternalIdKey(CREATED_BY)
1373 .setBridgeExternalIdValue(ODL)
1375 return externalIdsList;