Merge "Add linkstate information to RIB"
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / RIBImpl.java
index 9f0402054df3850195f9b95eef3017aac452c5a7..b06b2a0045f1ae8f80e1f0006c417399845fbebf 100644 (file)
  */
 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
@@ -140,7 +100,6 @@ public final class RIBImpl implements RIB {
        }
 
        protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
-               toStringHelper.add("name", this.name);
                return toStringHelper;
        }
 }