2 * Copyright (c) 2015 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 com.google.common.collect.ImmutableBiMap;
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.ArrayList;
16 import java.util.List;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
20 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
21 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
56 public class SouthboundUtils {
57 private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
58 private static final int OVSDB_UPDATE_TIMEOUT = 1000;
59 private static final String DEFAULT_OPENFLOW_PORT = "6653";
60 private static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
61 private MdsalUtils mdsalUtils;
62 public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
64 public SouthboundUtils(MdsalUtils mdsalUtils) {
65 this.mdsalUtils = mdsalUtils;
68 public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
69 = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
70 .put("internal", InterfaceTypeInternal.class)
71 .put("vxlan", InterfaceTypeVxlan.class)
72 .put("patch", InterfaceTypePatch.class)
73 .put("system", InterfaceTypeSystem.class)
74 .put("tap", InterfaceTypeTap.class)
75 .put("geneve", InterfaceTypeGeneve.class)
76 .put("gre", InterfaceTypeGre.class)
77 .put("ipsec_gre", InterfaceTypeIpsecGre.class)
78 .put("gre64", InterfaceTypeGre64.class)
79 .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
80 .put("lisp", InterfaceTypeLisp.class)
81 .put("dpdk", InterfaceTypeDpdk.class)
82 .put("dpdkr", InterfaceTypeDpdkr.class)
83 .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
84 .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class)
87 public static NodeId createNodeId(IpAddress ip, PortNumber port) {
88 String uriString = SouthboundConstants.OVSDB_URI_PREFIX + "://"
89 + String.valueOf(ip.getValue()) + ":" + port.getValue();
90 Uri uri = new Uri(uriString);
91 return new NodeId(uri);
94 public static Node createNode(ConnectionInfo key) {
95 NodeBuilder nodeBuilder = new NodeBuilder();
96 nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(), key.getRemotePort()));
97 nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
98 return nodeBuilder.build();
101 public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
102 OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
103 ovsdbNodeBuilder.setConnectionInfo(key);
104 return ovsdbNodeBuilder.build();
107 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key) {
108 return createInstanceIdentifier(key.getRemoteIp(), key.getRemotePort());
111 public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
112 InstanceIdentifier<Node> path = InstanceIdentifier
113 .create(NetworkTopology.class)
114 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
115 .child(Node.class,createNodeKey(ip,port));
116 LOG.debug("Created ovsdb path: {}",path);
120 public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key,OvsdbBridgeName bridgeName) {
121 return SouthboundMapper.createInstanceIdentifier(createManagedNodeId(key, bridgeName));
124 public InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(Node node, String portName){
126 InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
127 .create(NetworkTopology.class)
128 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
129 .child(Node.class,node.getKey())
130 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
132 LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
133 return terminationPointPath;
136 public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
137 return new NodeKey(createNodeId(ip, port));
140 public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
141 return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
144 public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
145 return new NodeId(createNodeId(ip,port).getValue()
146 + "/" + SouthboundConstants.BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
149 public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
150 NodeKey nodeKey = iid.firstKeyOf(Node.class, NodeKey.class);
151 return nodeKey.getNodeId();
154 public static ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
155 InetAddress inetAddress = null;
157 inetAddress = InetAddress.getByName(addressStr);
158 } catch (UnknownHostException e) {
159 LOG.warn("Could not allocate InetAddress");
162 IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
163 PortNumber port = new PortNumber(Integer.parseInt(portStr));
165 LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
166 .setRemoteIp(address)
169 return new ConnectionInfoBuilder()
170 .setRemoteIp(address)
175 public static String connectionInfoToString(final ConnectionInfo connectionInfo) {
176 return String.valueOf(
177 connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
180 public boolean addOvsdbNode(final ConnectionInfo connectionInfo) {
181 boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
182 createInstanceIdentifier(connectionInfo),
183 createNode(connectionInfo));
185 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
186 } catch (InterruptedException e) {
187 LOG.warn("Interrupted while waiting after adding OVSDB node {}", connectionInfoToString(connectionInfo), e);
192 public Node getOvsdbNode(final ConnectionInfo connectionInfo) {
193 return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
194 createInstanceIdentifier(connectionInfo));
197 public boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) {
198 boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
199 createInstanceIdentifier(connectionInfo));
201 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
202 } catch (InterruptedException e) {
203 LOG.warn("Interrupted while waiting after deleting OVSDB node {}", connectionInfoToString(connectionInfo),
209 public Node connectOvsdbNode(final ConnectionInfo connectionInfo) {
210 addOvsdbNode(connectionInfo);
211 Node node = getOvsdbNode(connectionInfo);
212 LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
216 public boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) {
217 deleteOvsdbNode(connectionInfo);
218 LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
222 public List<ControllerEntry> createControllerEntry(String controllerTarget) {
223 List<ControllerEntry> controllerEntriesList = new ArrayList<>();
224 controllerEntriesList.add(new ControllerEntryBuilder()
225 .setTarget(new Uri(controllerTarget))
227 return controllerEntriesList;
231 * Extract the <code>store</code> type data store contents for the particular bridge identified by
232 * <code>bridgeName</code>.
234 * @param connectionInfo address for the node
235 * @param bridgeName name of the bridge
236 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
237 * @return <code>store</code> type data store contents
239 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
240 LogicalDatastoreType store) {
241 OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
242 Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
243 if (bridgeNode != null) {
244 ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
246 return ovsdbBridgeAugmentation;
250 * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
251 * identified by <code>bridgeName</code>
253 * @param connectionInfo address for the node
254 * @param bridgeName name of the bridge
255 * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
256 * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
258 public OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
259 return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
263 * Extract the node contents from <code>store</code> type data store for the
264 * bridge identified by <code>bridgeName</code>.
266 * @param connectionInfo address for the node
267 * @param bridgeName name of the bridge
268 * @param store defined by the <code>LogicalDatastoreType</code> enumeration
269 * @return <code>store</code> type data store contents
271 public Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
272 InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
273 return mdsalUtils.read(store, bridgeIid);
276 public boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
278 boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
279 createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)));
281 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
282 } catch (InterruptedException e) {
283 LOG.warn("Interrupted while waiting after deleting bridge {}", bridgeName, e);
288 public List<ProtocolEntry> createMdsalProtocols() {
289 List<ProtocolEntry> protocolList = new ArrayList<>();
290 ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
291 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
292 protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
297 * base method for adding test bridges. Other helper methods used to create bridges should utilize this method.
299 * @param connectionInfo
300 * @param bridgeIid if passed null, one is created
301 * @param bridgeName cannot be null
302 * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
303 * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
304 * @param failMode toggles whether default fail mode is set for the bridge
305 * @param setManagedBy toggles whether to setManagedBy for the bridge
306 * @param dpType if passed null, this parameter is ignored
307 * @param externalIds if passed null, this parameter is ignored
308 * @param otherConfig if passed null, this parameter is ignored
309 * @return success of bridge addition
310 * @throws InterruptedException
312 public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
313 final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
314 final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
315 final Class<? extends DatapathTypeBase> dpType,
316 final List<BridgeExternalIds> externalIds,
317 final List<ControllerEntry> controllerEntries,
318 final List<BridgeOtherConfigs> otherConfigs,
319 final String dpid) throws InterruptedException {
321 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
322 if (bridgeIid == null) {
323 bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
325 if (bridgeNodeId == null) {
326 bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
328 bridgeNodeBuilder.setNodeId(bridgeNodeId);
329 OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
330 ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
331 if (setProtocolEntries) {
332 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
334 if (failMode != null) {
335 ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
338 setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
340 if (dpType != null) {
341 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
343 if (externalIds != null) {
344 ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
346 if (controllerEntries != null) {
347 ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
349 if (otherConfigs != null) {
350 ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
352 if (dpid != null && !dpid.isEmpty()) {
353 DatapathId datapathId = new DatapathId(dpid);
354 ovsdbBridgeAugmentationBuilder.setDatapathId(datapathId);
356 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
357 LOG.debug("Built with the intent to store bridge data {}",
358 ovsdbBridgeAugmentationBuilder.toString());
359 boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
360 bridgeIid, bridgeNodeBuilder.build());
361 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
365 public boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
366 final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
367 final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
368 final Class<? extends DatapathTypeBase> dpType,
369 final List<BridgeExternalIds> externalIds,
370 final List<ControllerEntry> controllerEntries,
371 final List<BridgeOtherConfigs> otherConfigs) throws InterruptedException {
372 return addBridge(connectionInfo, bridgeIid, bridgeName, bridgeNodeId, setProtocolEntries,
373 failMode, setManagedBy, dpType, externalIds, controllerEntries,
377 public boolean addBridge(final ConnectionInfo connectionInfo, final String bridgeName)
378 throws InterruptedException {
380 return addBridge(connectionInfo, null, bridgeName, null, true,
381 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null);
384 private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
385 final ConnectionInfo connectionInfo) {
386 InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
387 ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
390 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
391 String type, Map<String, String> options,
392 Map<String, String> externalIds) {
393 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
394 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
396 tpAugmentationBuilder.setName(portName);
398 tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
401 if (options != null && options.size() > 0) {
402 List<Options> optionsList = new ArrayList<>();
403 for (Map.Entry<String, String> entry : options.entrySet()) {
404 OptionsBuilder optionsBuilder = new OptionsBuilder();
405 optionsBuilder.setKey(new OptionsKey(entry.getKey()));
406 optionsBuilder.setOption(entry.getKey());
407 optionsBuilder.setValue(entry.getValue());
408 optionsList.add(optionsBuilder.build());
410 tpAugmentationBuilder.setOptions(optionsList);
413 if (externalIds != null && externalIds.size() > 0) {
414 List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
415 for (Map.Entry<String, String> entry : externalIds.entrySet()) {
416 InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
417 interfaceExternalIdsBuilder.setKey(new InterfaceExternalIdsKey(entry.getKey()));
418 interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
419 interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
420 externalIdsList.add(interfaceExternalIdsBuilder.build());
422 tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
425 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
426 tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
427 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
428 /* TODO SB_MIGRATION should this be merge or mdsalUtils.put */
429 return mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
432 public TerminationPoint readTerminationPoint(Node bridgeNode, String bridgeName, String portName) {
433 InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
434 bridgeNode, portName);
435 return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpIid);
438 public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
439 return addTerminationPoint(bridgeNode, bridgeName, portName, type, null, null);
442 public Boolean addTunnelTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type,
443 Map<String, String> options) {
444 return addTerminationPoint(bridgeNode, bridgeName, portName, type, options, null);