uses bgp-table-type;
}
}
+ case c-graceful-restart {
+ container graceful-restart-capability {
+ reference "http://tools.ietf.org/html/rfc4724#section-3";
+
+ leaf restart-flags {
+ type bits {
+ bit restart-state {
+ position 0;
+ }
+ }
+ mandatory true;
+ }
+
+ leaf restart-time {
+ type uint16 {
+ range 0..4095;
+ }
+ units seconds;
+ mandatory true;
+ }
+
+ list tables {
+ uses bgp-table-type;
+ key "afi safi";
+
+ leaf afi-flags {
+ type bits {
+ bit forwarding-state {
+ position 0;
+ }
+ }
+ mandatory true;
+ }
+ }
+ }
+ }
}
augment "/bgp-msg:update/bgp-msg:path-attributes" {
<module>rib-impl</module>
<module>testtool</module>
<module>rib-mock</module>
+ <module>topology-provider</module>
<module>util</module>
</modules>
</project>
*/
package org.opendaylight.protocol.bgp.rib.impl;
+import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.HashedWheelTimer;
import io.netty.util.Timer;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;
-
-import java.net.InetSocketAddress;
-
import org.opendaylight.protocol.bgp.parser.BGPMessageFactory;
import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
import org.opendaylight.protocol.framework.ReconnectStrategy;
import org.opendaylight.protocol.framework.SessionListenerFactory;
+import java.net.InetSocketAddress;
+
/**
* Implementation of BGPDispatcher.
*/
private final BGPHandlerFactory hf;
- public BGPDispatcherImpl(final BGPMessageFactory parser) {
- super();
+ public BGPDispatcherImpl(final BGPMessageFactory parser, EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
+ super(bossGroup, workerGroup);
this.hf = new BGPHandlerFactory(parser);
}
*/
package org.opendaylight.protocol.bgp.testtool;
+import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
-
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-
import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactoryImpl;
import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
/**
* Starter class for testing.
*/
private static final int RECONNECT_MILLIS = 5000;
Main() throws Exception {
- this.dispatcher = new BGPDispatcherImpl(new BGPMessageFactoryImpl(ServiceLoaderBGPExtensionProviderContext.createConsumerContext().getMessageRegistry()));
+ this.dispatcher = new BGPDispatcherImpl(new BGPMessageFactoryImpl(ServiceLoaderBGPExtensionProviderContext
+ .createConsumerContext().getMessageRegistry()), new NioEventLoopGroup(), new NioEventLoopGroup());
}
public static void main(final String[] args) throws Exception {
*/
package org.opendaylight.protocol.bgp.testtool;
+import com.google.common.base.Preconditions;
+import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.HashedWheelTimer;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.GlobalEventExecutor;
import io.netty.util.concurrent.Promise;
-
-import java.net.InetSocketAddress;
-
import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactoryImpl;
import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yangtools.yang.binding.Notification;
-import com.google.common.base.Preconditions;
+import java.net.InetSocketAddress;
public class BGPSpeakerMock<M, S extends ProtocolSession<M>, L extends SessionListener<M, ?, ?>> extends AbstractDispatcher<S, L> {
public BGPSpeakerMock(final SessionNegotiatorFactory<M, S, L> negotiatorFactory, final ProtocolHandlerFactory<?> factory,
final DefaultPromise<BGPSessionImpl> defaultPromise) {
+ super(new NioEventLoopGroup(), new NioEventLoopGroup());
this.negotiatorFactory = Preconditions.checkNotNull(negotiatorFactory);
this.factory = Preconditions.checkNotNull(factory);
}
<parent>
<groupId>org.opendaylight.bgpcep</groupId>
- <artifactId>topology-parent</artifactId>
+ <artifactId>bgp-parent</artifactId>
<version>0.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>topology-provider-bgp</artifactId>
+ <artifactId>bgp-topology-provider</artifactId>
<description>BGP Topology Provider</description>
<packaging>bundle</packaging>
<name>${project.artifactId}</name>
<distributionManagement>
<site>
<id>${project.artifactId}</id>
- <name>TOPOLOGY-PROVIDER-BGP Module site</name>
+ <name>BGP-TOPOLOGY-PROVIDER Module site</name>
<url>${basedir}/target/site/${project.artifactId}</url>
</site>
</distributionManagement>
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.topology.provider.bgp;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractLocRIBListener<T extends Route> implements LocRIBListener {
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractLocRIBListener.class);
+ protected final InstanceIdentifier<Topology> topology;
+ private final Class<T> idClass;
+
+ protected AbstractLocRIBListener(final InstanceIdentifier<Topology> topology, final Class<T> idClass) {
+ this.topology = Preconditions.checkNotNull(topology);
+ this.idClass = Preconditions.checkNotNull(idClass);
+ }
+
+ protected abstract void createObject(DataModification<InstanceIdentifier<?>, DataObject> trans, InstanceIdentifier<T> id, T value);
+ protected abstract void removeObject(DataModification<InstanceIdentifier<?>, DataObject> trans, InstanceIdentifier<T> id, T value);
+
+ private InstanceIdentifier<T> changedObject(final InstanceIdentifier<?> id, final int depth) {
+ final List<PathArgument> p = id.getPath();
+ final int i = p.indexOf(idClass);
+ Preconditions.checkState(i > -1, "Class %s not found in identifier %s", idClass, id);
+ return new InstanceIdentifier<>(p.subList(depth, i), idClass);
+ }
+
+ @Override
+ public final void onLocRIBChange(final DataModification<InstanceIdentifier<?>, DataObject> trans,
+ final DataChangeEvent<InstanceIdentifier<?>, DataObject> event, final int depth) {
+
+ final Set<InstanceIdentifier<T>> ids = new HashSet<>();
+ for (final InstanceIdentifier<?> i : event.getRemovedOperationalData()) {
+ ids.add(Preconditions.checkNotNull(changedObject(i, depth)));
+ }
+ for (final InstanceIdentifier<?> i : event.getUpdatedOperationalData().keySet()) {
+ ids.add(Preconditions.checkNotNull(changedObject(i, depth)));
+ }
+ for (final InstanceIdentifier<?> i : event.getCreatedOperationalData().keySet()) {
+ ids.add(Preconditions.checkNotNull(changedObject(i, depth)));
+ }
+
+ final Map<InstanceIdentifier<?>, DataObject> o = event.getOriginalOperationalData();
+ final Map<InstanceIdentifier<?>, DataObject> n = event.getUpdatedOperationalData();
+ for (final InstanceIdentifier<T> i : ids) {
+ final T oldValue = idClass.cast(o.get(i));
+ final T newValue = idClass.cast(n.get(i));
+
+ LOG.debug("Updating object {} value {} -> {}", i, oldValue, newValue);
+ if (oldValue != null) {
+ removeObject(trans, i, oldValue);
+ }
+ if (newValue != null) {
+ createObject(trans, i, newValue);
+ }
+ }
+ }
+}
import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public interface LocRIBListener extends EventListener {
/**
* is not shared with any other entity and will be cleaned up by the
* caller if it is not committed before this method returns.
* @param event Data change event
+ * @param depth Subscription path depth.
* @throws Exception throw it if you must. If you can handle it, please do so.
*/
- public void onLocRIBChange(DataModification<?, ?> trans, DataChangeEvent<?, ?> event) throws Exception;
+ public void onLocRIBChange(DataModification<InstanceIdentifier<?>, DataObject> trans,
+ DataChangeEvent<InstanceIdentifier<?>, DataObject> event, int depth) throws Exception;
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.topology.provider.bgp.impl;
+
+import java.util.ArrayList;
+
+import org.opendaylight.bgpcep.topology.provider.bgp.AbstractLocRIBListener;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.route.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.CNextHop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.CIpv4NextHop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.CIpv6NextHop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.c.ipv4.next.hop.Ipv4NextHop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.c.ipv6.next.hop.Ipv6NextHop;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+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.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.IgpNodeAttributes;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Node1;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Node1Builder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.IgpNodeAttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.igp.node.attributes.Prefix;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.igp.node.attributes.PrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.igp.node.attributes.PrefixKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+abstract class AbstractReachabilityTopologyBuilder<T extends Route> extends AbstractLocRIBListener<T> {
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractReachabilityTopologyBuilder.class);
+
+ protected AbstractReachabilityTopologyBuilder(final InstanceIdentifier<Topology> topology, final Class<T> idClass) {
+ super(topology, idClass);
+ }
+
+ private NodeId advertizingNode(final Attributes attrs) {
+ final CNextHop nh = attrs.getCNextHop();
+ if (nh instanceof CIpv4NextHop) {
+ final Ipv4NextHop ipv4 = ((CIpv4NextHop) nh).getIpv4NextHop();
+
+ return new NodeId(ipv4.getGlobal().getValue());
+ } else if (nh instanceof CIpv6NextHop) {
+ final Ipv6NextHop ipv6 = ((CIpv6NextHop) nh).getIpv6NextHop();
+
+ return new NodeId(ipv6.getGlobal().getValue());
+ } else {
+ LOG.warn("Unhandled next hop class {}", nh.getImplementedInterface());
+ return null;
+ }
+ }
+
+ private InstanceIdentifier<Node1> nodeInstanceId(final NodeId ni) {
+ return InstanceIdentifier.builder(topology).node(Node.class, new NodeKey(ni)).node(Node1.class).toInstance();
+ }
+
+ private InstanceIdentifier<Node1> ensureNodePresent(final DataModification<InstanceIdentifier<?>, DataObject> trans,
+ final NodeId ni) {
+ final InstanceIdentifier<Node1> nii = nodeInstanceId(ni);
+
+ if (trans.readOperationalData(nii) == null) {
+ LOG.debug("Create a new node at {}", nii);
+ trans.putOperationalData(nii, new Node1Builder().setIgpNodeAttributes(
+ new IgpNodeAttributesBuilder().setPrefix(new ArrayList<Prefix>()).build()).build());
+ }
+
+ return nii;
+ }
+
+ private void removeEmptyNode(final DataModification<InstanceIdentifier<?>, DataObject> trans, final InstanceIdentifier<Node1> nii) {
+ final Node1 node = (Node1) trans.readOperationalData(nii);
+ if (node != null && node.getIgpNodeAttributes().getPrefix().isEmpty()) {
+ trans.removeOperationalData(nii);
+ }
+ }
+
+ protected abstract Attributes getAttributes(final T value);
+ protected abstract IpPrefix getPrefix(final T value);
+
+ @Override
+ protected final void createObject(final DataModification<InstanceIdentifier<?>, DataObject> trans,
+ final InstanceIdentifier<T> id, final T value) {
+ final NodeId ni = advertizingNode(getAttributes(value));
+ final InstanceIdentifier<Node1> nii = ensureNodePresent(trans, ni);
+
+ final IpPrefix prefix = getPrefix(value);
+ final PrefixKey pk = new PrefixKey(prefix);
+
+ trans.putOperationalData(InstanceIdentifier.builder(nii).node(IgpNodeAttributes.class).node(Prefix.class, pk).toInstance(),
+ new PrefixBuilder().setKey(pk).setPrefix(prefix).build());
+ }
+
+
+ @Override
+ protected final void removeObject(final DataModification<InstanceIdentifier<?>, DataObject> trans,
+ final InstanceIdentifier<T> id, final T value) {
+ final NodeId ni = advertizingNode(getAttributes(value));
+ final InstanceIdentifier<Node1> nii = nodeInstanceId(ni);
+
+ final IpPrefix prefix = getPrefix(value);
+ final PrefixKey pk = new PrefixKey(prefix);
+
+ trans.removeOperationalData(InstanceIdentifier.builder(nii).node(IgpNodeAttributes.class).node(Prefix.class, pk).toInstance());
+
+ removeEmptyNode(trans, nii);
+ }
+}
import com.google.common.base.Preconditions;
public class Activator extends AbstractBindingAwareProvider {
-// private ServiceRegistration<LocRIBListeners.Subscribtion> ipv4, ipv6, linkstate;
+ private ServiceRegistration<LocRIBListeners.Subscribtion> ipv4, ipv6, linkstate;
private BundleContext context;
@Override
final LocRIBListenerSubscriptionTracker reg = new LocRIBListenerSubscriptionTracker(context, session.getSALService(DataProviderService.class));
reg.open();
-// ipv4 = LocRIBListeners.subscribe(context, Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class, new Ipv4ReachabilityTopologyBuilder());
-// ipv6 = LocRIBListeners.subscribe(context, Ipv6AddressFamily.class, UnicastSubsequentAddressFamily.class, new Ipv6ReachabilityTopologyBuilder());
-// linkstate = LocRIBListeners.subscribe(context, LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class, new LinkstateTopologyBuilder());
+ ipv4 = LocRIBListeners.subscribe(context, Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class,
+ new Ipv4ReachabilityTopologyBuilder(null));
+ ipv6 = LocRIBListeners.subscribe(context, Ipv6AddressFamily.class, UnicastSubsequentAddressFamily.class,
+ new Ipv6ReachabilityTopologyBuilder(null));
+// linkstate = LocRIBListeners.subscribe(context, LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class,
+// new LinkstateTopologyBuilder(null));
}
@Override
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.topology.provider.bgp.impl;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.routes.ipv4.routes.Ipv4Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.route.Attributes;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+final class Ipv4ReachabilityTopologyBuilder extends AbstractReachabilityTopologyBuilder<Ipv4Routes> {
+ Ipv4ReachabilityTopologyBuilder(final InstanceIdentifier<Topology> topology) {
+ super(topology, Ipv4Routes.class);
+ }
+
+ @Override
+ protected Attributes getAttributes(final Ipv4Routes value) {
+ return value.getAttributes();
+ }
+
+ @Override
+ protected IpPrefix getPrefix(final Ipv4Routes value) {
+ return new IpPrefix(value.getKey().getPrefix());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.topology.provider.bgp.impl;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.routes.ipv6.routes.Ipv6Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.route.Attributes;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+final class Ipv6ReachabilityTopologyBuilder extends AbstractReachabilityTopologyBuilder<Ipv6Routes> {
+ Ipv6ReachabilityTopologyBuilder(final InstanceIdentifier<Topology> topology) {
+ super(topology, Ipv6Routes.class);
+ }
+
+ @Override
+ protected Attributes getAttributes(final Ipv6Routes value) {
+ return value.getAttributes();
+ }
+
+ @Override
+ protected IpPrefix getPrefix(final Ipv6Routes value) {
+ return new IpPrefix(value.getKey().getPrefix());
+ }
+}
import org.opendaylight.bgpcep.topology.provider.bgp.LocRIBListener;
import org.opendaylight.bgpcep.topology.provider.bgp.LocRIBListeners;
import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.LocRib;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
final InstanceIdentifier<Tables> path = InstanceIdentifier.builder(locRIBPath).
node(Tables.class, new TablesKey(service.getAfi(), service.getSafi())).toInstance();
final LocRIBListener listener = service.getLocRIBListener();
+ final int depth = path.getPath().size();
final DataChangeListener dcl = new DataChangeListener() {
@Override
public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- final DataModification<?, ?> trans = dps.beginTransaction();
+ final DataModificationTransaction trans = dps.beginTransaction();
try {
- listener.onLocRIBChange(trans, change);
+ listener.onLocRIBChange(trans, change, depth);
} catch (Exception e) {
LOG.info("Data change {} was not completely propagated to listener {}", change, listener, e);
}
import java.util.Set;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.protocol.util.ByteArray;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nps.concepts.rev130930.Bandwidth;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GlobalEventExecutor;
import io.netty.util.concurrent.Promise;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.net.InetSocketAddress;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* Dispatcher class for creating servers and clients. The idea is to first create servers and clients and the run the
* start method that will handle sockets in different thread.
/**
* Initializes channel by specifying the handlers in its pipeline. Handlers are protocol specific, therefore this
* method needs to be implemented in protocol specific Dispatchers.
- *
+ *
* @param channel whose pipeline should be defined, also to be passed to {@link SessionNegotiatorFactory}
* @param promise to be passed to {@link SessionNegotiatorFactory}
*/
private final EventLoopGroup workerGroup;
+
+ /**
+ * Internally creates new instances of NioEventLoopGroup, might deplete system resources and result in Too many open files exception.
+ *
+ * @deprecated use {@link AbstractDispatcher#AbstractDispatcher(io.netty.channel.EventLoopGroup, io.netty.channel.EventLoopGroup)} instead.
+ */
+ @Deprecated
protected AbstractDispatcher() {
- // FIXME: we should get these as arguments
- this.bossGroup = new NioEventLoopGroup();
- this.workerGroup = new NioEventLoopGroup();
+ this(new NioEventLoopGroup(),new NioEventLoopGroup());
+ }
+
+ protected AbstractDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
+ this.bossGroup = bossGroup;
+ this.workerGroup = workerGroup;
}
/**
* Creates server. Each server needs factories to pass their instances to client sessions.
- *
+ *
* @param address address to which the server should be bound
* @param initializer instance of PipelineInitializer used to initialize the channel pipeline
- *
+ *
* @return ChannelFuture representing the binding process
*/
protected ChannelFuture createServer(final InetSocketAddress address, final PipelineInitializer<S> initializer) {
/**
* Creates a client.
- *
+ *
* @param address remote address
* @param connectStrategy Reconnection strategy to be used when initial connection fails
- *
+ *
* @return Future representing the connection process. Its result represents the combined success of TCP connection
- * as well as session negotiation.
+ * as well as session negotiation.
*/
protected Future<S> createClient(final InetSocketAddress address, final ReconnectStrategy strategy, final PipelineInitializer<S> initializer) {
final Bootstrap b = new Bootstrap();
/**
* Creates a client.
- *
+ *
* @param address remote address
* @param connectStrategyFactory Factory for creating reconnection strategy to be used when initial connection fails
* @param reestablishStrategy Reconnection strategy to be used when the already-established session fails
- *
+ *
* @return Future representing the reconnection task. It will report completion based on reestablishStrategy, e.g.
- * success if it indicates no further attempts should be made and failure if it reports an error
+ * success if it indicates no further attempts should be made and failure if it reports an error
*/
protected Future<Void> createReconnectingClient(final InetSocketAddress address, final ReconnectStrategyFactory connectStrategyFactory,
final ReconnectStrategy reestablishStrategy, final PipelineInitializer<S> initializer) {
package org.opendaylight.protocol.framework;
+import com.google.common.base.Preconditions;
import io.netty.channel.ChannelFuture;
+import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;
-
-import java.net.InetSocketAddress;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
+import java.net.InetSocketAddress;
public class SimpleDispatcher extends AbstractDispatcher<SimpleSession, SimpleSessionListener> {
public SimpleDispatcher(final SessionNegotiatorFactory<SimpleMessage, SimpleSession, SimpleSessionListener> negotiatorFactory, final ProtocolHandlerFactory<?> factory,
final Promise<SimpleSession> promise) {
+ super(new NioEventLoopGroup(), new NioEventLoopGroup());
this.negotiatorFactory = Preconditions.checkNotNull(negotiatorFactory);
this.factory = Preconditions.checkNotNull(factory);
}
container lspa {
uses object;
-
- leaf hold-priority {
- type uint8;
- mandatory true;
- }
-
- leaf setup-priority {
- type uint8;
- mandatory true;
- }
-
- leaf local-protection-desired {
- type boolean;
- default false;
- }
-
- uses rsvp:attribute-filters;
+ uses rsvp:tunnel-attributes;
}
}
*/
package org.opendaylight.protocol.pcep.impl;
+import com.google.common.base.Preconditions;
import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-
import org.opendaylight.protocol.framework.AbstractDispatcher;
import org.opendaylight.protocol.framework.SessionListenerFactory;
import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
import org.opendaylight.protocol.pcep.spi.MessageHandlerRegistry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
-import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.net.InetSocketAddress;
/**
* Implementation of PCEPDispatcher.
/**
* Creates an instance of PCEPDispatcherImpl, gets the default selector and opens it.
- *
+ *
* @throws IOException if some error occurred during opening the selector
*/
- public PCEPDispatcherImpl(final MessageHandlerRegistry registry, final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> negotiatorFactory) {
- super();
+ public PCEPDispatcherImpl(final MessageHandlerRegistry registry,
+ final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> negotiatorFactory,
+ EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
+ super(bossGroup, workerGroup);
this.snf = Preconditions.checkNotNull(negotiatorFactory);
this.hf = new PCEPHandlerFactory(registry);
}
<module>testtool</module>
<module>topology-api</module>
<module>topology-provider</module>
+ <module>topology-spi</module>
<module>tunnel-api</module>
<module>tunnel-provider</module>
</modules>
*/
package org.opendaylight.protocol.pcep.testtool;
+import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
-
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-
import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
import org.opendaylight.protocol.pcep.impl.DefaultPCEPSessionNegotiatorFactory;
import org.opendaylight.protocol.pcep.impl.PCEPDispatcherImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
final Open prefs = spf.getSessionProposal(address, 0);
- final PCEPDispatcherImpl dispatcher = new PCEPDispatcherImpl(PCEPExtensionProviderContextImpl.getSingletonInstance().getMessageHandlerRegistry(), new DefaultPCEPSessionNegotiatorFactory(new HashedWheelTimer(), prefs, 5));
+ final PCEPDispatcherImpl dispatcher = new PCEPDispatcherImpl(PCEPExtensionProviderContextImpl
+ .getSingletonInstance().getMessageHandlerRegistry(), new DefaultPCEPSessionNegotiatorFactory(
+ new HashedWheelTimer(), prefs, 5), new NioEventLoopGroup(), new NioEventLoopGroup());
dispatcher.createServer(address, new TestingSessionListenerFactory()).get();
}
*/
package org.opendaylight.protocol.pcep.testtool;
+import com.google.common.base.Preconditions;
+import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.HashedWheelTimer;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GlobalEventExecutor;
import io.netty.util.concurrent.Promise;
-
-import java.net.InetSocketAddress;
-
import org.opendaylight.protocol.framework.AbstractDispatcher;
import org.opendaylight.protocol.framework.NeverReconnectStrategy;
import org.opendaylight.protocol.framework.ProtocolHandlerFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.TlvsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.predundancy.group.id.tlv.PredundancyGroupIdBuilder;
-import com.google.common.base.Preconditions;
+import java.net.InetSocketAddress;
public class PCCMock<M, S extends ProtocolSession<M>, L extends SessionListener<M, ?, ?>> extends AbstractDispatcher<S, L> {
public PCCMock(final SessionNegotiatorFactory<M, S, L> negotiatorFactory, final ProtocolHandlerFactory<?> factory,
final DefaultPromise<PCEPSessionImpl> defaultPromise) {
+ super(new NioEventLoopGroup(), new NioEventLoopGroup());
this.negotiatorFactory = Preconditions.checkNotNull(negotiatorFactory);
this.factory = Preconditions.checkNotNull(factory);
}
<artifactId>pcep-topology-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-topology-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-api</artifactId>
package org.opendaylight.bgpcep.pcep.topology.provider;
import io.netty.channel.ChannelFuture;
+import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
-import io.netty.util.concurrent.GlobalEventExecutor;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutionException;
final InetSocketAddress address = new InetSocketAddress("0.0.0.0", 4189);
final PCEPSessionProposalFactory spf = new PCEPSessionProposalFactoryImpl(30, 10, true, true, true, true, 0);
final Open prefs = spf.getSessionProposal(address, 0);
- final PCEPDispatcher dispatcher = new PCEPDispatcherImpl(PCEPExtensionProviderContextImpl.getSingletonInstance().getMessageHandlerRegistry(), new DefaultPCEPSessionNegotiatorFactory(new HashedWheelTimer(), prefs, 5));
+ final PCEPDispatcher dispatcher = new PCEPDispatcherImpl(PCEPExtensionProviderContextImpl
+ .getSingletonInstance().getMessageHandlerRegistry(), new DefaultPCEPSessionNegotiatorFactory(
+ new HashedWheelTimer(), prefs, 5), new NioEventLoopGroup(), new NioEventLoopGroup());
+
final InstanceIdentifier<Topology> topology = InstanceIdentifier.builder().node(Topology.class).toInstance();
- final PCEPTopologyProvider exp = new PCEPTopologyProvider(dispatcher, GlobalEventExecutor.INSTANCE, null, dps, topology);
+ final PCEPTopologyProvider exp = new PCEPTopologyProvider(dispatcher, null, dps, topology);
final ChannelFuture s = exp.startServer(address);
try {
s.get();
package org.opendaylight.bgpcep.pcep.topology.provider;
import io.netty.channel.ChannelFuture;
-import io.netty.util.concurrent.EventExecutor;
import java.net.InetSocketAddress;
private final TopologyRPCs element;
public PCEPTopologyProvider(final PCEPDispatcher dispatcher,
- final EventExecutor executor,
final InstructionScheduler scheduler,
final DataProviderService dataService,
final InstanceIdentifier<Topology> topology) {
this.dispatcher = Preconditions.checkNotNull(dispatcher);
- this.manager = new ServerSessionManager(executor, dataService, topology);
- this.element = new TopologyRPCs(executor, manager);
- this.topology = new TopologyProgramming(executor, scheduler, manager);
+ this.manager = new ServerSessionManager(dataService, topology);
+ this.element = new TopologyRPCs(manager);
+ this.topology = new TopologyProgramming(scheduler, manager);
}
public ChannelFuture startServer(final InetSocketAddress address) {
*/
package org.opendaylight.bgpcep.pcep.topology.provider;
-import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.FutureListener;
-import io.netty.util.concurrent.Promise;
import java.net.InetAddress;
import java.util.HashMap;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
/**
*
}
private final class SessionListener implements PCEPSessionListener {
- private final Map<SrpIdNumber, Promise<OperationResult>> waitingRequests = new HashMap<>();
- private final Map<SrpIdNumber, Promise<OperationResult>> sendingRequests = new HashMap<>();
+ private final Map<SrpIdNumber, SettableFuture<OperationResult>> waitingRequests = new HashMap<>();
+ private final Map<SrpIdNumber, SettableFuture<OperationResult>> sendingRequests = new HashMap<>();
private final Map<PlspId, SymbolicPathName> lsps = new HashMap<>();
private PathComputationClientBuilder pccBuilder;
private InstanceIdentifier<Node1> topologyAugment;
}
// Clear all requests which have not been sent to the peer: they result in cancellation
- for (final Entry<SrpIdNumber, Promise<OperationResult>> e : this.sendingRequests.entrySet()) {
+ for (final Entry<SrpIdNumber, SettableFuture<OperationResult>> e : this.sendingRequests.entrySet()) {
LOG.debug("Request {} was not sent when session went down, cancelling the instruction", e.getKey());
- e.getValue().setSuccess(OPERATION_UNSENT);
+ e.getValue().set(OPERATION_UNSENT);
}
this.sendingRequests.clear();
// CLear all requests which have not been acked by the peer: they result in failure
- for (final Entry<SrpIdNumber, Promise<OperationResult>> e : this.waitingRequests.entrySet()) {
+ for (final Entry<SrpIdNumber, SettableFuture<OperationResult>> e : this.waitingRequests.entrySet()) {
LOG.info("Request {} was incomplete when session went down, failing the instruction", e.getKey());
- e.getValue().setSuccess(OPERATION_NOACK);
+ e.getValue().set(OPERATION_NOACK);
}
this.waitingRequests.clear();
}
case Active:
case Down:
case Up:
- final Promise<OperationResult> p = this.waitingRequests.remove(id);
+ final SettableFuture<OperationResult> p = this.waitingRequests.remove(id);
if (p != null) {
LOG.debug("Request {} resulted in LSP operational state {}", id, lsp.getOperational());
- p.setSuccess(OPERATION_SUCCESS);
+ p.set(OPERATION_SUCCESS);
} else {
LOG.warn("Request ID {} not found in outstanding DB", id);
}
}
private synchronized void messageSendingComplete(final SrpIdNumber requestId, final io.netty.util.concurrent.Future<Void> future) {
- final Promise<OperationResult> promise = this.sendingRequests.remove(requestId);
+ final SettableFuture<OperationResult> promise = this.sendingRequests.remove(requestId);
if (future.isSuccess()) {
this.waitingRequests.put(requestId, promise);
} else {
LOG.info("Failed to send request {}, instruction cancelled", requestId, future.cause());
- promise.setSuccess(OPERATION_UNSENT);
+ promise.set(OPERATION_UNSENT);
}
}
- private synchronized io.netty.util.concurrent.Future<OperationResult> sendMessage(final Message message, final SrpIdNumber requestId) {
+ private synchronized ListenableFuture<OperationResult> sendMessage(final Message message, final SrpIdNumber requestId) {
final io.netty.util.concurrent.Future<Void> f = this.session.sendMessage(message);
- final Promise<OperationResult> ret = ServerSessionManager.this.exec.newPromise();
+ final SettableFuture<OperationResult> ret = SettableFuture.create();
this.sendingRequests.put(requestId, ret);
private final Map<NodeId, SessionListener> nodes = new HashMap<>();
private final InstanceIdentifier<Topology> topology;
private final DataProviderService dataProvider;
- private final EventExecutor exec;
- public ServerSessionManager(final EventExecutor exec, final DataProviderService dataProvider,
- final InstanceIdentifier<Topology> topology) {
+ public ServerSessionManager(final DataProviderService dataProvider, final InstanceIdentifier<Topology> topology) {
this.dataProvider = Preconditions.checkNotNull(dataProvider);
this.topology = Preconditions.checkNotNull(topology);
- this.exec = Preconditions.checkNotNull(exec);
}
@Override
return new SessionListener();
}
- synchronized io.netty.util.concurrent.Future<OperationResult> realAddLsp(final AddLspArgs input) {
+ synchronized ListenableFuture<OperationResult> realAddLsp(final AddLspArgs input) {
// Get the listener corresponding to the node
final SessionListener l = this.nodes.get(input.getNode());
if (l == null) {
LOG.debug("Session for node {} not found", input.getNode());
- return this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Make sure there is no such LSP
new ReportedLspsKey(input.getName())).toInstance();
if (this.dataProvider.readOperationalData(lsp) != null) {
LOG.debug("Node {} already contains lsp {} at {}", input.getNode(), input.getName(), lsp);
- return this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Build the request
};
}
- synchronized io.netty.util.concurrent.Future<OperationResult> realRemoveLsp(final RemoveLspArgs input) {
+ synchronized ListenableFuture<OperationResult> realRemoveLsp(final RemoveLspArgs input) {
// Get the listener corresponding to the node
final SessionListener l = this.nodes.get(input.getNode());
if (l == null) {
LOG.debug("Session for node {} not found", input.getNode());
- return this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Make sure the LSP exists, we need it for PLSP-ID
final ReportedLsps rep = (ReportedLsps) this.dataProvider.readOperationalData(lsp);
if (rep == null) {
LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
- return this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Build the request and send it
return l.sendMessage(new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build(), rb.getSrp().getOperationId());
}
- synchronized io.netty.util.concurrent.Future<OperationResult> realUpdateLsp(final UpdateLspArgs input) {
+ synchronized ListenableFuture<OperationResult> realUpdateLsp(final UpdateLspArgs input) {
// Get the listener corresponding to the node
final SessionListener l = this.nodes.get(input.getNode());
if (l == null) {
LOG.debug("Session for node {} not found", input.getNode());
- return this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Make sure the LSP exists
final ReportedLsps rep = (ReportedLsps) this.dataProvider.readOperationalData(lsp);
if (rep == null) {
LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
- return this.exec.newSucceededFuture(OPERATION_UNSENT);
+ return Futures.immediateFuture(OPERATION_UNSENT);
}
// Build the PCUpd request and send it
*/
package org.opendaylight.bgpcep.pcep.topology.provider;
-import io.netty.util.concurrent.EventExecutor;
-import io.netty.util.concurrent.FutureListener;
-import io.netty.util.concurrent.Promise;
-
-import java.util.concurrent.Future;
-
-import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
+import org.opendaylight.bgpcep.pcep.topology.spi.AbstractTopologyProgrammingExecutor;
import org.opendaylight.bgpcep.programming.spi.InstructionExecutor;
import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.FailureBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.failure.Failure;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.NetworkTopologyPcepProgrammingService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.programming.rev131106.SubmitUpdateLspOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.FailureType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
import org.opendaylight.yangtools.yang.common.RpcResult;
import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
/**
*
*/
final class TopologyProgramming implements NetworkTopologyPcepProgrammingService {
- private abstract class AbstractInstructionExecutor implements InstructionExecutor {
-
- protected abstract io.netty.util.concurrent.Future<OperationResult> executeImpl();
-
- @Override
- public final io.netty.util.concurrent.Future<ExecutionResult<Details>> execute() {
- final Promise<ExecutionResult<Details>> promise = exec.newPromise();
-
- executeImpl().addListener(new FutureListener<OperationResult>() {
- @Override
- public void operationComplete(final io.netty.util.concurrent.Future<OperationResult> future) {
- if (future.isSuccess()) {
- final OperationResult res = future.getNow();
- final FailureType fail = res.getFailure();
-
- final ExecutionResult<Details> result;
- if (fail != null) {
- switch (fail) {
- case Failed:
- case NoAck:
- result = new ExecutionResult<Details>(InstructionStatus.Failed, null);
- break;
- case Unsent:
- result = new ExecutionResult<Details>(InstructionStatus.Cancelled, null);
- break;
- }
-
- throw new IllegalStateException("Unhandled operation state " + fail);
- } else {
- result = new ExecutionResult<Details>(InstructionStatus.Successful, null);
- }
-
- promise.setSuccess(result);
- } else {
- promise.setFailure(future.cause());
- }
- }
- });
-
- return promise;
- }
- }
-
private final InstructionScheduler scheduler;
private final ServerSessionManager manager;
- private final EventExecutor exec;
- TopologyProgramming(final EventExecutor executor, final InstructionScheduler scheduler, final ServerSessionManager manager) {
+ TopologyProgramming(final InstructionScheduler scheduler, final ServerSessionManager manager) {
this.scheduler = Preconditions.checkNotNull(scheduler);
this.manager = Preconditions.checkNotNull(manager);
- this.exec = Preconditions.checkNotNull(executor);
}
@Override
- public Future<RpcResult<SubmitAddLspOutput>> submitAddLsp(final SubmitAddLspInput input) {
+ public ListenableFuture<RpcResult<SubmitAddLspOutput>> submitAddLsp(final SubmitAddLspInput input) {
Preconditions.checkArgument(input.getNode() != null);
Preconditions.checkArgument(input.getName() != null);
- final InstructionExecutor e = new AbstractInstructionExecutor() {
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
@Override
- public io.netty.util.concurrent.Future<OperationResult> executeImpl() {
+ public ListenableFuture<OperationResult> executeImpl() {
return manager.realAddLsp(input);
}
};
}
final RpcResult<SubmitAddLspOutput> res = SuccessfulRpcResult.create(b.build());
- return exec.newSucceededFuture(res);
+ return Futures.immediateFuture(res);
}
@Override
- public Future<RpcResult<SubmitRemoveLspOutput>> submitRemoveLsp(final SubmitRemoveLspInput input) {
+ public ListenableFuture<RpcResult<SubmitRemoveLspOutput>> submitRemoveLsp(final SubmitRemoveLspInput input) {
Preconditions.checkArgument(input.getNode() != null);
Preconditions.checkArgument(input.getName() != null);
- final InstructionExecutor e = new AbstractInstructionExecutor() {
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
@Override
- protected io.netty.util.concurrent.Future<OperationResult> executeImpl() {
+ protected ListenableFuture<OperationResult> executeImpl() {
return manager.realRemoveLsp(input);
}
};
}
final RpcResult<SubmitRemoveLspOutput> res = SuccessfulRpcResult.create(b.build());
- return exec.newSucceededFuture(res);
+ return Futures.immediateFuture(res);
}
@Override
- public Future<RpcResult<SubmitUpdateLspOutput>> submitUpdateLsp(final SubmitUpdateLspInput input) {
+ public ListenableFuture<RpcResult<SubmitUpdateLspOutput>> submitUpdateLsp(final SubmitUpdateLspInput input) {
Preconditions.checkArgument(input.getNode() != null);
Preconditions.checkArgument(input.getName() != null);
- final InstructionExecutor e = new AbstractInstructionExecutor() {
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
@Override
- protected io.netty.util.concurrent.Future<OperationResult> executeImpl() {
+ protected ListenableFuture<OperationResult> executeImpl() {
return manager.realUpdateLsp(input);
}
};
}
final RpcResult<SubmitUpdateLspOutput> res = SuccessfulRpcResult.create(b.build());
- return exec.newSucceededFuture(res);
+ return Futures.immediateFuture(res);
}
}
*/
package org.opendaylight.bgpcep.pcep.topology.provider;
-import io.netty.util.concurrent.EventExecutor;
-import io.netty.util.concurrent.FutureListener;
-import io.netty.util.concurrent.Promise;
-
import java.util.concurrent.Future;
import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutputBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import com.google.common.base.Function;
import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
final class TopologyRPCs implements NetworkTopologyPcepService {
private final ServerSessionManager manager;
- private final EventExecutor exec;
-
- private abstract class ExecutionResultAdaptor<T> implements FutureListener<OperationResult> {
- protected final Promise<RpcResult<T>> promise = exec.newPromise();
-
- protected abstract RpcResult<T> convertResult(OperationResult result);
- @Override
- public final void operationComplete(final io.netty.util.concurrent.Future<OperationResult> future) {
- if (future.isSuccess()) {
- promise.setSuccess(convertResult(future.getNow()));
- } else {
- promise.setFailure(future.cause());
- }
- }
- }
-
- TopologyRPCs(final EventExecutor exec, final ServerSessionManager manager) {
+ TopologyRPCs(final ServerSessionManager manager) {
this.manager = Preconditions.checkNotNull(manager);
- this.exec = Preconditions.checkNotNull(exec);
}
@Override
public Future<RpcResult<AddLspOutput>> addLsp(final AddLspInput input) {
- final ExecutionResultAdaptor<AddLspOutput> adaptor = new ExecutionResultAdaptor<AddLspOutput>() {
+ return Futures.transform(manager.realAddLsp(input), new Function<OperationResult, RpcResult<AddLspOutput>>() {
@Override
- protected RpcResult<AddLspOutput> convertResult(final OperationResult result) {
- return SuccessfulRpcResult.create(new AddLspOutputBuilder(result).build());
+ public RpcResult<AddLspOutput> apply(final OperationResult input) {
+ return SuccessfulRpcResult.create(new AddLspOutputBuilder(input).build());
}
- };
-
- manager.realAddLsp(input).addListener(adaptor);
- return adaptor.promise;
+ });
}
@Override
public Future<RpcResult<RemoveLspOutput>> removeLsp(final RemoveLspInput input) {
- final ExecutionResultAdaptor<RemoveLspOutput> adaptor = new ExecutionResultAdaptor<RemoveLspOutput>() {
+ return Futures.transform(manager.realRemoveLsp(input), new Function<OperationResult, RpcResult<RemoveLspOutput>>() {
@Override
- protected RpcResult<RemoveLspOutput> convertResult(final OperationResult result) {
- return SuccessfulRpcResult.create(new RemoveLspOutputBuilder(result).build());
+ public RpcResult<RemoveLspOutput> apply(final OperationResult input) {
+ return SuccessfulRpcResult.create(new RemoveLspOutputBuilder(input).build());
}
- };
-
- manager.realRemoveLsp(input).addListener(adaptor);
- return adaptor.promise;
+ });
}
@Override
public Future<RpcResult<UpdateLspOutput>> updateLsp(final UpdateLspInput input) {
- final ExecutionResultAdaptor<UpdateLspOutput> adaptor = new ExecutionResultAdaptor<UpdateLspOutput>() {
+ return Futures.transform(manager.realUpdateLsp(input), new Function<OperationResult, RpcResult<UpdateLspOutput>>() {
@Override
- protected RpcResult<UpdateLspOutput> convertResult(final OperationResult result) {
- return SuccessfulRpcResult.create(new UpdateLspOutputBuilder(result).build());
+ public RpcResult<UpdateLspOutput> apply(final OperationResult input) {
+ return SuccessfulRpcResult.create(new UpdateLspOutputBuilder(input).build());
}
- };
-
- manager.realUpdateLsp(input).addListener(adaptor);
- return adaptor.promise;
+ });
}
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>pcep-topology-spi</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>pcep-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>pcep-topology-spi</artifactId>
+ <description>PCEP Topology SPI</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>topology-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>programming-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>programming-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-topology-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- FIXME: integrate with config to get rid of this -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.bgpcep.pcep.topology.spi
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>PCEP-TOPOLOGY-SPI Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.pcep.topology.spi;
+
+import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
+import org.opendaylight.bgpcep.programming.spi.InstructionExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.FailureType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public abstract class AbstractTopologyProgrammingExecutor implements InstructionExecutor {
+
+ protected abstract ListenableFuture<OperationResult> executeImpl();
+
+ @Override
+ public final ListenableFuture<ExecutionResult<Details>> execute() {
+ return Futures.transform(executeImpl(), new Function<OperationResult, ExecutionResult<Details>>() {
+
+ @Override
+ public ExecutionResult<Details> apply(final OperationResult input) {
+ final FailureType fail = input.getFailure();
+ if (fail == null) {
+ return new ExecutionResult<Details>(InstructionStatus.Successful, null);
+ }
+
+ switch (fail) {
+ case Failed:
+ case NoAck:
+ return new ExecutionResult<Details>(InstructionStatus.Failed, null);
+ case Unsent:
+ return new ExecutionResult<Details>(InstructionStatus.Cancelled, null);
+ }
+
+ throw new IllegalStateException("Unhandled operation state " + fail);
+ }
+ });
+ }
+}
namespace "urn:opendaylight:params:xml:ns:yang:topology:tunnel:pcep:programming";
prefix "ttpp";
- import network-topology { prefix nt; revision-date 2013-10-21; }
import pcep-types { prefix pcep; revision-date 2013-10-05; }
- import programming { prefix pgm; revision-date 2013-09-30; }
- import topology-tunnel { prefix tt; revision-date 2013-08-19; }
import topology-tunnel-programming { prefix ttp; revision-date 2013-09-30; }
+ import topology-tunnel-p2p { prefix p2p; revision-date 2013-08-19; }
+ import topology-tunnel-pcep { prefix ptp; }
organization "Cisco Systems, Inc.";
contact "Robert Varga <rovarga@cisco.com>";
reference "";
}
- rpc pcep-create-tunnel {
+ rpc pcep-create-p2p-tunnel {
input {
- uses ttp:create-tunnel-input;
+ uses ttp:create-p2p-tunnel-input;
- leaf symbolic-path-name {
- type pcep:symbolic-path-name;
- mandatory true;
- }
-
- container endpoints {
- uses pcep:endpoints;
- }
-
- leaf signaling-type {
- // FIXME: dedicated type in PCEP
- type uint8;
- default 0;
- }
-
- leaf administrative {
- type boolean;
- default true;
- }
-
- // FIXME: ERO
- // FIXME: attribute-list
+ uses p2p:tunnel-p2p-path-cfg-attributes;
+ uses ptp:tunnel-pcep-link-cfg-attributes;
}
output {
- uses ttp:create-tunnel-output;
+ uses ttp:create-p2p-tunnel-output;
}
}
rpc pcep-update-tunnel {
input {
- container update-tunnel {
- leaf topology-id {
- type nt:topology-id;
- mandatory true;
- }
- leaf link-id {
- type nt:link-id;
- mandatory true;
- }
+ uses ttp:base-tunnel-input;
- // FIXME: all that PCUpd jazz
- }
+ uses p2p:tunnel-p2p-path-cfg-attributes;
+ uses ptp:tunnel-pcep-link-cfg-attributes;
}
output {
- uses pgm:submit-instruction-output;
+ uses ttp:base-tunnel-output;
}
}
}
namespace "urn:opendaylight:params:xml:ns:yang:topology:tunnel:pcep";
prefix "pceptun";
- import ieee754 { prefix ieee754; revision-date 2013-08-19; }
import network-topology { prefix nt; revision-date 2013-10-21; }
+ import nps-concepts { prefix nps-c; }
import pcep-types { prefix pcep; revision-date 2013-10-05; }
import rsvp { prefix rsvp; revision-date 2013-08-20; }
import topology-tunnel { prefix tt; revision-date 2013-08-19; }
reference "https://tools.ietf.org/html/draft-ietf-pce-stateful-pce-05#section-7.3";
}
+ grouping topology-tunnel-pcep-type {
+ container topology-tunnel-pcep {
+ presence "indicates a PCEP tunnel-aware topology";
+ }
+ }
+
+ augment "/nt:network-topology/nt:topology/nt:topology-types" {
+ uses topology-tunnel-pcep-type;
+ }
+
+ grouping tunnel-pcep-supporting-node-attributes {
+ container path-computation-client {
+ leaf controlling {
+ type boolean;
+ default false;
+ }
+ }
+ }
+
+ augment "/nt:network-topology/nt:topology/nt:node/nt:supporting-node" {
+ when "../../../nt:topology-types/topology-tunnel-pcep";
+
+ uses tunnel-pcep-supporting-node-attributes;
+ }
+
grouping tunnel-pcep-type {
container pcep-tunnel {
presence "indicates a link is a PCEP tunnel";
uses tunnel-pcep-type;
}
- grouping tunnel-pcep-link-attributes {
+ grouping tunnel-pcep-link-cfg-attributes {
leaf administrative-status {
type administrative-status;
}
- leaf operational-status {
- type pcep:operational-status;
- config false;
- }
-
leaf class-type {
type pcep:class-type;
}
leaf bandwidth {
- type ieee754:float32;
+ type nps-c:bandwidth;
+ }
+
+ leaf symbolic-path-name {
+ type pcep:symbolic-path-name;
+ }
+
+ uses rsvp:tunnel-attributes;
+ }
+
+ grouping tunnel-pcep-link-oper-attributes {
+ leaf operational-status {
+ type pcep:operational-status;
+ config false;
}
}
augment "/nt:network-topology/nt:topology/nt:link" {
when "../../tunnel-types/pcep-tunnel";
- uses tunnel-pcep-link-attributes;
+ uses tunnel-pcep-link-cfg-attributes;
+ uses tunnel-pcep-link-oper-attributes;
}
augment "/nt:network-topology/nt:topology/tt:paths" {
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>pcep-topology-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-topology-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
package org.opendaylight.bgpcep.pcep.tunnel.provider;
+import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.NetworkTopologyPcepService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// FIXME: migrate to config subsystem
final TunnelTopologyExporter tte = new TunnelTopologyExporter(dps, null);
tte.addTargetTopology(null);
+
+ final InstructionScheduler scheduler = null;
+ final TunnelProgramming tp = new TunnelProgramming(scheduler, dps, session.getRpcService(NetworkTopologyPcepService.class));
}
}
import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.SymbolicPathName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsps;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
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.topology.Link;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
LOG.error("Failed to propagate a topology change, target topology became inconsistent", e);
}
}
-}
\ No newline at end of file
+
+ public static InstanceIdentifier<Link> linkIdentifier(final InstanceIdentifier<Topology> topology,
+ final NodeId node, final SymbolicPathName name) {
+ return InstanceIdentifier.builder(topology).
+ node(Link.class, new LinkKey(new LinkId(node.getValue() + "/lsp/" + name))).toInstance();
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.bgpcep.pcep.tunnel.provider;
-
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.topology.pcep.type.TopologyPcep;
-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.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.TopologyTypes;
-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.Preconditions;
-
-public final class PCEPTunnelInstructionExecutor {
- private static final Logger LOG = LoggerFactory.getLogger(PCEPTunnelInstructionExecutor.class);
- private final InstanceIdentifier<Topology> underlay;
- private final InstanceIdentifier<Topology> target;
- private final DataProviderService dps;
-
- private PCEPTunnelInstructionExecutor(final DataProviderService dps, final InstanceIdentifier<Topology> underlay,
- final InstanceIdentifier<Topology> target, final TopologyId topologyId) {
- this.dps = Preconditions.checkNotNull(dps);
- this.underlay = Preconditions.checkNotNull(underlay);
- this.target = Preconditions.checkNotNull(target);
- }
-
- public static PCEPTunnelInstructionExecutor create(final DataProviderService dps, final InstanceIdentifier<Topology> underlay,
- final TopologyId targetId) {
- Preconditions.checkNotNull(dps);
- Preconditions.checkNotNull(targetId);
-
- // Topology pointer
- final InstanceIdentifier<Topology> target = InstanceIdentifier.builder().node(NetworkTopology.class).
- node(Topology.class, new TopologyKey(targetId)).toInstance();
-
- // Now check if there is a container identifying the topology as PCEP-aware
- final InstanceIdentifier<TopologyPcep> i = InstanceIdentifier.builder(target).node(TopologyTypes.class).node(TopologyPcep.class).toInstance();
- final DataObject ttt = dps.readOperationalData(i);
- Preconditions.checkArgument(ttt != null, "Specified topology does not list topology-pcep as its type");
-
- return new PCEPTunnelInstructionExecutor(dps, underlay, target, targetId);
- }
-}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.pcep.tunnel.provider;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.bgpcep.pcep.topology.spi.AbstractTopologyProgrammingExecutor;
+import org.opendaylight.bgpcep.programming.spi.InstructionExecutor;
+import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
+import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.bandwidth.object.BandwidthBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.classtype.object.ClassTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.EndpointsObjBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobjects;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lspa.object.LspaBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.FailureBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.failure.Failure;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.NetworkTopologyPcepService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.add.lsp.args.ArgumentsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.programming.rev131102.TopologyInstructionInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.p2p.rev130819.tunnel.p2p.path.cfg.attributes.ExplicitHops;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepCreateP2pTunnelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepCreateP2pTunnelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepCreateP2pTunnelOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepDestroyTunnelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepDestroyTunnelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepDestroyTunnelOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepUpdateTunnelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepUpdateTunnelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.PcepUpdateTunnelOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev131030.TopologyTunnelPcepProgrammingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.AdministrativeStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.ExplicitHops1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.Link1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.SupportingNode1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.programming.rev130930.BaseTunnelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.programming.rev130930.TpReference;
+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.NodeId;
+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.Link;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
+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.NodeKey;
+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.TerminationPointKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNode;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.TerminationPoint1;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.igp.termination.point.attributes.TerminationPointType;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.igp.termination.point.attributes.termination.point.type.Ip;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+final class TunnelProgramming implements TopologyTunnelPcepProgrammingService {
+ private static final Logger LOG = LoggerFactory.getLogger(TunnelProgramming.class);
+ private final NetworkTopologyPcepService topologyService;
+ private final DataProviderService dataProvider;
+ private final InstructionScheduler scheduler;
+
+ TunnelProgramming(final InstructionScheduler scheduler, final DataProviderService dataProvider,
+ final NetworkTopologyPcepService topologyService) {
+ this.scheduler = Preconditions.checkNotNull(scheduler);
+ this.dataProvider = Preconditions.checkNotNull(dataProvider);
+ this.topologyService = Preconditions.checkNotNull(topologyService);
+ }
+
+ private static final class TpReader {
+ private final DataModificationTransaction t;
+ private final InstanceIdentifier<Node> nii;
+ private final InstanceIdentifier<TerminationPoint> tii;
+
+ TpReader(final DataModificationTransaction t, final InstanceIdentifier<Topology> topo, final TpReference ref) {
+ this.t = Preconditions.checkNotNull(t);
+
+ nii = InstanceIdentifier.builder(topo).node(Node.class, new NodeKey(ref.getNode())).toInstance();
+ tii = InstanceIdentifier.builder(nii).node(TerminationPoint.class, new TerminationPointKey(ref.getTp())).toInstance();
+ }
+
+ private Node getNode() {
+ return (Node) t.readOperationalData(nii);
+ }
+
+ private TerminationPoint getTp() {
+ return (TerminationPoint) t.readOperationalData(tii);
+ }
+ }
+
+ private AddressFamily buildAddressFamily(final TerminationPoint sp, final TerminationPoint dp) {
+ // We need the IGP augmentation -- it has IP addresses
+ final TerminationPoint1 sp1 = Preconditions.checkNotNull(sp.getAugmentation(TerminationPoint1.class));
+ final TerminationPoint1 dp1 = Preconditions.checkNotNull(dp.getAugmentation(TerminationPoint1.class));
+
+ // Get the types
+ final TerminationPointType spt = sp1.getIgpTerminationPointAttributes().getTerminationPointType();
+ final TerminationPointType dpt = dp1.getIgpTerminationPointAttributes().getTerminationPointType();
+
+ // The types have to match
+ Preconditions.checkArgument(spt.getImplementedInterface().equals(dpt.getImplementedInterface()));
+
+ // And they have to actually be Ip
+ final Ip sips = (Ip) spt;
+ final Ip dips = (Ip) dpt;
+
+ /*
+ * Now a bit of magic. We need to find 'like' addresses, e.g. both
+ * IPv4 or both IPv6. We are in IPv6-enabled world now, so let's
+ * prefer that.
+ */
+ AddressFamily ret = findIpv6(sips.getIpAddress(), dips.getIpAddress());
+ if (ret == null) {
+ ret = findIpv4(sips.getIpAddress(), dips.getIpAddress());
+ }
+
+ // We need to have a ret now
+ Preconditions.checkArgument(ret != null, "Failed to find like Endpoint addresses");
+
+ return ret;
+ }
+
+ private AddressFamily findIpv4(final List<IpAddress> srcs, final List<IpAddress> dsts) {
+ for (final IpAddress sc : srcs) {
+ if (sc.getIpv4Address() != null) {
+ for (final IpAddress dc : dsts) {
+ if (dc.getIpv4Address() != null) {
+ return new Ipv4Builder().
+ setSourceIpv4Address(sc.getIpv4Address()).
+ setDestinationIpv4Address(dc.getIpv4Address()).build();
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private AddressFamily findIpv6(final List<IpAddress> srcs, final List<IpAddress> dsts) {
+ for (final IpAddress sc : srcs) {
+ if (sc.getIpv6Address() != null) {
+ for (final IpAddress dc : dsts) {
+ if (dc.getIpv6Address() != null) {
+ return new Ipv6Builder().
+ setSourceIpv6Address(sc.getIpv6Address()).
+ setDestinationIpv6Address(dc.getIpv6Address()).build();
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private NodeId supportingNode(final DataModificationTransaction t, final Node node) {
+ for (SupportingNode n : node.getSupportingNode()) {
+ final SupportingNode1 n1 = n.getAugmentation(SupportingNode1.class);
+ if (n1 != null && n1.getPathComputationClient().isControlling()) {
+ return n.getKey().getNodeRef();
+ }
+ }
+
+ return null;
+ }
+
+ private Ero buildEro(final List<ExplicitHops> explicitHops) {
+ final EroBuilder b = new EroBuilder();
+
+ if (!explicitHops.isEmpty()) {
+ final List<Subobjects> subobjs = new ArrayList<>(explicitHops.size());
+ for (ExplicitHops h : explicitHops) {
+
+ final ExplicitHops1 h1 = h.getAugmentation(ExplicitHops1.class);
+ if (h1 != null) {
+ final SubobjectsBuilder sb = new SubobjectsBuilder();
+ sb.fieldsFrom(h1);
+ sb.setLoose(h.isLoose());
+ subobjs.add(sb.build());
+ } else {
+ LOG.debug("Ignoring unhandled explicit hop {}", h);
+ }
+ }
+ b.setSubobjects(subobjs);
+ }
+ return b.build();
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<PcepCreateP2pTunnelOutput>> pcepCreateP2pTunnel(final PcepCreateP2pTunnelInput input) {
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
+ @Override
+ protected ListenableFuture<OperationResult> executeImpl() {
+ final InstanceIdentifier<Topology> tii = topologyIdentifier(input);
+
+ final DataModificationTransaction t = dataProvider.beginTransaction();
+
+
+ final TpReader dr = new TpReader(t, tii, input.getDestination());
+ final TpReader sr = new TpReader(t, tii, input.getSource());
+
+ final Node sn = Preconditions.checkNotNull(sr.getNode());
+ final TerminationPoint sp = Preconditions.checkNotNull(sr.getTp());
+ final TerminationPoint dp = Preconditions.checkNotNull(dr.getTp());
+
+ final AddLspInputBuilder ab = new AddLspInputBuilder();
+ ab.setNode(Preconditions.checkNotNull(supportingNode(t, sn)));
+ ab.setName(Preconditions.checkNotNull(input.getSymbolicPathName()));
+
+ // The link has to be non-existent
+ final InstanceIdentifier<Link> lii = NodeChangedListener.linkIdentifier(tii, ab.getNode(), ab.getName());
+ Preconditions.checkState(t.readOperationalData(lii) == null);
+
+ final ArgumentsBuilder args = new ArgumentsBuilder();
+ args.setAdministrative(input.getAdministrativeStatus() == AdministrativeStatus.Active);
+ args.setBandwidth(new BandwidthBuilder().setBandwidth(input.getBandwidth()).build());
+ args.setClassType(new ClassTypeBuilder().setClassType(input.getClassType()).build());
+ args.setEndpointsObj(new EndpointsObjBuilder().setAddressFamily(buildAddressFamily(sp, dp)).build());
+ args.setEro(buildEro(input.getExplicitHops()));
+ args.setLspa(new LspaBuilder(input).build());
+
+ ab.setArguments(args.build());
+
+ return Futures.transform(
+ (ListenableFuture<RpcResult<AddLspOutput>>) topologyService.addLsp(ab.build()),
+ new Function<RpcResult<AddLspOutput>, OperationResult>() {
+ @Override
+ public OperationResult apply(final RpcResult<AddLspOutput> input) {
+ return input.getResult();
+ }
+ });
+ }
+ };
+
+ final Failure f = this.scheduler.submitInstruction(input, e);
+ final PcepCreateP2pTunnelOutputBuilder b = new PcepCreateP2pTunnelOutputBuilder();
+ if (f != null) {
+ b.setResult(new FailureBuilder().setFailure(f).build());
+ }
+
+ final RpcResult<PcepCreateP2pTunnelOutput> res = SuccessfulRpcResult.create(b.build());
+ return Futures.immediateFuture(res);
+ }
+
+ // FIXME: topology programming utility class
+ private InstanceIdentifier<Topology> topologyIdentifier(final TopologyInstructionInput input) {
+ return InstanceIdentifier.builder().
+ node(NetworkTopology.class).node(Topology.class, new TopologyKey(input.getTopologyId())).toInstance();
+ }
+
+ // FIXME: tunnel programming utility class
+ private InstanceIdentifier<Link> linkIdentifier(final InstanceIdentifier<Topology> topology, final BaseTunnelInput input) {
+ return InstanceIdentifier.builder(topology).
+ node(Link.class, new LinkKey(Preconditions.checkNotNull(input.getLinkId()))).toInstance();
+ }
+
+ private Node sourceNode(final DataModificationTransaction t, final InstanceIdentifier<Topology> topology, final Link link) {
+ final InstanceIdentifier<Node> nii = InstanceIdentifier.builder(topology).
+ node(Node.class, new NodeKey(link.getSource().getSourceNode())).toInstance();
+ return (Node) t.readOperationalData(nii);
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<PcepDestroyTunnelOutput>> pcepDestroyTunnel(final PcepDestroyTunnelInput input) {
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
+ @Override
+ protected ListenableFuture<OperationResult> executeImpl() {
+ final InstanceIdentifier<Topology> tii = topologyIdentifier(input);
+ final InstanceIdentifier<Link> lii = linkIdentifier(tii, input);
+
+ final DataModificationTransaction t = dataProvider.beginTransaction();
+
+ // The link has to exist
+ final Link link = (Link) t.readOperationalData(lii);
+ Preconditions.checkState(link != null);
+
+ // The source node has to exist
+ final Node node = sourceNode(t, tii, link);
+ Preconditions.checkState(node != null);
+
+ final RemoveLspInputBuilder ab = new RemoveLspInputBuilder();
+ ab.setName(link.getAugmentation(Link1.class).getSymbolicPathName());
+ ab.setNode(node.getSupportingNode().get(0).getKey().getNodeRef());
+
+ return Futures.transform(
+ (ListenableFuture<RpcResult<RemoveLspOutput>>) topologyService.removeLsp(ab.build()),
+ new Function<RpcResult<RemoveLspOutput>, OperationResult>() {
+ @Override
+ public OperationResult apply(final RpcResult<RemoveLspOutput> input) {
+ return input.getResult();
+ }
+ });
+ }
+ };
+
+ final Failure f = this.scheduler.submitInstruction(input, e);
+ final PcepDestroyTunnelOutputBuilder b = new PcepDestroyTunnelOutputBuilder();
+ if (f != null) {
+ b.setResult(new FailureBuilder().setFailure(f).build());
+ }
+
+ final RpcResult<PcepDestroyTunnelOutput> res = SuccessfulRpcResult.create(b.build());
+ return Futures.immediateFuture(res);
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<PcepUpdateTunnelOutput>> pcepUpdateTunnel(final PcepUpdateTunnelInput input) {
+ final InstructionExecutor e = new AbstractTopologyProgrammingExecutor() {
+ @Override
+ protected ListenableFuture<OperationResult> executeImpl() {
+ final InstanceIdentifier<Topology> tii = topologyIdentifier(input);
+ final InstanceIdentifier<Link> lii = linkIdentifier(tii, input);
+
+ final DataModificationTransaction t = dataProvider.beginTransaction();
+
+ // The link has to exist
+ final Link link = (Link) t.readOperationalData(lii);
+ Preconditions.checkState(link != null);
+
+ // The source node has to exist
+ final Node node = sourceNode(t, tii, link);
+ Preconditions.checkState(node != null);
+
+ final UpdateLspInputBuilder ab = new UpdateLspInputBuilder();
+ ab.setName(link.getAugmentation(Link1.class).getSymbolicPathName());
+ ab.setNode(Preconditions.checkNotNull(supportingNode(t, node)));
+
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.update.lsp.args.ArgumentsBuilder args =
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.update.lsp.args.ArgumentsBuilder();
+
+ args.setAdministrative(input.getAdministrativeStatus() == AdministrativeStatus.Active);
+ args.setBandwidth(new BandwidthBuilder().setBandwidth(input.getBandwidth()).build());
+ args.setClassType(new ClassTypeBuilder().setClassType(input.getClassType()).build());
+ args.setEro(buildEro(input.getExplicitHops()));
+ args.setLspa(new LspaBuilder(input).build());
+
+ ab.setArguments(args.build());
+
+ return Futures.transform(
+ (ListenableFuture<RpcResult<UpdateLspOutput>>) topologyService.updateLsp(ab.build()),
+ new Function<RpcResult<UpdateLspOutput>, OperationResult>() {
+ @Override
+ public OperationResult apply(final RpcResult<UpdateLspOutput> input) {
+ return input.getResult();
+ }
+ });
+ }
+ };
+
+ final Failure f = this.scheduler.submitInstruction(input, e);
+ final PcepUpdateTunnelOutputBuilder b = new PcepUpdateTunnelOutputBuilder();
+ if (f != null) {
+ b.setResult(new FailureBuilder().setFailure(f).build());
+ }
+
+ final RpcResult<PcepUpdateTunnelOutput> res = SuccessfulRpcResult.create(b.build());
+ return Futures.immediateFuture(res);
+ }
+}
package org.opendaylight.bgpcep.programming.impl;
import io.netty.util.Timeout;
-import io.netty.util.concurrent.Future;
import java.util.ArrayList;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
final class Instruction {
private final List<Instruction> dependants = new ArrayList<>();
return status;
}
- Future<ExecutionResult<Details>> execute() {
+ ListenableFuture<ExecutionResult<Details>> execute() {
return executor.execute();
}
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.TimerTask;
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.FutureListener;
import java.math.BigInteger;
import java.util.ArrayDeque;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
final class ProgrammingServiceImpl implements InstructionScheduler, ProgrammingService {
private static final Logger LOG = LoggerFactory.getLogger(ProgrammingServiceImpl.class);
Preconditions.checkState(i.getStatus().equals(InstructionStatus.Scheduled));
transitionInstruction(i, InstructionStatus.Executing, null);
- final Future<ExecutionResult<Details>> f = i.execute();
- f.addListener(new FutureListener<ExecutionResult<?>>() {
+ Futures.addCallback(i.execute(), new FutureCallback<ExecutionResult<Details>>() {
+
+ @Override
+ public void onSuccess(final ExecutionResult<Details> result) {
+ executionSuccessful(i, result);
+ }
+
@Override
- public void operationComplete(final Future<ExecutionResult<?>> future) {
- if (future.isSuccess()) {
- executionSuccessful(i, future.getNow());
- } else {
- executionFailed(i, future.cause());
- }
+ public void onFailure(final Throwable t) {
+ executionFailed(i, t);
}
});
}
*/
package org.opendaylight.bgpcep.programming.spi;
-import io.netty.util.concurrent.Future;
-
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
+import com.google.common.util.concurrent.ListenableFuture;
+
public interface InstructionExecutor {
- Future<ExecutionResult<Details>> execute();
+ ListenableFuture<ExecutionResult<Details>> execute();
}
reference "";
}
- grouping create-tunnel-input {
+ grouping base-tunnel-input {
uses tp:topology-instruction-input;
leaf link-id {
}
}
- grouping create-tunnel-output {
+ grouping base-tunnel-output {
uses tp:topology-instruction-output;
}
- grouping destroy-tunnel-input {
+ grouping create-tunnel-input {
uses tp:topology-instruction-input;
+ }
+
+ grouping create-tunnel-output {
+ uses base-tunnel-output;
leaf link-id {
type nt:link-id;
}
}
+ grouping destroy-tunnel-input {
+ uses base-tunnel-input;
+ }
+
grouping destroy-tunnel-output {
- uses tp:topology-instruction-output;
+ uses base-tunnel-output;
+ }
+
+ grouping tp-reference {
+ leaf node {
+ type nt:node-ref;
+ mandatory true;
+ }
+ leaf tp {
+ type nt:tp-ref;
+ mandatory true;
+ }
+ }
+
+ grouping create-p2p-tunnel-input {
+ uses create-tunnel-input;
+
+ container destination {
+ uses tp-reference;
+ }
+ container source {
+ uses tp-reference;
+ }
+ }
+
+ grouping create-p2p-tunnel-output {
+ uses create-tunnel-output;
}
}
}
}
+ grouping tunnel-attributes {
+ leaf hold-priority {
+ type uint8;
+ mandatory true;
+ }
+
+ leaf setup-priority {
+ type uint8;
+ mandatory true;
+ }
+
+ leaf local-protection-desired {
+ type boolean;
+ default false;
+ }
+
+ uses attribute-filters;
+ }
+
typedef lsp-id {
type uint32;
reference "https://tools.ietf.org/html/rfc3209#section-4.6.2.1";
<modules>
<module>api</module>
- <module>provider-bgp</module>
<module>tunnel-api</module>
<module>segment-routing</module>
</modules>
}
}
- grouping tunnel-p2p-path-attributes {
+ grouping tunnel-p2p-path-cfg-attributes {
list explicit-hops {
uses tunnel-p2p-path-hops;
key order;
mandatory true;
}
}
+ }
+ grouping tunnel-p2p-path-oper-attributes {
list reported-hops {
+ config false;
uses tunnel-p2p-path-hops;
key order;
}
augment "/nt:network-topology/nt:topology/tt:paths" {
when "../path-types/p2p-tunnel";
- uses tunnel-p2p-path-attributes;
+ uses tunnel-p2p-path-cfg-attributes;
+ uses tunnel-p2p-path-oper-attributes;
}
}