*/
package org.opendaylight.protocol.bgp.rib.impl;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-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.concepts.BGPTableType;
-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.rib.RIB;
-import org.opendaylight.protocol.bgp.rib.RIBChangedEvent;
-import org.opendaylight.protocol.bgp.rib.RIBEvent;
-import org.opendaylight.protocol.bgp.rib.RIBEventListener;
-import org.opendaylight.protocol.concepts.InitialListenerEvents;
-import org.opendaylight.protocol.concepts.ListenerRegistration;
-import org.opendaylight.protocol.concepts.Prefix;
+
+
+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.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;
import com.google.common.base.Preconditions;
-import com.google.common.eventbus.EventBus;
-import com.google.common.eventbus.Subscribe;
@ThreadSafe
-public final class RIBImpl implements RIB {
- 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 final EventBus bus;
- private final String name;
-
- public RIBImpl(final String name) {
- this.name = Preconditions.checkNotNull(name);
- this.bus = new EventBus(name);
+final class RIBImpl {
+ private static final Logger logger = LoggerFactory.getLogger(RIBImpl.class);
+ private final DataProviderService dps;
+ private final RIBTables tables;
+
+ RIBImpl(final DataProviderService dps) {
+ this.dps = Preconditions.checkNotNull(dps);
+ this.tables = new RIBTables(BGPObjectComparator.INSTANCE, 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);
- else
- throw new IllegalArgumentException("Unsupported identifier " + id.getClass());
-
- 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());
- } else
- throw new IllegalArgumentException("Unsupported identifier " + o.getClass());
-
- if (!l.isEmpty() || !n.isEmpty() || !p.isEmpty() || !r.isEmpty())
- this.bus.post(new RIBChangedEvent(l, n, p, r));
- }
+ synchronized void updateTables(final BGPPeer peer, final Update message) {
+ final DataModificationTransaction trans = dps.beginTransaction();
- synchronized void clearTable(final BGPPeer peer, final BGPTableType t) {
- switch (t.getAddressFamily()) {
- case Ipv4:
- case Ipv6:
- this.bus.post(new RIBChangedEvent(this.routes.clear(peer)));
- break;
- case Linkstate:
- this.bus.post(new RIBChangedEvent(this.links.clear(peer), this.nodes.clear(peer), this.prefixes.clear(peer)));
- break;
- }
- }
+ // FIXME: detect and handle end-of-RIB markers
- @Override
- synchronized public InitialListenerEvents<RIBEventListener, RIBEvent> registerListener(final RIBEventListener listener) {
- final List<RIBEvent> events = new ArrayList<>();
+ //remove(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class,
+ // trans, peer, message.getWithdrawnRoutes().getWithdrawnRoutes().iterator());
- events.add(new RIBChangedEvent(this.routes.currentState()));
- events.add(new RIBChangedEvent(this.links.currentState(), this.nodes.currentState(), this.prefixes.currentState()));
+ final PathAttributes attrs = message.getPathAttributes();
+ final PathAttributes2 mpu = attrs.getAugmentation(PathAttributes2.class);
+ if (mpu != null) {
+ final MpUnreachNlri nlri = mpu.getMpUnreachNlri();
- final Object wrapper = new Object() {
- @Subscribe
- public void notifyListener(final RIBChangedEvent event) {
- listener.onRIBEvent(event);
+ AdjRIBsIn ari = tables.getOrCreate(new TablesKey(nlri.getAfi(), nlri.getSafi()));
+ if (ari != null) {
+ ari.removeRoutes(trans, peer, nlri);
+ } else {
+ logger.debug("Not removing objects from unhandled NLRI {}", nlri);
}
- };
- this.bus.register(wrapper);
+ }
- return new InitialListenerEvents<RIBEventListener, RIBEvent>(new ListenerRegistration<RIBEventListener>() {
- @Override
- public void close() {
- RIBImpl.this.bus.unregister(wrapper);
- }
+ //add(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class,
+ // trans, peer, message.getNlri().getNlri().iterator(), attrs);
- @Override
- public RIBEventListener getListener() {
- return listener;
+ 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 {
+ logger.debug("Not adding objects from unhandled NLRI {}", nlri);
}
- }, events);
+ }
+
+ // FIXME: we need to attach to this future for failures
+ Future<RpcResult<TransactionStatus>> f = trans.commit();
+ }
+
+ synchronized void clearTable(final BGPPeer peer, final TablesKey key) {
+ final AdjRIBsIn ari = tables.get(key);
+ if (ari != null) {
+ final DataModificationTransaction trans = dps.beginTransaction();
+ ari.clear(trans, peer);
+
+ // FIXME: we need to attach to this future for failures
+ Future<RpcResult<TransactionStatus>> f = trans.commit();
+ }
}
@Override
}
protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
- toStringHelper.add("name", this.name);
return toStringHelper;
}
}