From: Ed Warnicke Date: Tue, 14 Apr 2015 05:09:48 +0000 (-0700) Subject: Create the tunnel port in OVSDB, and connect. X-Git-Tag: release/lithium~90 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F37%2F18237%2F10;p=groupbasedpolicy.git Create the tunnel port in OVSDB, and connect. This patch creates a tunnel port for ofoverlay, and optionally connects it to the controller (set by member in the class). Change-Id: Iac2f099cbe3521c8b9d53bf55752264543e4e22d Signed-off-by: Ed Warnicke --- diff --git a/renderers/ofoverlay/pom.xml b/renderers/ofoverlay/pom.xml index ddae38fd3..04f90504f 100644 --- a/renderers/ofoverlay/pom.xml +++ b/renderers/ofoverlay/pom.xml @@ -41,6 +41,16 @@ mockito-all test + + org.opendaylight.ovsdb + southbound-api + ${ovsdb.southbound.version} + + + org.opendaylight.ovsdb + southbound-impl + ${ovsdb.southbound.version} + diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/OFOverlayRenderer.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/OFOverlayRenderer.java index 263778a1d..c169e1f93 100644 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/OFOverlayRenderer.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/OFOverlayRenderer.java @@ -18,6 +18,7 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver; +import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.ovsdb.OfOverlayOvsdbBridgeDataChangeListener; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.DataObject; @@ -44,6 +45,7 @@ public class OFOverlayRenderer implements AutoCloseable, DataChangeListener { private final SwitchManager switchManager; private final EndpointManager endpointManager; private final PolicyManager policyManager; + private final OfOverlayOvsdbBridgeDataChangeListener ovsdbListener; private final ScheduledExecutorService executor; @@ -56,6 +58,7 @@ public class OFOverlayRenderer implements AutoCloseable, DataChangeListener { public OFOverlayRenderer(DataBroker dataProvider, RpcProviderRegistry rpcRegistry) { super(); + ovsdbListener = new OfOverlayOvsdbBridgeDataChangeListener(dataProvider); this.dataBroker = dataProvider; int numCPU = Runtime.getRuntime().availableProcessors(); @@ -95,6 +98,7 @@ public class OFOverlayRenderer implements AutoCloseable, DataChangeListener { if (policyResolver != null) policyResolver.close(); if (switchManager != null) switchManager.close(); if (endpointManager != null) endpointManager.close(); + if (ovsdbListener != null) ovsdbListener.close(); } // ****************** diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/ovsdb/OfOverlayOvsdbBridgeDataChangeListener.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/ovsdb/OfOverlayOvsdbBridgeDataChangeListener.java new file mode 100644 index 000000000..30b107e78 --- /dev/null +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/ovsdb/OfOverlayOvsdbBridgeDataChangeListener.java @@ -0,0 +1,204 @@ +package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.ovsdb; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.ovsdb.southbound.SouthboundConstants; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; + +public class OfOverlayOvsdbBridgeDataChangeListener implements DataChangeListener, AutoCloseable { + + private static final String REMOTE_IP_VALUE = "flow"; + private static final String REMOTE_IP_KEY = "remote_ip"; + private static final String VNID_KEY = "key"; + private static final String VNID_VALUE = "flow"; + private static final String OFOVERLAY_TUNNEL = "ofoverlay-tun"; + private static final String OF_PORT = "6653"; + private static boolean connectController = false; + private ListenerRegistration registration; + private DataBroker db; + private static final Logger LOG = LoggerFactory.getLogger(OfOverlayOvsdbBridgeDataChangeListener.class); + + public OfOverlayOvsdbBridgeDataChangeListener(DataBroker db) { + this.db = db; + InstanceIdentifier iid = InstanceIdentifier + .create(NetworkTopology.class) + .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) + .child(Node.class); + registration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid, this, DataChangeScope.BASE); + } + + @Override + public void close() throws Exception { + registration.close(); + + } + + @Override + public void onDataChanged( + AsyncDataChangeEvent, DataObject> change) { + ReadWriteTransaction transaction = db.newReadWriteTransaction(); + for (Entry, DataObject> entry :change.getCreatedData().entrySet()) { + if(entry.getValue() instanceof Node) { + Node node = (Node)entry.getValue(); + InstanceIdentifier nodeIid = (InstanceIdentifier) entry.getKey(); + OvsdbBridgeAugmentation bridge = node.getAugmentation(OvsdbBridgeAugmentation.class); + if(bridge!= null) { + Optional connectionOptional = getConnection(transaction, bridge); + if(connectionOptional.isPresent()) { + + List options = getOptions(); + + OvsdbTerminationPointAugmentation ovsdbTp = getOvsdbTerminationPointAugmentation(bridge,options); + + List tps = getTerminationPoints(bridge,ovsdbTp); + + OvsdbBridgeAugmentation ovsdbBridgeAugmentation = getOvsdbBridgeAugmentation(bridge,connectionOptional.get()); + + Node configNode = getNode(node, tps,ovsdbBridgeAugmentation); + LOG.info("About to write nodeId {} node {}",nodeIid,configNode); + transaction.merge(LogicalDatastoreType.CONFIGURATION, nodeIid, configNode); + } + } + } + } + transaction.submit(); + } + + private Node getNode(Node node, List tps, + OvsdbBridgeAugmentation ovsdbBridgeAugmentation) { + NodeBuilder nodeBuilder = new NodeBuilder(); + nodeBuilder.setKey(node.getKey()); + + nodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, + ovsdbBridgeAugmentation); + + nodeBuilder.setTerminationPoint(tps); + return nodeBuilder.build(); + } + + private OvsdbBridgeAugmentation getOvsdbBridgeAugmentation(OvsdbBridgeAugmentation bridge, + OvsdbNodeAugmentation connection) { + OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentation = new OvsdbBridgeAugmentationBuilder(); + List controllerEntries = getControllerEntries(connection); + ovsdbBridgeAugmentation.setControllerEntry(controllerEntries); + ovsdbBridgeAugmentation.setBridgeName(bridge.getBridgeName()); + ovsdbBridgeAugmentation.setManagedBy(bridge.getManagedBy()); + return ovsdbBridgeAugmentation.build(); + } + + private List getTerminationPoints(OvsdbBridgeAugmentation bridge, + OvsdbTerminationPointAugmentation ovsdbTp) { + TerminationPointBuilder tpBuilder = new TerminationPointBuilder(); + tpBuilder.setTpId(new TpId(new Uri(generateTpName(bridge)))); + tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, ovsdbTp); + + List tps = new ArrayList(); + tps.add(tpBuilder.build()); + return tps; + } + + private String generateTpName(OvsdbBridgeAugmentation bridge) { + return OFOVERLAY_TUNNEL; + } + + private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation(OvsdbBridgeAugmentation bridge, + List options) { + OvsdbTerminationPointAugmentationBuilder ovsdbTpBuilder = new OvsdbTerminationPointAugmentationBuilder(); + ovsdbTpBuilder.setName(generateTpName(bridge)); + ovsdbTpBuilder.setOptions(options); + ovsdbTpBuilder.setInterfaceType(InterfaceTypeVxlan.class); + return ovsdbTpBuilder.build(); + } + + private void setOption(List options, String key, String value) { + OptionsBuilder option = new OptionsBuilder(); + option.setOption(key); + option.setValue(value); + options.add(option.build()); + } + + private List getOptions() { + List options = new ArrayList(); + setOption(options, REMOTE_IP_KEY, REMOTE_IP_VALUE); + setOption(options, VNID_KEY, VNID_VALUE); + return options; + } + + private List getControllerEntries(OvsdbNodeAugmentation connection) { + ControllerEntryBuilder controllerBuilder = new ControllerEntryBuilder(); + List result = new ArrayList(); + if (connectController == true && connection.getConnectionInfo().getLocalIp() != null) { + String localIp = String.valueOf(connection.getConnectionInfo().getLocalIp().getValue()); + String targetString = "tcp:" + localIp + ":" + OF_PORT; + controllerBuilder.setTarget(new Uri(targetString)); + result.add(controllerBuilder.build()); + } + + return result; + } + + private Optional getConnection(ReadWriteTransaction transaction,OvsdbBridgeAugmentation bridge) { + OvsdbNodeRef bareIId = bridge.getManagedBy(); + if(bareIId != null) { + if(bareIId.getValue().getTargetType().equals(Node.class)) { + InstanceIdentifier iid = (InstanceIdentifier) bareIId.getValue(); + CheckedFuture, ReadFailedException> connectionFuture = + transaction.read(LogicalDatastoreType.OPERATIONAL, iid); + try { + Optional nodeOptional = connectionFuture.get(); + if(nodeOptional.isPresent() && nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class) != null) { + return Optional.of(nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class)); + } else { + LOG.warn("Could not find ovsdb-node for connection for {}",bridge); + } + } catch (InterruptedException | ExecutionException e) { + LOG.warn("Could not find ovsdb-node for connection for {}",bridge,e); + } + } else { + LOG.warn("Bridge 'managedBy' non-ovsdb-node. bridge {} getManagedBy() {}",bridge,bareIId.getValue()); + } + } else { + LOG.warn("Bridge 'managedBy' is null. bridge {}",bridge); + } + return Optional.absent(); + } +} +