<module>rib-impl</module>
<module>testtool</module>
<module>rib-mock</module>
+ <module>topology-provider</module>
<module>util</module>
</modules>
</project>
<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);
}
<modules>
<module>api</module>
- <module>provider-bgp</module>
<module>tunnel-api</module>
<module>segment-routing</module>
</modules>