final class LinkstateAdjRIBsIn extends AbstractAdjRIBsIn<CLinkstateDestination, LinkstateRoute> {
private static abstract class LinkstateRIBEntryData<LSATTR extends LinkStateAttribute> extends
- RIBEntryData<CLinkstateDestination, LinkstateRoute> {
+ RIBEntryData<CLinkstateDestination, LinkstateRoute> {
private final LSATTR lsattr;
protected LinkstateRIBEntryData(final PathAttributes attributes, final LSATTR lsattr) {
}
}
- LinkstateAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
- super(comparator, key);
+ LinkstateAdjRIBsIn(final DataModificationTransaction trans, final Comparator<PathAttributes> comparator, final TablesKey key) {
+ super(trans, comparator, key);
}
@Override
import java.util.Comparator;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInFactory;
import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderActivator;
reg = context.registerAdjRIBsInFactory(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class, new AdjRIBsInFactory() {
@Override
- public AdjRIBsIn createAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
- return new LinkstateAdjRIBsIn(comparator, key);
+ public AdjRIBsIn createAdjRIBsIn(final DataModificationTransaction trans, final Comparator<PathAttributes> comparator, final TablesKey key) {
+ return new LinkstateAdjRIBsIn(trans, comparator, key);
}
});
}
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
final class Ipv4AdjRIBsIn extends AbstractAdjRIBsIn<Ipv4Prefix, Ipv4Route> {
- Ipv4AdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
- super(comparator, key);
+ Ipv4AdjRIBsIn(final DataModificationTransaction trans, final Comparator<PathAttributes> comparator, final TablesKey key) {
+ super(trans, comparator, key);
}
@Override
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
final class Ipv6AdjRIBsIn extends AbstractAdjRIBsIn<Ipv6Prefix, Ipv6Route> {
- Ipv6AdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
- super(comparator, key);
+ Ipv6AdjRIBsIn(final DataModificationTransaction trans, final Comparator<PathAttributes> comparator, final TablesKey key) {
+ super(trans, comparator, key);
}
@Override
import java.util.Comparator;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInFactory;
import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderActivator;
v4reg = context.registerAdjRIBsInFactory(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class, new AdjRIBsInFactory() {
@Override
- public AdjRIBsIn createAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
- return new Ipv4AdjRIBsIn(comparator, key);
+ public AdjRIBsIn createAdjRIBsIn(final DataModificationTransaction trans, final Comparator<PathAttributes> comparator, final TablesKey key) {
+ return new Ipv4AdjRIBsIn(trans, comparator, key);
}
});
v6reg = context.registerAdjRIBsInFactory(Ipv6AddressFamily.class, UnicastSubsequentAddressFamily.class, new AdjRIBsInFactory() {
@Override
- public AdjRIBsIn createAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
- return new Ipv6AdjRIBsIn(comparator, key);
+ public AdjRIBsIn createAdjRIBsIn(final DataModificationTransaction trans, final Comparator<PathAttributes> comparator, final TablesKey key) {
+ return new Ipv6AdjRIBsIn(trans, comparator, key);
}
});
import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.UpdateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.Nlri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.WithdrawnRoutes;
@ThreadSafe
public class RIBImpl {
private static final Logger LOG = LoggerFactory.getLogger(RIBImpl.class);
+ private static final Update EOR = new UpdateBuilder().build();
private final DataProviderService dps;
private final RIBTables tables;
synchronized void updateTables(final BGPPeer peer, final Update message) {
final DataModificationTransaction trans = this.dps.beginTransaction();
- // FIXME: detect and handle end-of-RIB markers
+ if (EOR.equals(message)) {
+ final AdjRIBsIn ari = this.tables.getOrCreate(trans, new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class));
+ if (ari != null) {
+ ari.markUptodate(trans, peer);
+ } else {
+ LOG.debug("End-of-RIB for IPv4 Unicast ignored");
+ }
+ return;
+ }
final WithdrawnRoutes wr = message.getWithdrawnRoutes();
if (wr != null) {
- final AdjRIBsIn ari = this.tables.getOrCreate(new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class));
+ final AdjRIBsIn ari = this.tables.getOrCreate(trans, new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class));
if (ari != null) {
ari.removeRoutes(trans, peer, new MpUnreachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).setWithdrawnRoutes(
new WithdrawnRoutesBuilder().setDestinationType(new DestinationIpv4Builder().setIpv4Prefixes(wr.getWithdrawnRoutes()).build()).build()).build());
if (mpu != null) {
final MpUnreachNlri nlri = mpu.getMpUnreachNlri();
- final AdjRIBsIn ari = this.tables.getOrCreate(new TablesKey(nlri.getAfi(), nlri.getSafi()));
+ final AdjRIBsIn ari = this.tables.getOrCreate(trans, new TablesKey(nlri.getAfi(), nlri.getSafi()));
if (ari != null) {
ari.removeRoutes(trans, peer, nlri);
} else {
final Nlri ar = message.getNlri();
if (ar != null) {
- final AdjRIBsIn ari = this.tables.getOrCreate(new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class));
+ final AdjRIBsIn ari = this.tables.getOrCreate(trans, new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class));
if (ari != null) {
ari.addRoutes(trans, peer, new MpReachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).
setCNextHop(attrs.getCNextHop()).setAdvertizedRoutes(
if (mpr != null) {
final MpReachNlri nlri = mpr.getMpReachNlri();
- final AdjRIBsIn ari = this.tables.getOrCreate(new TablesKey(nlri.getAfi(), nlri.getSafi()));
+ final AdjRIBsIn ari = this.tables.getOrCreate(trans, new TablesKey(nlri.getAfi(), nlri.getSafi()));
if (ari != null) {
ari.addRoutes(trans, peer, nlri, attrs);
+ if (message.equals(ari.endOfRib())) {
+ ari.markUptodate(trans, peer);
+ }
} else {
LOG.debug("Not adding objects from unhandled NLRI {}", nlri);
}
import java.util.HashMap;
import java.util.Map;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInFactory;
import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
return tables.get(key);
}
- public synchronized AdjRIBsIn getOrCreate(final TablesKey key) {
+ public synchronized AdjRIBsIn getOrCreate(final DataModificationTransaction trans, final TablesKey key) {
if (tables.containsKey(key)) {
return tables.get(key);
}
return null;
}
- final AdjRIBsIn table = Preconditions.checkNotNull(f.createAdjRIBsIn(comparator, key));
+ final AdjRIBsIn table = Preconditions.checkNotNull(f.createAdjRIBsIn(trans, comparator, key));
tables.put(key, table);
return table;
}
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.UpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlriBuilder;
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.TablesBuilder;
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;
LOG.trace("Electing state {} to supersede {}", candidate, currentState);
if (this.currentState == null || !this.currentState.equals(candidate)) {
- transaction.putRuntimeData(getName(), candidate.getDataObject(this.key));
+ transaction.putOperationalData(getName(), candidate.getDataObject(this.key));
this.currentState = candidate;
}
}
private static final Logger LOG = LoggerFactory.getLogger(AbstractAdjRIBsIn.class);
private final Comparator<PathAttributes> comparator;
private final InstanceIdentifier<Tables> basePath;
+ private final Update eor;
+
@GuardedBy("this")
private final Map<ID, RIBEntry> entries = new HashMap<>();
- protected AbstractAdjRIBsIn(final Comparator<PathAttributes> comparator, final TablesKey key) {
+ @GuardedBy("this")
+ private final Map<Peer, Boolean> peers = new HashMap<>();
+
+ protected AbstractAdjRIBsIn(final DataModificationTransaction trans, final Comparator<PathAttributes> comparator, final TablesKey key) {
this.comparator = Preconditions.checkNotNull(comparator);
this.basePath = InstanceIdentifier.builder(LocRib.class).child(Tables.class, key).toInstance();
+
+ eor = new UpdateBuilder().setPathAttributes(
+ new PathAttributesBuilder().addAugmentation(
+ PathAttributes1.class,
+ new PathAttributes1Builder().setMpReachNlri(
+ new MpReachNlriBuilder().setAfi(key.getAfi()).setSafi(key.getSafi()).build()).build()).build()).build();
+
+ trans.putOperationalData(basePath, new TablesBuilder().setAfi(key.getAfi()).setSafi(key.getSafi()).setUptodate(Boolean.FALSE).build());
+ }
+
+ private void setUptodate(final DataModificationTransaction trans, final Boolean uptodate) {
+ final Tables t = (Tables) trans.readOperationalData(basePath);
+ if (t == null || !uptodate.equals(t.isUptodate())) {
+ LOG.debug("Table {} switching uptodate to {}", uptodate);
+ trans.putOperationalData(basePath, new TablesBuilder(t).setUptodate(uptodate).build());
+ }
}
@Override
i.remove();
}
}
+
+ peers.remove(peer);
+ setUptodate(trans, peers.values().contains(Boolean.FALSE) == false);
}
protected abstract InstanceIdentifier<?> identifierForKey(final InstanceIdentifier<Tables> basePath, final ID id);
}
e.setState(trans, peer, data);
+ if (!peers.containsKey(peer)) {
+ peers.put(peer, Boolean.FALSE);
+ setUptodate(trans, Boolean.FALSE);
+ }
}
protected synchronized void remove(final DataModificationTransaction trans, final Peer peer, final ID id) {
this.entries.remove(id);
}
}
+
+ @Override
+ public final void markUptodate(final DataModificationTransaction trans, final Peer peer) {
+ peers.put(peer, Boolean.TRUE);
+ setUptodate(trans, peers.values().contains(Boolean.FALSE) == false);
+ }
+
+ @Override
+ public final Update endOfRib() {
+ return eor;
+ }
}
package org.opendaylight.protocol.bgp.rib.spi;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlri;
public interface AdjRIBsIn {
- public void addRoutes(DataModificationTransaction trans, Peer peer, MpReachNlri nlri, PathAttributes attributes);
- public void removeRoutes(DataModificationTransaction trans, Peer peer, MpUnreachNlri nlri);
- public void clear(DataModificationTransaction trans, Peer peer);
+ void addRoutes(DataModificationTransaction trans, Peer peer, MpReachNlri nlri, PathAttributes attributes);
+ void removeRoutes(DataModificationTransaction trans, Peer peer, MpUnreachNlri nlri);
+ void clear(DataModificationTransaction trans, Peer peer);
+ void markUptodate(DataModificationTransaction trans, Peer peer);
+ Update endOfRib();
}
import java.util.Comparator;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.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);
+ public AdjRIBsIn createAdjRIBsIn(final DataModificationTransaction trans, final Comparator<PathAttributes> comparator, final TablesKey key);
}
package org.opendaylight.protocol.integration.bgp;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.protocol.bgp.linkstate.RIBActivator;
import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
import org.opendaylight.protocol.bgp.rib.impl.BGPPeer;
+import org.opendaylight.protocol.bgp.rib.impl.RIBActivator;
import org.opendaylight.protocol.bgp.rib.impl.RIBImpl;
import org.opendaylight.protocol.bgp.rib.mock.BGPMock;
import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext;
}
}).when(this.mockedTransaction).commit();
+ final HashMap<Object, Object> data = new HashMap<>();
+
Mockito.doAnswer(new Answer<String>() {
@Override
public String answer(final InvocationOnMock invocation) throws Throwable {
final Object[] args = invocation.getArguments();
- for (final Object a : args) {
- LOG.debug("Arg: {}", a);
- }
+ LOG.debug("Put key {} value {}", args[0]);
+ LOG.debug("Put value {}", args[1]);
+ data.put(args[0], args[1]);
return null;
}
- }).when(this.mockedTransaction).putRuntimeData(Matchers.any(InstanceIdentifier.class), Matchers.any(DataObject.class));
+ }).when(this.mockedTransaction).putOperationalData(Matchers.any(InstanceIdentifier.class), Matchers.any(DataObject.class));
+
+ Mockito.doAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(final InvocationOnMock invocation) throws Throwable {
+ final Object[] args = invocation.getArguments();
+ LOG.debug("Get key {}", args[0]);
+ return data.get(args[0]);
+ }
+
+ }).when(this.mockedTransaction).readOperationalData(Matchers.any(InstanceIdentifier.class));
}
@Test
public void test() {
final RIBExtensionProviderContext ext = new SimpleRIBExtensionProviderContext();
new RIBActivator().startRIBExtensionProvider(ext);
+ new org.opendaylight.protocol.bgp.linkstate.RIBActivator().startRIBExtensionProvider(ext);
final RIBImpl rib = new RIBImpl(ext, this.providerService);
final BGPPeer peer = new BGPPeer(rib, "peer-" + this.mock.toString());
}
}, null);
Mockito.verify(this.mockedTransaction, Mockito.times(24)).commit();
- Mockito.verify(this.mockedTransaction, Mockito.times(40)).putRuntimeData(Matchers.any(InstanceIdentifier.class),
+ Mockito.verify(this.mockedTransaction, Mockito.times(67)).putOperationalData(Matchers.any(InstanceIdentifier.class),
Matchers.any(DataObject.class));
}