<module>parser-impl</module>
<module>parser-mock</module>
<module>rib-api</module>
+ <module>rib-spi</module>
<module>rib-impl</module>
<module>testtool</module>
<module>rib-mock</module>
}
grouping route {
- container next-hop {
- uses bgp-t:next-hop;
- }
-
container attributes {
uses bgp-msg:path-attributes;
}
when "../../afi = ipv6";
leaf prefix {
- type inet:ipv4-prefix;
+ type inet:ipv6-prefix;
}
key prefix;
uses route;
}
- case link-state {
- list link-state-links {
+ case linkstate-routes {
+ list linkstate-links {
// FIXME: fill this out
uses route;
}
- list link-state-nodes {
+ list linkstate-nodes {
// FIXME: fill this out
uses route;
}
- list link-state-ipv4-prefixes {
+ list linkstate-ipv4-prefixes {
// FIXME: fill this out
uses route;
}
- list link-state-ipv6-prefixes {
+ list linkstate-ipv6-prefixes {
// FIXME: fill this out
uses route;
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>bgp-rib-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-rib-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
- </dependency>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
--- /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.protocol.bgp.rib.impl;
+
+import java.util.Comparator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModification;
+import org.opendaylight.protocol.bgp.rib.spi.AbstractAdjRIBsIn;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInFactory;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInFactoryRegistry;
+import org.opendaylight.protocol.bgp.rib.spi.Peer;
+import org.opendaylight.protocol.concepts.AbstractRegistration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.linkstate.destination.Linkstate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.PathAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpReachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpUnreachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.loc.rib.tables.routes.ipv4.routes.Ipv4Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.loc.rib.tables.routes.ipv4.routes.Ipv4RoutesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.loc.rib.tables.routes.ipv6.routes.Ipv6Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.loc.rib.tables.routes.ipv6.routes.Ipv6RoutesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv6AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+
+public final class AdjRIBsInFactoryRegistryImpl implements AdjRIBsInFactoryRegistry {
+ public static final AdjRIBsInFactoryRegistry INSTANCE;
+
+ private final Map<TablesKey, AdjRIBsInFactory> factories = new ConcurrentHashMap<>();
+
+ private static final class Ipv4AdjRIBsIn extends AbstractAdjRIBsIn<Ipv4Prefix, DataObject> {
+ private Ipv4AdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
+ super(comparator, key);
+ }
+
+ @Override
+ public InstanceIdentifier identifierForKey(final InstanceIdentifier basePath,
+ final Ipv4Prefix key) {
+ final InstanceIdentifierBuilder builder = InstanceIdentifier.builder(basePath);
+
+ builder.node(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.loc.rib.tables.routes.Ipv4Routes.class);
+ builder.node(Ipv4Routes.class, new Ipv4RoutesKey(key));
+
+ return builder.toInstance();
+ }
+
+ @Override
+ public void addRoutes(
+ final DataModification trans,
+ final Peer peer,
+ final MpReachNlri nlri,
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributes attributes) {
+ final RIBEntryData data = new RIBEntryData(attributes) {
+ @Override
+ protected DataObject getDataObject() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+
+ for (Ipv4Prefix id : ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.mp.unreach.nlri.withdrawn.routes.nlri.Ipv4)nlri.getAdvertizedRoutes().getNlri()).getIpv4Prefixes()) {
+ super.add(trans, peer, id, data);
+ }
+ }
+
+ @Override
+ public void removeRoutes(final DataModification trans, final Peer peer,
+ final MpUnreachNlri nlri) {
+ for (Ipv4Prefix id : ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.mp.unreach.nlri.withdrawn.routes.nlri.Ipv4)nlri.getWithdrawnRoutes().getNlri()).getIpv4Prefixes()) {
+ super.remove(trans, peer, id);
+ }
+ }
+ }
+
+ private static final class Ipv6AdjRIBsIn extends AbstractAdjRIBsIn<Ipv6Prefix, DataObject> {
+ Ipv6AdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
+ super(comparator, key);
+ }
+
+ @Override
+ public InstanceIdentifier identifierForKey(final InstanceIdentifier basePath,
+ final Ipv6Prefix key) {
+ final InstanceIdentifierBuilder builder = InstanceIdentifier.builder(basePath);
+
+ builder.node(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.loc.rib.tables.routes.Ipv6Routes.class);
+ builder.node(Ipv6Routes.class, new Ipv6RoutesKey(key));
+
+ return builder.toInstance();
+ }
+
+ @Override
+ public void addRoutes(
+ final DataModification trans,
+ final Peer peer,
+ final MpReachNlri nlri,
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributes attributes) {
+ final RIBEntryData data = new RIBEntryData(attributes) {
+ @Override
+ protected DataObject getDataObject() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+
+ for (Ipv6Prefix id : ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.mp.reach.nlri.advertized.routes.nlri.Ipv6)nlri.getAdvertizedRoutes().getNlri()).getIpv6Prefixes()) {
+ super.add(trans, peer, id, data);
+ }
+ }
+
+ @Override
+ public void removeRoutes(final DataModification trans, final Peer peer,
+ final MpUnreachNlri nlri) {
+ for (Ipv6Prefix id : ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.mp.unreach.nlri.withdrawn.routes.nlri.Ipv6)nlri.getWithdrawnRoutes().getNlri()).getIpv6Prefixes()) {
+ super.remove(trans, peer, id);
+ }
+ }
+ }
+
+ private static final class LinkstateAdjRIBsIn extends AbstractAdjRIBsIn<Linkstate, DataObject> {
+ LinkstateAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
+ super(comparator, key);
+ }
+
+ @Override
+ public InstanceIdentifier identifierForKey(final InstanceIdentifier basePath,
+ final Linkstate key) {
+ final InstanceIdentifierBuilder builder = InstanceIdentifier.builder(basePath);
+
+ switch (key.getNlriType()) {
+ case Ipv4Prefix:
+ // FIXME: finish this
+ return builder.toInstance();
+ case Ipv6Prefix:
+ // FIXME: finish this
+ return builder.toInstance();
+ case Link:
+ // FIXME: finish this
+ return builder.toInstance();
+ case Node:
+ // FIXME: finish this
+ return builder.toInstance();
+ }
+
+ throw new IllegalStateException("Unhandled link-state NLRI type " + key.getNlriType());
+ }
+
+ @Override
+ public void addRoutes(
+ final DataModification trans,
+ final Peer peer,
+ final MpReachNlri nlri,
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributes attributes) {
+ final Linkstate key =
+ ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.
+ update.path.attributes.mp.reach.nlri.advertized.routes.nlri.Linkstate) nlri.getAdvertizedRoutes().getNlri()).getLinkstate();
+
+ RIBEntryData data = null;
+ switch (key.getNlriType()) {
+ case Ipv4Prefix:
+ data = new RIBEntryData(attributes) {
+ @Override
+ protected DataObject getDataObject() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+ break;
+ case Ipv6Prefix:
+ data = new RIBEntryData(attributes) {
+ @Override
+ protected DataObject getDataObject() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+ break;
+ case Link:
+ data = new RIBEntryData(attributes) {
+ @Override
+ protected DataObject getDataObject() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+ break;
+ case Node:
+ data = new RIBEntryData(attributes) {
+ @Override
+ protected DataObject getDataObject() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+ break;
+ }
+
+ if (data == null) {
+ throw new IllegalStateException("Unhandled link-state NLRI type " + key.getNlriType());
+ }
+ super.add(trans, peer, key, data);
+ }
+
+ @Override
+ public void removeRoutes(final DataModification trans, final Peer peer,
+ final MpUnreachNlri nlri) {
+ final Linkstate key =
+ ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.
+ update.path.attributes.mp.unreach.nlri.withdrawn.routes.nlri.Linkstate) nlri.getWithdrawnRoutes().getNlri()).getLinkstate();
+
+ super.remove(trans, peer, key);
+ }
+ }
+
+ static {
+ final AdjRIBsInFactoryRegistry reg = new AdjRIBsInFactoryRegistryImpl();
+
+ reg.registerAdjRIBsInFactory(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class,
+ new AdjRIBsInFactory() {
+ @Override
+ public AdjRIBsIn createAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
+ return new Ipv4AdjRIBsIn(comparator, key);
+ }
+ });
+ reg.registerAdjRIBsInFactory(Ipv6AddressFamily.class, UnicastSubsequentAddressFamily.class,
+ new AdjRIBsInFactory() {
+ @Override
+ public AdjRIBsIn createAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
+ return new Ipv6AdjRIBsIn(comparator, key);
+ }
+ });
+ reg.registerAdjRIBsInFactory(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class,
+ new AdjRIBsInFactory() {
+ @Override
+ public AdjRIBsIn createAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
+ return new LinkstateAdjRIBsIn(comparator, key);
+ }
+ });
+
+ INSTANCE = reg;
+ }
+
+ private AdjRIBsInFactoryRegistryImpl() {
+
+ }
+
+ @Override
+ public synchronized AutoCloseable registerAdjRIBsInFactory(final Class<? extends AddressFamily> afi,
+ final Class<? extends SubsequentAddressFamily> safi, final AdjRIBsInFactory factory) {
+ final TablesKey key = new TablesKey(afi, safi);
+
+ if (factories.containsKey(key)) {
+ throw new RuntimeException("Specified AFI/SAFI combination is already registered");
+ }
+
+ factories.put(key, factory);
+
+ final Object lock = this;
+ return new AbstractRegistration() {
+ @Override
+ protected void removeRegistration() {
+ synchronized (lock) {
+ factories.remove(key);
+ }
+ }
+ };
+ }
+
+ @Override
+ public synchronized AdjRIBsInFactory getAdjRIBsInFactory(final Class<? extends AddressFamily> afi, final Class<? extends SubsequentAddressFamily> safi) {
+ return factories.get(new TablesKey(afi, safi));
+ }
+}
import java.util.Comparator;
-import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.PathAttributes;
/**
*
* @param <T> Actual object state reference
*/
-final class BGPObjectComparator<T extends AbstractBGPObjectState<?>> implements Comparator<T> {
+final class BGPObjectComparator implements Comparator<PathAttributes> {
@Override
- public int compare(final T o1, final T o2) {
- if (o1 == o2)
+ public int compare(final PathAttributes o1, final PathAttributes o2) {
+ if (o1 == o2) {
return 0;
- if (o1 == null)
+ }
+ if (o1 == null) {
return 1;
- if (o2 == null)
+ }
+ if (o2 == null) {
return -1;
+ }
// FIXME: look at ASPath
// FIXME: look at everything else :-)
import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
import org.opendaylight.protocol.bgp.parser.BGPTableType;
import org.opendaylight.protocol.bgp.parser.BGPTerminationReason;
-import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.rib.spi.Peer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* Class representing a peer. We have a single instance for each peer, which provides translation from BGP events into
* RIB actions.
*/
-public final class BGPPeer implements BGPSessionListener {
+public final class BGPPeer implements BGPSessionListener, Peer {
private static final Logger logger = LoggerFactory.getLogger(BGPPeer.class);
- private Set<BGPTableType> tables;
+ private Set<TablesKey> tables;
private final String name;
private final RIBImpl rib;
@Override
public void onMessage(final BGPSession session, final Notification message) {
- if (message instanceof BGPUpdateMessage) {
- final BGPUpdateMessage m = (BGPUpdateMessage) message;
- this.rib.updateTables(this, m.getAddedObjects(), m.getRemovedObjects());
+ if (message instanceof Update) {
+ this.rib.updateTables(this, (Update)message);
} else {
logger.info("Ignoring unhandled message class " + message.getClass());
}
@Override
public void onSessionUp(final BGPSession session) {
logger.info("Session with peer {} went up with tables: {}", this.name, session.getAdvertisedTableTypes());
+
+ for (BGPTableType t : session.getAdvertisedTableTypes()) {
+ tables.add(new TablesKey(t.getAddressFamily(), t.getSubsequentAddressFamily()));
+ }
}
@Override
public void onSessionDown(final BGPSession session, final Exception e) {
// FIXME: support graceful restart
- for (final BGPTableType t : this.tables) {
- this.rib.clearTable(this, t);
+ for (final TablesKey key : this.tables) {
+ this.rib.clearTable(this, key);
}
+
+ tables.clear();
}
@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.protocol.bgp.rib.impl;
-
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
-
-import org.opendaylight.protocol.concepts.Identifier;
-import org.opendaylight.protocol.concepts.NamedObject;
-import com.google.common.base.Preconditions;
-
-/**
- * A single RIB table entry, which holds multiple versions of the entry's state and elects the authoritative based on
- * ordering specified by the supplied comparator.
- *
- * @param <ID> Identifier type
- * @param <STATE> State type
- */
-@ThreadSafe
-final class RIBEntry<ID extends Identifier, STATE extends AbstractBGPObjectState<?>> implements NamedObject<ID> {
- /*
- * TODO: we could dramatically optimize performance by using the comparator
- * to retain the candidate states ordered -- thus selection would occur
- * automatically through insertion, without the need of a second walk.
- */
- private final Map<BGPPeer, STATE> candidates = new HashMap<>();
- private final Comparator<STATE> comparator;
- private STATE currentState = null;
- private final ID name;
-
- RIBEntry(final ID name, final Comparator<STATE> comparator) {
- this.name = Preconditions.checkNotNull(name);
- this.comparator = Preconditions.checkNotNull(comparator);
- }
-
- @Override
- public ID getName() {
- return this.name;
- }
-
- private STATE findCandidate(final STATE initial) {
- STATE newState = initial;
- for (final STATE s : this.candidates.values())
- if (this.comparator.compare(newState, s) > 0)
- newState = s;
-
- return newState;
- }
-
- private void electCandidate(final Map<ID, STATE> transaction, final STATE candidate) {
- if (this.currentState == null || !this.currentState.equals(candidate)) {
- transaction.put(this.name, candidate);
- this.currentState = candidate;
- }
- }
-
- synchronized boolean removeState(final Map<ID, STATE> transaction, final BGPPeer peer) {
- this.candidates.remove(peer);
-
- final STATE candidate = findCandidate(null);
- if (candidate != null) {
- electCandidate(transaction, candidate);
- return true;
- } else
- return false;
- }
-
- synchronized void setState(final Map<ID, STATE> transaction, final BGPPeer peer, final STATE state) {
- this.candidates.put(peer, state);
- electCandidate(transaction, findCandidate(state));
- }
-
- synchronized STATE getState() {
- return this.currentState;
- }
-}
*/
package org.opendaylight.protocol.bgp.rib.impl;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
+import java.util.concurrent.Future;
import javax.annotation.concurrent.ThreadSafe;
-import org.opendaylight.protocol.bgp.concepts.BGPObject;
-import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
-import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
-import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
-import org.opendaylight.protocol.bgp.parser.BGPLink;
-import org.opendaylight.protocol.bgp.parser.BGPLinkState;
-import org.opendaylight.protocol.bgp.parser.BGPNode;
-import org.opendaylight.protocol.bgp.parser.BGPNodeState;
-import org.opendaylight.protocol.bgp.parser.BGPPrefix;
-import org.opendaylight.protocol.bgp.parser.BGPPrefixState;
-import org.opendaylight.protocol.bgp.parser.BGPRoute;
-import org.opendaylight.protocol.bgp.parser.BGPRouteState;
-import org.opendaylight.protocol.bgp.parser.BGPTableType;
-import org.opendaylight.protocol.concepts.Prefix;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateAddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv6AddressFamily;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.data.DataModification;
+import org.opendaylight.controller.sal.binding.api.data.DataModification.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpReachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpUnreachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
@ThreadSafe
public final class RIBImpl {
- private final RIBTable<LinkIdentifier, BGPLinkState> links = new RIBTable<>();
- private final RIBTable<NodeIdentifier, BGPNodeState> nodes = new RIBTable<>();
- private final RIBTable<PrefixIdentifier<?>, BGPPrefixState> prefixes = new RIBTable<>();
- private final RIBTable<Prefix<?>, BGPRouteState> routes = new RIBTable<>();
+ private static final Logger logger = LoggerFactory.getLogger(RIBImpl.class);
+ private final DataProviderService dps;
+ private final RIBTables tables;
private final String name;
- public RIBImpl(final String name) {
+ public RIBImpl(final String name, final ProviderContext context) {
this.name = Preconditions.checkNotNull(name);
+ this.dps = context.getSALService(DataProviderService.class);
+ this.tables = new RIBTables(new BGPObjectComparator(), AdjRIBsInFactoryRegistryImpl.INSTANCE);
}
- synchronized void updateTables(final BGPPeer peer, final Set<BGPObject> addedObjects, final Set<?> removedObjects) {
- final Map<LinkIdentifier, BGPLinkState> l = new HashMap<>();
- final Map<NodeIdentifier, BGPNodeState> n = new HashMap<>();
- final Map<PrefixIdentifier<?>, BGPPrefixState> p = new HashMap<>();
- final Map<Prefix<?>, BGPRouteState> r = new HashMap<>();
-
- for (final Object id : removedObjects) {
- if (id instanceof Prefix<?>) {
- this.routes.remove(r, peer, (Prefix<?>) id);
- } else if (id instanceof LinkIdentifier) {
- this.links.remove(l, peer, (LinkIdentifier) id);
- } else if (id instanceof NodeIdentifier) {
- this.nodes.remove(n, peer, (NodeIdentifier) id);
- } else if (id instanceof PrefixIdentifier<?>) {
- this.prefixes.remove(p, peer, (PrefixIdentifier<?>) id);
+ synchronized void updateTables(final BGPPeer peer, final Update message) {
+ final DataModification trans = dps.beginTransaction();
+
+ //remove(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class,
+ // trans, peer, message.getWithdrawnRoutes().getWithdrawnRoutes().iterator());
+
+ final PathAttributes attrs = message.getPathAttributes();
+ final PathAttributes2 mpu = attrs.getAugmentation(PathAttributes2.class);
+ if (mpu != null) {
+ final MpUnreachNlri nlri = mpu.getMpUnreachNlri();
+
+ AdjRIBsIn ari = tables.getOrCreate(new TablesKey(nlri.getAfi(), nlri.getSafi()));
+ if (ari != null) {
+ ari.removeRoutes(trans, peer, nlri);
} else {
- throw new IllegalArgumentException("Unsupported identifier " + id.getClass());
+ logger.debug("Not removing objects from unhandled NLRI {}", nlri);
}
}
- for (final BGPObject o : addedObjects) {
- if (o instanceof BGPLink) {
- final BGPLink link = (BGPLink) o;
- this.links.add(l, peer, link.getLinkIdentifier(), link.currentState());
- } else if (o instanceof BGPNode) {
- final BGPNode node = (BGPNode) o;
- this.nodes.add(n, peer, node.getNodeIdentifier(), node.currentState());
- } else if (o instanceof BGPPrefix<?>) {
- final BGPPrefix<?> prefix = (BGPPrefix<?>) o;
- this.prefixes.add(p, peer, prefix.getPrefixIdentifier(), prefix.currentState());
- } else if (o instanceof BGPRoute) {
- final BGPRoute route = (BGPRoute) o;
- this.routes.add(r, peer, route.getName(), route.currentState());
+ //add(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class,
+ // trans, peer, message.getNlri().getNlri().iterator(), attrs);
+
+ final PathAttributes1 mpr = message.getPathAttributes().getAugmentation(PathAttributes1.class);
+ if (mpr != null) {
+ final MpReachNlri nlri = mpr.getMpReachNlri();
+
+ final AdjRIBsIn ari = tables.getOrCreate(new TablesKey(nlri.getAfi(), nlri.getSafi()));
+ if (ari != null) {
+ ari.addRoutes(trans, peer, nlri, attrs);
} else {
- throw new IllegalArgumentException("Unsupported identifier " + o.getClass());
+ logger.debug("Not adding objects from unhandled NLRI {}", nlri);
}
}
- // FIXME: push into MD SAL
+ // FIXME: we need to attach to this future for failures
+ Future<RpcResult<TransactionStatus>> f = trans.commit();
}
- synchronized void clearTable(final BGPPeer peer, final BGPTableType t) {
- if (Ipv4AddressFamily.class == t.getAddressFamily() || Ipv6AddressFamily.class == t.getAddressFamily()) {
- this.routes.clear(peer);
- } else if (LinkstateAddressFamily.class == t.getAddressFamily()) {
- this.links.clear(peer);
- this.nodes.clear(peer);
- this.prefixes.clear(peer);
+ synchronized void clearTable(final BGPPeer peer, final TablesKey key) {
+ final AdjRIBsIn ari = tables.get(key);
+ if (ari != null) {
+ final DataModification trans = dps.beginTransaction();
+ ari.clear(trans, peer);
+
+ // FIXME: we need to attach to this future for failures
+ Future<RpcResult<TransactionStatus>> f = trans.commit();
}
}
+++ /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.protocol.bgp.rib.impl;
-
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
-
-import org.opendaylight.protocol.concepts.Identifier;
-
-@ThreadSafe
-class RIBTable<ID extends Identifier, STATE extends AbstractBGPObjectState<?>> {
- private final Comparator<STATE> comparator = new BGPObjectComparator<>();
- private final Map<ID, RIBEntry<ID, STATE>> entries = new HashMap<>();
-
- RIBTable() {
- }
-
- synchronized void add(final Map<ID, STATE> transaction, final BGPPeer peer, final ID id, final STATE state) {
- RIBEntry<ID, STATE> e = this.entries.get(id);
- if (e == null) {
- e = new RIBEntry<ID, STATE>(id, this.comparator);
- this.entries.put(id, e);
- }
-
- e.setState(transaction, peer, state);
- }
-
- synchronized Map<ID, STATE> clear(final BGPPeer peer) {
- final Map<ID, STATE> transaction = new HashMap<>();
-
- final Iterator<Map.Entry<ID, RIBEntry<ID, STATE>>> i = this.entries.entrySet().iterator();
- while (i.hasNext()) {
- final Map.Entry<ID, RIBEntry<ID, STATE>> e = i.next();
-
- if (e.getValue().removeState(transaction, peer))
- i.remove();
- }
-
- return transaction;
- }
-
- synchronized void remove(final Map<ID, STATE> transaction, final BGPPeer peer, final ID id) {
- final RIBEntry<ID, STATE> e = this.entries.get(id);
- if (e != null && e.removeState(transaction, peer))
- this.entries.remove(id);
- }
-
- synchronized Map<ID, STATE> currentState() {
- final Map<ID, STATE> ret = new HashMap<>();
-
- for (final Entry<ID, RIBEntry<ID, STATE>> e : this.entries.entrySet())
- ret.put(e.getKey(), e.getValue().getState());
-
- return ret;
- }
-}
--- /dev/null
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInFactoryRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.PathAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+
+final class RIBTables {
+ private final Map<TablesKey, AdjRIBsIn> tables = new HashMap<>();
+ private final Comparator<PathAttributes> comparator;
+ private final AdjRIBsInFactoryRegistry registry;
+
+ RIBTables(final Comparator<PathAttributes> comparator, final AdjRIBsInFactoryRegistry registry) {
+ this.comparator = comparator;
+ this.registry = registry;
+ }
+
+ public synchronized AdjRIBsIn get(final TablesKey key) {
+ return tables.get(key);
+ }
+
+ public synchronized AdjRIBsIn getOrCreate(final TablesKey key) {
+ final AdjRIBsIn table;
+
+ if (!tables.containsKey(key)) {
+ table = registry.getAdjRIBsInFactory(key.getAfi(), key.getSafi()).createAdjRIBsIn(comparator, key);
+ tables.put(key, table);
+ } else {
+ table = tables.get(key);
+ }
+
+ return table;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-rib-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>bgp-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-rib-spi</artifactId>
+ <description>BGP RIB SPI</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-rib-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </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>
+ <Import-Package>
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.rib.spi
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-RIB-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.protocol.bgp.rib.spi;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.PathAttributes;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+@ThreadSafe
+public abstract class AbstractAdjRIBsIn<ID, DATA extends DataObject> implements AdjRIBsIn {
+ protected abstract class RIBEntryData {
+ final PathAttributes attributes;
+
+ protected RIBEntryData(final PathAttributes attributes) {
+ this.attributes = Preconditions.checkNotNull(attributes);
+ }
+
+ protected abstract DATA getDataObject();
+ }
+
+ /**
+ * A single RIB table entry, which holds multiple versions of the entry's state and elects the authoritative based on
+ * ordering specified by the supplied comparator.
+ *
+ */
+ private final class RIBEntry {
+ /*
+ * TODO: we could dramatically optimize performance by using the comparator
+ * to retain the candidate states ordered -- thus selection would occur
+ * automatically through insertion, without the need of a second walk.
+ */
+ private final Map<Peer, RIBEntryData> candidates = new HashMap<>();
+ private final InstanceIdentifier name;
+
+ @GuardedBy("this")
+ private RIBEntryData currentState = null;
+
+ RIBEntry(final InstanceIdentifier name) {
+ this.name = Preconditions.checkNotNull(name);
+ }
+
+ private RIBEntryData findCandidate(final RIBEntryData initial) {
+ RIBEntryData newState = initial;
+ for (final RIBEntryData s : this.candidates.values()) {
+ if (newState == null || comparator.compare(newState.attributes, s.attributes) > 0) {
+ newState = s;
+ }
+ }
+
+ return newState;
+ }
+
+ private void electCandidate(final DataModification transaction, final RIBEntryData candidate) {
+ if (this.currentState == null || !this.currentState.equals(candidate)) {
+ transaction.putRuntimeData(name, candidate.getDataObject());
+ this.currentState = candidate;
+ }
+ }
+
+ synchronized boolean removeState(final DataModification transaction, final Peer peer) {
+ this.candidates.remove(peer);
+
+ final RIBEntryData candidate = findCandidate(null);
+ if (candidate != null) {
+ electCandidate(transaction, candidate);
+ return true;
+ } else {
+ transaction.removeRuntimeData(name);
+ return false;
+ }
+ }
+
+ synchronized void setState(final DataModification transaction, final Peer peer, final RIBEntryData state) {
+ this.candidates.put(peer, state);
+ electCandidate(transaction, findCandidate(state));
+ }
+ }
+
+ private final Comparator<PathAttributes> comparator;
+ private final InstanceIdentifier basePath;
+ @GuardedBy("this")
+ private final Map<ID, RIBEntry> entries = new HashMap<>();
+
+ protected AbstractAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
+ this.comparator = Preconditions.checkNotNull(comparator);
+ basePath = InstanceIdentifier.builder().node(LocRib.class).node(Tables.class, key).toInstance();
+ }
+
+ @Override
+ public synchronized void clear(final DataModification trans, final Peer peer) {
+ final Iterator<Map.Entry<ID, RIBEntry>> i = this.entries.entrySet().iterator();
+ while (i.hasNext()) {
+ final Map.Entry<ID, RIBEntry> e = i.next();
+
+ if (e.getValue().removeState(trans, peer)) {
+ i.remove();
+ }
+ }
+ }
+
+ protected abstract InstanceIdentifier identifierForKey(final InstanceIdentifier basePath, final ID id);
+
+ protected synchronized void add(final DataModification trans, final Peer peer, final ID id, final RIBEntryData data) {
+ RIBEntry e = this.entries.get(id);
+ if (e == null) {
+ e = new RIBEntry(identifierForKey(basePath, id));
+ this.entries.put(id, e);
+ }
+
+ e.setState(trans, peer, data);
+ }
+
+ protected synchronized void remove(final DataModification trans, final Peer peer, final ID id) {
+ final RIBEntry e = this.entries.get(id);
+ if (e != null && e.removeState(trans, peer)) {
+ this.entries.remove(id);
+ }
+ }
+}
--- /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.protocol.bgp.rib.spi;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpReachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpUnreachNlri;
+
+public interface AdjRIBsIn {
+ public void addRoutes(DataModification trans, Peer peer, MpReachNlri nlri, PathAttributes attributes);
+ public void removeRoutes(DataModification trans, Peer peer, MpUnreachNlri nlri);
+ public void clear(DataModification trans, Peer peer);
+}
--- /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.protocol.bgp.rib.spi;
+
+import java.util.Comparator;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.PathAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+
+public interface AdjRIBsInFactory {
+ public AdjRIBsIn createAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key);
+}
--- /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.protocol.bgp.rib.spi;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
+
+/**
+ * Interface for registering AdjRIBsIn factories. In order for a model-driven
+ * RIB implementation to work correctly, it has to know how to handle
+ * individual NLRI fields, whose encoding is specific to a AFI/SAFI pair. This
+ * interface exposes an interface for registration of factories for creating
+ * AdjRIBsIn instances, which handle the specifics.
+ */
+public interface AdjRIBsInFactoryRegistry {
+ /**
+ * Register a AdjRIBsInFactory for a particular AFI/SAFI combination.
+ *
+ * @param afi Address Family identifier
+ * @param safi Subsequent Address Family identifier
+ * @param factory AdjRIBsInFactory
+ * @return Registration handle. Call its close() method to remove it.
+ */
+ public AutoCloseable registerAdjRIBsInFactory(Class<? extends AddressFamily> afi,
+ Class<? extends SubsequentAddressFamily> safi, AdjRIBsInFactory factory);
+
+ public AdjRIBsInFactory getAdjRIBsInFactory(Class<? extends AddressFamily> afi,
+ Class<? extends SubsequentAddressFamily> safi);
+
+}
\ No newline at end of file
--- /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.protocol.bgp.rib.spi;
+
+/**
+ * Marker interface identifying a BGP peer.
+ */
+public interface Peer {
+
+}