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 com.google.common.collect.ImmutableMap;
15 import java.math.BigInteger;
16 import java.net.Inet4Address;
17 import java.net.Inet6Address;
18 import java.net.InetAddress;
19 import java.net.UnknownHostException;
20 import java.security.InvalidParameterException;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Locale;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29 import java.util.stream.Collectors;
30 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
31 import org.opendaylight.ovsdb.utils.config.ConfigProperties;
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.BridgeExternalIdsKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntry;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntryKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntryKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsKey;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
105 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
106 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
107 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
108 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
109 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
110 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
111 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
112 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
113 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
114 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
115 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
116 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
117 import org.opendaylight.yangtools.yang.binding.DataObject;
118 import org.opendaylight.yangtools.yang.binding.Identifier;
119 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
120 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
121 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
122 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
123 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
124 import org.opendaylight.yangtools.yang.common.Uint16;
125 import org.opendaylight.yangtools.yang.common.Uint32;
126 import org.slf4j.Logger;
127 import org.slf4j.LoggerFactory;
129 public class SouthboundUtils {
130 private abstract static class UtilsProvider {
132 abstract <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path);
134 abstract boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path);
136 abstract <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path,
139 abstract <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data);
142 private static final class MdsalUtilsProvider extends UtilsProvider {
143 private final MdsalUtils mdsalUtils;
145 MdsalUtilsProvider(final MdsalUtils mdsalUtils) {
146 this.mdsalUtils = requireNonNull(mdsalUtils);
150 <T extends DataObject> T read(LogicalDatastoreType store, InstanceIdentifier<T> path) {
151 return mdsalUtils.read(store, path);
155 <T extends DataObject> boolean put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
156 return mdsalUtils.put(store, path, data);
160 boolean delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
161 return mdsalUtils.delete(store, path);
165 <T extends DataObject> boolean merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
166 return mdsalUtils.merge(store, path, data);
170 private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
171 private static final int OVSDB_UPDATE_TIMEOUT = 1000;
172 public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
173 public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
174 public static final String OPENFLOW_SECURE_PROTOCOL = "ssl";
175 public static final short OPENFLOW_PORT = 6653;
176 public static final String OVSDB_URI_PREFIX = "ovsdb";
177 public static final String BRIDGE_URI_PREFIX = "bridge";
178 private static final String DISABLE_IN_BAND = "disable-in-band";
179 private static final String PATCH_PORT_TYPE = "patch";
180 // External ID key used for mapping between an OVSDB port and an interface name
181 private static final InterfaceExternalIdsKey EXTERNAL_INTERFACE_ID_KEY = new InterfaceExternalIdsKey("iface-id");
182 private static final String CREATED_BY = "created_by";
183 private static final String ODL = "odl";
184 private static final String FORMAT = "(\\d+)\\.(\\d+)\\.(\\d+)";
185 private static final Pattern PATTERN = Pattern.compile(FORMAT);
186 // DPDK interface type
187 private static final InterfaceTypeEntryKey DPDK_IFACE_KEY = new InterfaceTypeEntryKey(InterfaceTypeDpdk.class);
189 private final UtilsProvider provider;
191 public SouthboundUtils(MdsalUtils mdsalUtils) {
192 provider = new MdsalUtilsProvider(mdsalUtils);
195 public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP =
196 new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
197 .put("internal", InterfaceTypeInternal.class)
198 .put("vxlan", InterfaceTypeVxlan.class)
199 .put("vxlan-gpe", InterfaceTypeVxlanGpe.class)
200 .put("patch", InterfaceTypePatch.class)
201 .put("system", InterfaceTypeSystem.class)
202 .put("tap", InterfaceTypeTap.class)
203 .put("geneve", InterfaceTypeGeneve.class)
204 .put("gre", InterfaceTypeGre.class)
205 .put("ipsec_gre", InterfaceTypeIpsecGre.class)
206 .put("gre64", InterfaceTypeGre64.class)
207 .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
208 .put("lisp", InterfaceTypeLisp.class)
209 .put("dpdk", InterfaceTypeDpdk.class)
210 .put("dpdkr", InterfaceTypeDpdkr.class)
211 .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
212 .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
213 .put("dpdkvhostuserclient", InterfaceTypeDpdkvhostuserclient.class)
216 public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>, String> OVSDB_PROTOCOL_MAP =
217 new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>, String>()
218 .put(OvsdbBridgeProtocolOpenflow10.class,"OpenFlow10")
219 .put(OvsdbBridgeProtocolOpenflow11.class,"OpenFlow11")
220 .put(OvsdbBridgeProtocolOpenflow12.class,"OpenFlow12")
221 .put(OvsdbBridgeProtocolOpenflow13.class,"OpenFlow13")
222 .put(OvsdbBridgeProtocolOpenflow14.class,"OpenFlow14")
223 .put(OvsdbBridgeProtocolOpenflow15.class,"OpenFlow15")
226 private static final ImmutableBiMap<Class<? extends OvsdbFailModeBase>, String> OVSDB_FAIL_MODE_MAP =
227 new ImmutableBiMap.Builder<Class<? extends OvsdbFailModeBase>, String>()
228 .put(OvsdbFailModeStandalone.class,"standalone")
229 .put(OvsdbFailModeSecure.class,"secure")
232 private static final BridgeOtherConfigs OTHER_CONFIG_DISABLE_INBAND = new BridgeOtherConfigsBuilder()
233 .setBridgeOtherConfigKey(DISABLE_IN_BAND)
234 .setBridgeOtherConfigValue("true")
236 private static final Map<BridgeOtherConfigsKey, BridgeOtherConfigs> DEFAULT_OTHER_CONFIGS =
237 BindingMap.of(OTHER_CONFIG_DISABLE_INBAND);
239 public static NodeId createNodeId(IpAddress ip, PortNumber port) {
240 String uriString = OVSDB_URI_PREFIX + "://" + ip.stringValue() + ":" + port.getValue();
241 Uri uri = new Uri(uriString);
242 return new NodeId(uri);
245 public static Node createNode(ConnectionInfo key) {
246 return new NodeBuilder()
247 .setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()))
248 .addAugmentation(createOvsdbAugmentation(key))
252 public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
253 return new OvsdbNodeAugmentationBuilder().setConnectionInfo(key).build();
256 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
257 return InstanceIdentifier
258 .create(NetworkTopology.class)
259 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
260 .child(Node.class,new NodeKey(nodeId));
263 public static InstanceIdentifier<Node> createInstanceIdentifier(NodeKey ovsdbNodeKey, String bridgeName) {
264 return createInstanceIdentifier(createManagedNodeId(ovsdbNodeKey.getNodeId(), bridgeName));
267 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
268 return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
271 public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
272 InstanceIdentifier<Node> path = InstanceIdentifier
273 .create(NetworkTopology.class)
274 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
275 .child(Node.class,createNodeKey(ip,port));
276 LOG.debug("Created ovsdb path: {}",path);
280 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, OvsdbBridgeName bridgeName) {
281 return createInstanceIdentifier(createManagedNodeId(key, bridgeName));
284 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key, String bridgeName) {
285 return createInstanceIdentifier(key, new OvsdbBridgeName(bridgeName));
288 public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName) {
290 InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
291 .create(NetworkTopology.class)
292 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
293 .child(Node.class,node.key())
294 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
296 LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
297 return terminationPointPath;
300 public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
301 return new NodeKey(createNodeId(ip, port));
304 public static NodeId createManagedNodeId(NodeId ovsdbNodeId, String bridgeName) {
305 return new NodeId(ovsdbNodeId.getValue()
306 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName);
309 public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
310 return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
313 public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
314 return new NodeId(createNodeId(ip,port).getValue()
315 + "/" + BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
318 public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
319 NodeKey nodeKey = iid.firstKeyOf(Node.class);
320 return nodeKey.getNodeId();
323 public OvsdbNodeAugmentation extractOvsdbNode(Node node) {
324 return node.augmentation(OvsdbNodeAugmentation.class);
327 public static IpAddress createIpAddress(InetAddress address) {
329 if (address instanceof Inet4Address) {
330 ip = createIpAddress((Inet4Address)address);
331 } else if (address instanceof Inet6Address) {
332 ip = createIpAddress((Inet6Address)address);
337 public static IpAddress createIpAddress(Inet4Address address) {
338 return IetfInetUtil.INSTANCE.ipAddressFor(address);
341 public static IpAddress createIpAddress(Inet6Address address) {
342 Ipv6Address ipv6 = new Ipv6Address(address.getHostAddress());
343 return new IpAddress(ipv6);
346 public ConnectionInfo getConnectionInfo(Node ovsdbNode) {
347 ConnectionInfo connectionInfo = null;
348 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(ovsdbNode);
349 if (ovsdbNodeAugmentation != null) {
350 connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
352 return connectionInfo;
355 public static ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
356 InetAddress inetAddress = null;
358 inetAddress = InetAddress.getByName(addressStr);
359 } catch (UnknownHostException e) {
360 LOG.warn("Could not allocate InetAddress", e);
363 IpAddress address = createIpAddress(inetAddress);
364 PortNumber port = new PortNumber(Uint16.valueOf(portStr));
366 LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
367 .setRemoteIp(address)
370 return new ConnectionInfoBuilder()
371 .setRemoteIp(address)
376 public static String connectionInfoToString(final ConnectionInfo connectionInfo) {
377 return connectionInfo.getRemoteIp().stringValue() + ":" + connectionInfo.getRemotePort().getValue();
380 public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
381 return addOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
384 public boolean addOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
385 boolean result = provider.put(LogicalDatastoreType.CONFIGURATION,
386 createInstanceIdentifier(connectionInfo),
387 createNode(connectionInfo));
390 Thread.sleep(timeout);
391 } catch (InterruptedException e) {
392 LOG.warn("Interrupted while waiting after adding OVSDB node {}",
393 connectionInfoToString(connectionInfo), e);
399 public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
400 return provider.read(LogicalDatastoreType.OPERATIONAL,
401 createInstanceIdentifier(connectionInfo));
404 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
405 return deleteOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
408 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
409 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
410 createInstanceIdentifier(connectionInfo));
413 Thread.sleep(timeout);
414 } catch (InterruptedException e) {
415 LOG.warn("Interrupted while waiting after deleting OVSDB node {}",
416 connectionInfoToString(connectionInfo), e);
422 public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
423 return connectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
426 public Node connectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
427 addOvsdbNode(connectionInfo, timeout);
428 Node node = getOvsdbNode(connectionInfo);
429 LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
433 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
434 return disconnectOvsdbNode(connectionInfo, OVSDB_UPDATE_TIMEOUT);
437 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo, long timeout) {
438 deleteOvsdbNode(connectionInfo, timeout);
439 LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
443 public List<ControllerEntry> createControllerEntry(String controllerTarget) {
444 List<ControllerEntry> controllerEntriesList = new ArrayList<>();
445 controllerEntriesList.add(new ControllerEntryBuilder()
446 .setTarget(new Uri(controllerTarget))
448 return controllerEntriesList;
452 * Extract the <code>store</code> type data store contents for the particular bridge identified by
453 * <code>bridgeName</code>.
455 * @param connectionInfo address for the node
456 * @param bridgeName name of the bridge
457 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
458 * @return <code>store</code> type data store contents
460 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
461 LogicalDatastoreType store) {
462 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
463 Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
464 if (bridgeNode != null) {
465 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
467 return ovsdbBridgeAugmentation;
471 * Extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
472 * identified by <code>bridgeName</code>.
474 * @param connectionInfo address for the node
475 * @param bridgeName name of the bridge
476 * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
477 * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
479 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
480 return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
484 * Extract the node contents from <code>store</code> type data store for the
485 * bridge identified by <code>bridgeName</code>.
487 * @param connectionInfo address for the node
488 * @param bridgeName name of the bridge
489 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
490 * @return <code>store</code> type data store contents
492 public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
493 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
494 return provider.read(store, bridgeIid);
497 public Node getBridgeNode(Node node, String bridgeName) {
498 OvsdbBridgeAugmentation bridge = extractBridgeAugmentation(node);
499 if (bridge != null && bridge.getBridgeName().getValue().equals(bridgeName)) {
502 return readBridgeNode(node, bridgeName);
506 public Node readBridgeNode(Node node, String name) {
507 Node ovsdbNode = node;
508 if (extractNodeAugmentation(ovsdbNode) == null) {
509 ovsdbNode = readOvsdbNode(node);
510 if (ovsdbNode == null) {
514 Node bridgeNode = null;
515 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
516 if (connectionInfo != null) {
517 InstanceIdentifier<Node> bridgeIid =
518 createInstanceIdentifier(node.key(), name);
519 bridgeNode = provider.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
524 public OvsdbNodeAugmentation extractNodeAugmentation(Node node) {
525 return node.augmentation(OvsdbNodeAugmentation.class);
528 public OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
532 return node.augmentation(OvsdbBridgeAugmentation.class);
535 public Node readOvsdbNode(Node bridgeNode) {
536 Node ovsdbNode = null;
537 OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
538 if (bridgeAugmentation != null) {
539 InstanceIdentifier<Node> ovsdbNodeIid =
540 (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
541 ovsdbNode = provider.read(LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
543 LOG.debug("readOvsdbNode: Provided node is not a bridge node : {}",bridgeNode);
548 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
549 return deleteBridge(connectionInfo, bridgeName, OVSDB_UPDATE_TIMEOUT);
552 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName, long timeout) {
553 boolean result = provider.delete(LogicalDatastoreType.CONFIGURATION,
554 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
557 Thread.sleep(timeout);
558 } catch (InterruptedException e) {
559 LOG.warn("Interrupted while waiting after deleting bridge {}", bridgeName, e);
565 public Map<ProtocolEntryKey, ProtocolEntry> createMdsalProtocols() {
566 final ProtocolEntry entry = new ProtocolEntryBuilder()
567 .setProtocol(OVSDB_PROTOCOL_MAP.inverse().get("OpenFlow13"))
569 return Map.of(entry.key(), entry);
573 * base method for adding test bridges. Other helper methods used to create bridges should utilize this method.
575 * @param connectionInfo
576 * @param bridgeIid if passed null, one is created
577 * @param bridgeName cannot be null
578 * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
579 * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
580 * @param failMode toggles whether default fail mode is set for the bridge
581 * @param setManagedBy toggles whether to setManagedBy for the bridge
582 * @param dpType if passed null, this parameter is ignored
583 * @param externalIds if passed null, this parameter is ignored
584 * @param otherConfig if passed null, this parameter is ignored
585 * @return success of bridge addition
586 * @throws InterruptedException
588 public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
589 final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
590 final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
591 final Class<? extends DatapathTypeBase> dpType,
592 final Map<BridgeExternalIdsKey, BridgeExternalIds> externalIds,
593 final Map<ControllerEntryKey, ControllerEntry> controllerEntries,
594 final Map<BridgeOtherConfigsKey, BridgeOtherConfigs> otherConfigs,
595 final String dpid, long timeout) throws InterruptedException {
597 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
598 if (bridgeIid == null) {
599 bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
601 if (bridgeNodeId == null) {
602 bridgeNodeId = createManagedNodeId(bridgeIid);
604 bridgeNodeBuilder.setNodeId(bridgeNodeId);
605 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
606 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
607 if (setProtocolEntries) {
608 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
610 if (failMode != null) {
611 ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
614 setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
616 if (dpType != null) {
617 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
619 if (externalIds != null) {
620 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
622 if (controllerEntries != null) {
623 ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
625 if (otherConfigs != null) {
626 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
628 if (dpid != null && !dpid.isEmpty()) {
629 DatapathId datapathId = new DatapathId(dpid);
630 ovsdbBridgeAugmentationBuilder.setDatapathId(datapathId);
632 bridgeNodeBuilder.addAugmentation(ovsdbBridgeAugmentationBuilder.build());
633 LOG.debug("Built with the intent to store bridge data {}",
634 ovsdbBridgeAugmentationBuilder.toString());
635 boolean result = provider.merge(LogicalDatastoreType.CONFIGURATION,
636 bridgeIid, bridgeNodeBuilder.build());
638 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
643 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
644 final Class<? extends DatapathTypeBase> dpType, String mac) {
645 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, mac, null, null);
648 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
649 final Class<? extends DatapathTypeBase> dpType, String mac,
650 Long maxBackoff, Long inactivityProbe) {
651 List<BridgeOtherConfigs> otherConfigs = new ArrayList<>();
653 otherConfigs.add(new BridgeOtherConfigsBuilder()
654 .setBridgeOtherConfigKey("hwaddr")
655 .setBridgeOtherConfigValue(mac).build());
658 return addBridge(ovsdbNode, bridgeName, controllersStr, dpType, otherConfigs, null, null);
661 public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
662 final Class<? extends DatapathTypeBase> dpType, List<BridgeOtherConfigs> otherConfigs,
663 Uint32 maxBackoff, Uint32 inactivityProbe) {
664 LOG.info("addBridge: node: {}, bridgeName: {}, controller(s): {}", ovsdbNode, bridgeName, controllersStr);
665 ConnectionInfo connectionInfo = getConnectionInfo(ovsdbNode);
666 if (connectionInfo == null) {
667 throw new InvalidParameterException("Could not find ConnectionInfo");
670 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder()
671 .setControllerEntry(createControllerEntries(controllersStr, maxBackoff, inactivityProbe))
672 .setBridgeName(new OvsdbBridgeName(bridgeName))
673 .setProtocolEntry(createMdsalProtocols())
674 .setFailMode(OVSDB_FAIL_MODE_MAP.inverse().get("secure"))
675 .setBridgeExternalIds(setBridgeExternalIds())
676 .setManagedBy(new OvsdbNodeRef(createInstanceIdentifier(ovsdbNode.key().getNodeId())))
677 // TODO: Currently netvirt relies on this function to set disabled-in-band=true. However,
678 // TODO (cont): a better design would be to have netvirt pass that in. That way this function
679 // TODO (cont): can take a null otherConfigs to erase other_configs.
680 .setBridgeOtherConfigs(disableInBand(otherConfigs));
683 if (dpType != null) {
684 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
686 if (isOvsdbNodeDpdk(ovsdbNode)) {
687 ovsdbBridgeAugmentationBuilder.setDatapathType(DatapathTypeNetdev.class);
690 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
691 Node node = new NodeBuilder()
692 .addAugmentation(ovsdbBridgeAugmentationBuilder.build())
693 .setNodeId(createManagedNodeId(bridgeIid))
695 boolean result = provider.put(LogicalDatastoreType.CONFIGURATION, bridgeIid, node);
696 LOG.info("addBridge: result: {}", result);
700 private static Map<BridgeOtherConfigsKey, BridgeOtherConfigs> disableInBand(List<BridgeOtherConfigs> otherConfigs) {
701 return otherConfigs == null || otherConfigs.isEmpty() ? DEFAULT_OTHER_CONFIGS
702 : BindingMap.<BridgeOtherConfigsKey, BridgeOtherConfigs>orderedBuilder(otherConfigs.size() + 1)
703 .addAll(otherConfigs)
704 .add(OTHER_CONFIG_DISABLE_INBAND)
709 * Set the controllers of an existing bridge node.
711 * @param ovsdbNode where the bridge is
712 * @param bridgeName Name of the bridge
713 * @param controllers controller strings
714 * @return success if the write to md-sal was successful
716 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers) {
717 return setBridgeController(ovsdbNode, bridgeName, controllers, null, null);
721 * Set the controllers of an existing bridge node.
723 * @param ovsdbNode where the bridge is
724 * @param bridgeName Name of the bridge
725 * @param controllers controller strings
726 * @param maxBackoff Max backoff in milliseconds
727 * @param inactivityProbe inactivity probe in milliseconds
728 * @return success if the write to md-sal was successful
730 public boolean setBridgeController(Node ovsdbNode, String bridgeName, List<String> controllers,
731 Uint32 maxBackoff, Uint32 inactivityProbe) {
732 LOG.debug("setBridgeController: ovsdbNode: {}, bridgeNode: {}, controller(s): {}",
733 ovsdbNode, bridgeName, controllers);
735 InstanceIdentifier<Node> bridgeNodeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
736 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid);
737 if (bridgeNode == null) {
738 LOG.info("setBridgeController could not find bridge in configuration {}", bridgeNodeIid);
742 OvsdbBridgeAugmentation bridgeAug = extractBridgeAugmentation(bridgeNode);
744 Map<ControllerEntryKey, ControllerEntry> currentControllerEntries =
745 createControllerEntries(controllers, maxBackoff, inactivityProbe);
747 final Map<ControllerEntryKey, ControllerEntry> newControllerEntries;
748 // Only add controller entries that do not already exist on this bridge
749 Map<ControllerEntryKey, ControllerEntry> existingControllerEntries = bridgeAug.getControllerEntry();
750 if (existingControllerEntries != null) {
751 newControllerEntries = currentControllerEntries.values().stream()
752 .filter(entry -> !existingControllerEntries.containsKey(new ControllerEntryKey(entry.getTarget())))
753 .collect(BindingMap.toOrderedMap());
755 newControllerEntries = currentControllerEntries;
758 if (newControllerEntries.isEmpty()) {
762 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(ovsdbNode.key(), bridgeName);
763 return provider.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, new NodeBuilder(bridgeNode)
764 .addAugmentation(new OvsdbBridgeAugmentationBuilder(bridgeAug)
765 .setControllerEntry(newControllerEntries)
770 private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
771 final ConnectionInfo connectionInfo) {
772 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
773 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
776 public boolean addTerminationPoint(
777 Node bridgeNode, String portName, String type, Map<String, String> options,
778 Map<String, String> externalIds) {
779 return addTerminationPoint(bridgeNode, portName, type, options, externalIds, null);
782 public boolean addTerminationPoint(
783 Node bridgeNode, String portName, String type, Map<String, String> options, Map<String, String> externalIds,
785 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
787 tpAugmentationBuilder.setName(portName);
788 tpAugmentationBuilder.setOfport(ofPort);
790 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
793 if (options != null && options.size() > 0) {
794 tpAugmentationBuilder.setOptions(buildOptions(options));
797 if (externalIds != null && externalIds.size() > 0) {
798 final ImmutableMap.Builder<InterfaceExternalIdsKey, InterfaceExternalIds> builder =
799 ImmutableMap.builderWithExpectedSize(externalIds.size());
800 for (Map.Entry<String, String> entry : externalIds.entrySet()) {
801 final InterfaceExternalIdsKey key = new InterfaceExternalIdsKey(entry.getKey());
802 builder.put(key, new InterfaceExternalIdsBuilder()
804 .setExternalIdValue(entry.getValue())
807 tpAugmentationBuilder.setInterfaceExternalIds(builder.build());
810 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
811 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, new TerminationPointBuilder()
812 .withKey(InstanceIdentifier.keyOf(tpIid))
813 .addAugmentation(tpAugmentationBuilder.build())
817 public Boolean addTerminationPoint(Node bridgeNode, String portName, String type) {
818 return addTerminationPoint(bridgeNode, portName, type, Collections.emptyMap(), null);
821 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
822 String type, Map<String, String> options) {
823 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
825 tpAugmentationBuilder.setName(portName);
827 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
830 tpAugmentationBuilder.setOptions(buildOptions(options));
832 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
833 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, new TerminationPointBuilder()
834 .withKey(InstanceIdentifier.keyOf(tpIid))
835 .addAugmentation(tpAugmentationBuilder.build())
839 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
840 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
841 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
842 new OvsdbTerminationPointAugmentationBuilder();
844 tpAugmentationBuilder.setName(portName);
846 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
848 return provider.merge(LogicalDatastoreType.CONFIGURATION, tpIid, new TerminationPointBuilder()
849 .withKey(InstanceIdentifier.keyOf(tpIid))
850 .addAugmentation(tpAugmentationBuilder.build())
854 public Boolean addPatchTerminationPoint(Node node, String bridgeName, String portName, String peerPortName) {
855 Map<String, String> option = new HashMap<>();
856 option.put("peer", peerPortName);
857 return addTerminationPoint(node, bridgeName, portName, PATCH_PORT_TYPE, option);
860 private String getControllerIPAddress() {
861 String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
862 if (addressString != null) {
864 if (InetAddress.getByName(addressString) != null) {
865 return addressString;
867 } catch (UnknownHostException e) {
868 LOG.error("Host {} is invalid", addressString, e);
872 addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
873 if (addressString != null) {
875 if (InetAddress.getByName(addressString) != null) {
876 return addressString;
878 } catch (UnknownHostException e) {
879 LOG.error("Host {} is invalid", addressString, e);
886 private short getControllerOFPort() {
887 short openFlowPort = OPENFLOW_PORT;
888 String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
889 if (portString != null) {
891 openFlowPort = Short.parseShort(portString);
892 } catch (NumberFormatException e) {
893 LOG.warn("Invalid port:{}, use default({})", portString,
900 public List<String> getControllersFromOvsdbNode(Node node) {
901 List<String> controllersStr = new ArrayList<>();
903 String controllerIpStr = getControllerIPAddress();
904 if (controllerIpStr != null) {
905 // If codepath makes it here, the ip address to be used was explicitly provided.
906 // Being so, also fetch openflowPort provided via ConfigProperties.
907 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
908 + ":" + controllerIpStr + ":" + getControllerOFPort());
910 // Check if ovsdb node has manager entries
911 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(node);
912 if (ovsdbNodeAugmentation != null) {
913 Map<ManagerEntryKey, ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
914 if (managerEntries != null && !managerEntries.isEmpty()) {
915 for (ManagerEntry managerEntry : managerEntries.values()) {
916 if (managerEntry == null || managerEntry.getTarget() == null) {
919 String managerStr = managerEntry.getTarget().getValue().toLowerCase(Locale.ROOT);
920 int firstColonIdx = managerStr.indexOf(':');
921 int lastColonIdx = managerStr.lastIndexOf(':');
922 if (lastColonIdx <= firstColonIdx) {
925 controllerIpStr = managerStr.substring(firstColonIdx + 1, lastColonIdx);
926 if (managerStr.startsWith("tcp")) {
927 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL + ":" + controllerIpStr + ":"
928 + getControllerOFPort());
929 } else if (managerStr.startsWith("ssl")) {
930 controllersStr.add(OPENFLOW_SECURE_PROTOCOL + ":" + controllerIpStr + ":"
931 + getControllerOFPort());
932 } else if (managerStr.startsWith("ptcp")) {
933 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
934 /* If we're connected to switch ptcp, only then use connection info
935 to configure controller. Ptcp is configured as:
936 Manager "ptcp:<port>:<ip>"
939 String managerPortStr = managerStr.split(":", 3)[1];
940 if (connectionInfo != null && connectionInfo.getLocalIp() != null
941 && connectionInfo.getRemotePort() != null
942 && managerPortStr.equals(connectionInfo.getRemotePort().toString())) {
943 IpAddress controllerIp = connectionInfo.getLocalIp();
944 if (controllerIp.getIpv6Address() != null) {
945 controllerIpStr = "[" + connectionInfo.getLocalIp().stringValue() + "]";
947 controllerIpStr = connectionInfo.getLocalIp().stringValue();
949 controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
950 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
952 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
954 } else if (managerStr.startsWith("pssl")) {
955 ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
956 if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
957 controllerIpStr = connectionInfo.getLocalIp().stringValue();
958 controllersStr.add(OPENFLOW_SECURE_PROTOCOL
959 + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
961 LOG.warn("Ovsdb Node does not contain connection info: {}", node);
964 LOG.trace("Skipping manager entry {} for node {}",
965 managerEntry.getTarget(), node.getNodeId().getValue());
969 LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
974 if (controllersStr.isEmpty()) {
975 LOG.warn("Failed to determine OpenFlow controller ip address");
976 } else if (LOG.isDebugEnabled()) {
977 LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(),
978 controllersStr.stream().collect(Collectors.joining(" ")));
980 return controllersStr;
983 public long getDataPathId(Node node) {
985 String datapathId = getDatapathId(node);
986 if (datapathId != null) {
987 dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
992 public String getDataPathIdStr(final Node node) {
994 long dpId = getDataPathId(node);
996 return String.valueOf(dpId);
1003 public String getDatapathId(Node node) {
1004 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.augmentation(OvsdbBridgeAugmentation.class);
1005 return getDatapathId(ovsdbBridgeAugmentation);
1008 public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
1009 String datapathId = null;
1010 if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
1011 datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
1016 public String extractBridgeName(Node node) {
1017 return node.augmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
1020 public boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgeName) {
1021 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1022 if (ovsdbNodeAugmentation != null) {
1023 Map<ManagedNodeEntryKey, ManagedNodeEntry> managedNodes = ovsdbNodeAugmentation.getManagedNodeEntry();
1024 if (managedNodes != null) {
1025 for (ManagedNodeEntry managedNode : managedNodes.values()) {
1026 if (matchesBridgeName(managedNode, bridgeName)) {
1035 // see OVSDB-470 for background
1036 private static boolean matchesBridgeName(ManagedNodeEntry managedNode, String bridgeName) {
1037 InstanceIdentifier<?> bridgeIid = managedNode.getBridgeRef().getValue();
1038 for (PathArgument bridgeIidPathArg : bridgeIid.getPathArguments()) {
1039 if (bridgeIidPathArg instanceof IdentifiableItem<?, ?>) {
1040 IdentifiableItem<?, ?> identifiableItem = (IdentifiableItem<?, ?>) bridgeIidPathArg;
1041 Identifier<?> key = identifiableItem.getKey();
1042 if (key instanceof NodeKey) {
1043 // Do not combine the above if with that below, we want to
1044 // avoid the toString() call in the else if this is a NodeKey
1045 NodeKey nodeKey = (NodeKey) key;
1046 if (nodeKey.getNodeId().getValue().contains(bridgeName)) {
1049 } else if (key.toString().contains(bridgeName)) {
1052 } else if (bridgeIidPathArg instanceof Item<?>) {
1053 if (((Item<?>) bridgeIidPathArg).getType().getName().contains(bridgeName)) {
1057 throw new IllegalArgumentException("Unknown kind of PathArgument: " + bridgeIidPathArg);
1063 public OvsdbBridgeAugmentation getBridgeFromConfig(Node node, String bridge) {
1064 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
1065 InstanceIdentifier<Node> bridgeIid =
1066 createInstanceIdentifier(node.key(), bridge);
1067 Node bridgeNode = provider.read(LogicalDatastoreType.CONFIGURATION, bridgeIid);
1068 if (bridgeNode != null) {
1069 ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
1071 return ovsdbBridgeAugmentation;
1074 public boolean isOvsdbNodeDpdk(Node ovsdbNode) {
1075 OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
1076 if (ovsdbNodeAugmentation != null) {
1077 Map<InterfaceTypeEntryKey, InterfaceTypeEntry> ifTypes = ovsdbNodeAugmentation.getInterfaceTypeEntry();
1078 if (ifTypes != null) {
1079 if (ifTypes.containsKey(DPDK_IFACE_KEY)) {
1087 private static Map<ControllerEntryKey, ControllerEntry> createControllerEntries(List<String> controllersStr,
1088 Uint32 maxBackoff, Uint32 inactivityProbe) {
1089 if (controllersStr == null) {
1093 BindingMap.Builder<ControllerEntryKey, ControllerEntry> controllerEntries =
1094 BindingMap.orderedBuilder(controllersStr.size());
1095 for (String controllerStr : controllersStr) {
1096 controllerEntries.add(new ControllerEntryBuilder()
1097 .setTarget(new Uri(controllerStr))
1098 .setMaxBackoff(maxBackoff)
1099 .setInactivityProbe(inactivityProbe)
1102 return controllerEntries.build();
1105 public OvsdbTerminationPointAugmentation extractTerminationPointAugmentation(Node bridgeNode, String portName) {
1106 if (bridgeNode.augmentation(OvsdbBridgeAugmentation.class) != null) {
1107 List<OvsdbTerminationPointAugmentation> tpAugmentations = extractTerminationPointAugmentations(bridgeNode);
1108 for (OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation : tpAugmentations) {
1109 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1110 return ovsdbTerminationPointAugmentation;
1117 public List<OvsdbTerminationPointAugmentation> extractTerminationPointAugmentations(Node node) {
1118 List<OvsdbTerminationPointAugmentation> tpAugmentations = new ArrayList<>();
1120 LOG.error("extractTerminationPointAugmentations: Node value is null");
1121 return Collections.emptyList();
1123 Map<TerminationPointKey, TerminationPoint> terminationPoints = node.getTerminationPoint();
1124 if (terminationPoints != null && !terminationPoints.isEmpty()) {
1125 for (TerminationPoint tp : terminationPoints.values()) {
1126 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1127 tp.augmentation(OvsdbTerminationPointAugmentation.class);
1128 if (ovsdbTerminationPointAugmentation != null) {
1129 tpAugmentations.add(ovsdbTerminationPointAugmentation);
1133 return tpAugmentations;
1137 * Extract the <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code> identified by
1138 * <code>portName</code>.
1140 public OvsdbTerminationPointAugmentation getTerminationPointOfBridge(Node node, String portName) {
1141 OvsdbTerminationPointAugmentation tpAugmentation = extractTerminationPointAugmentation(node,portName);
1142 if (tpAugmentation == null) {
1143 List<OvsdbTerminationPointAugmentation> tpAugmentations = readTerminationPointAugmentations(node);
1144 if (tpAugmentations != null) {
1145 for (OvsdbTerminationPointAugmentation ovsdbTpAugmentation : tpAugmentations) {
1146 if (ovsdbTpAugmentation.getName().equals(portName)) {
1147 return ovsdbTpAugmentation;
1152 return tpAugmentation;
1156 * Read the list of <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code>.
1158 public List<OvsdbTerminationPointAugmentation> readTerminationPointAugmentations(Node node) {
1160 LOG.error("readTerminationPointAugmentations: Node value is null");
1161 return Collections.emptyList();
1163 Node operNode = provider.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier
1164 .create(NetworkTopology.class)
1165 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
1166 .child(Node.class, new NodeKey(node.getNodeId())));
1167 if (operNode != null) {
1168 return extractTerminationPointAugmentations(operNode);
1170 return new ArrayList<>();
1174 * Get all OVSDB nodes from topology.
1175 * @return a list of nodes or null if the topology could not found
1177 public Map<NodeKey, Node> getOvsdbNodes() {
1178 InstanceIdentifier<Topology> inst = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
1179 new TopologyKey(OVSDB_TOPOLOGY_ID));
1180 Topology topology = provider.read(LogicalDatastoreType.OPERATIONAL, inst);
1181 return topology != null ? topology.getNode() : null;
1185 * Get OpenvSwitch other-config by key.
1186 * @param node OVSDB node
1187 * @param key key to extract from other-config
1188 * @return the value for key or null if key not found
1190 public String getOpenvswitchOtherConfig(Node node, String key) {
1191 OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
1192 if (ovsdbNode == null) {
1193 Node nodeFromReadOvsdbNode = readOvsdbNode(node);
1194 if (nodeFromReadOvsdbNode != null) {
1195 ovsdbNode = nodeFromReadOvsdbNode.augmentation(OvsdbNodeAugmentation.class);
1199 if (ovsdbNode != null) {
1200 final OpenvswitchOtherConfigs found = ovsdbNode.nonnullOpenvswitchOtherConfigs()
1201 .get(new OpenvswitchOtherConfigsKey(key));
1202 if (found != null) {
1203 return found.getOtherConfigValue();
1210 public static TerminationPoint getTerminationPointByExternalId(final Node bridgeNode, final String interfaceName) {
1211 final Map<TerminationPointKey, TerminationPoint> tps = bridgeNode.getTerminationPoint();
1213 for (TerminationPoint tp : tps.values()) {
1214 OvsdbTerminationPointAugmentation ovsdbTp = tp.augmentation(OvsdbTerminationPointAugmentation.class);
1215 String externalIdValue = getExternalInterfaceIdValue(ovsdbTp);
1216 if (externalIdValue != null && externalIdValue.equals(interfaceName)) {
1217 LOG.debug("Found matching termination point with iface-id {} on bridgeNode {}, returning tp {}",
1218 interfaceName, bridgeNode, tp);
1226 // This utility shouldn't be called often, as it reads all OVSDB nodes each time - not good for scale
1227 public Node getNodeByTerminationPointExternalId(final String interfaceName) {
1228 Map<NodeKey, Node> nodes = getOvsdbNodes();
1229 if (nodes != null) {
1230 for (Node node : nodes.values()) {
1231 TerminationPoint tp = getTerminationPointByExternalId(node, interfaceName);
1240 public static String getExternalInterfaceIdValue(final OvsdbTerminationPointAugmentation ovsdbTp) {
1241 if (ovsdbTp != null) {
1242 Map<InterfaceExternalIdsKey, InterfaceExternalIds> ifaceExtIds = ovsdbTp.getInterfaceExternalIds();
1243 if (ifaceExtIds != null) {
1244 final InterfaceExternalIds entry = ifaceExtIds.get(EXTERNAL_INTERFACE_ID_KEY);
1245 if (entry != null) {
1246 return entry.getExternalIdValue();
1253 public String getDatapathIdFromNodeInstanceId(InstanceIdentifier<Node> nodeInstanceId) {
1254 Node node = provider.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
1255 String dpId = node != null ? getDataPathIdStr(node) : null;
1262 public static boolean compareDbVersionToMinVersion(final String dbVersion, final String minVersion) {
1263 if (dbVersion == null || minVersion == null) {
1264 LOG.error("Invalid DB version {} or minVersion {}", dbVersion, minVersion);
1267 final Matcher dbVersionMatcher = PATTERN.matcher(dbVersion);
1268 final Matcher minVersionMatcher = PATTERN.matcher(minVersion);
1269 LOG.debug("dbVersion {}, minVersion {}", dbVersion, minVersion);
1270 if (!dbVersionMatcher.find()) {
1271 LOG.error("Invalid DB version format {}", dbVersion);
1274 if (!minVersionMatcher.find()) {
1275 LOG.error("Invalid Min DB version format {}", minVersion);
1279 if (dbVersion != null && !dbVersion.isEmpty() && minVersion != null && !minVersion.isEmpty()) {
1280 final int dbVersionMatch1 = Integer.parseInt(dbVersionMatcher.group(1));
1281 final int dbVersionMatch2 = Integer.parseInt(dbVersionMatcher.group(2));
1282 final int dbVersionMatch3 = Integer.parseInt(dbVersionMatcher.group(3));
1283 final int minVersionMatch1 = Integer.parseInt(minVersionMatcher.group(1));
1284 final int minVersionMatch2 = Integer.parseInt(minVersionMatcher.group(2));
1285 final int minVersionMatch3 = Integer.parseInt(minVersionMatcher.group(3));
1286 if (dbVersionMatch1 == minVersionMatch1 && dbVersionMatch2 == minVersionMatch2
1287 && dbVersionMatch3 == minVersionMatch3) {
1291 if (dbVersionMatch1 > minVersionMatch1) {
1295 if (dbVersionMatch1 < minVersionMatch1) {
1299 // major version is equal
1300 if (dbVersionMatch2 > minVersionMatch2) {
1304 if (dbVersionMatch2 < minVersionMatch2) {
1308 if (dbVersionMatch3 > minVersionMatch3) {
1315 private static Map<BridgeExternalIdsKey, BridgeExternalIds> setBridgeExternalIds() {
1316 final BridgeExternalIds ids = new BridgeExternalIdsBuilder()
1317 .setBridgeExternalIdKey(CREATED_BY)
1318 .setBridgeExternalIdValue(ODL)
1320 return Map.of(ids.key(), ids);
1323 private static Map<OptionsKey, Options> buildOptions(final Map<String, String> options) {
1324 final ImmutableMap.Builder<OptionsKey, Options> builder = ImmutableMap.builderWithExpectedSize(options.size());
1325 for (Map.Entry<String, String> entry : options.entrySet()) {
1326 final OptionsKey key = new OptionsKey(entry.getKey());
1327 builder.put(key, new OptionsBuilder().withKey(key).setValue(entry.getValue()).build());
1329 return builder.build();