BUG-46: preliminary switch to MD-SAL 34/1634/7
authorRobert Varga <rovarga@cisco.com>
Thu, 3 Oct 2013 13:07:27 +0000 (15:07 +0200)
committerRobert Varga <rovarga@cisco.com>
Fri, 4 Oct 2013 12:11:26 +0000 (14:11 +0200)
Change-Id: I6ede4d6eef457f0fb6e59ce1325a839997daf82f
Signed-off-by: Robert Varga <rovarga@cisco.com>
17 files changed:
bgp/pom.xml
bgp/rib-api/src/main/yang/bgp-rib.yang
bgp/rib-impl/pom.xml
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBsInFactoryRegistryImpl.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPObjectComparator.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBEntry.java [deleted file]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBTable.java [deleted file]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBTables.java [new file with mode: 0644]
bgp/rib-spi/.project [new file with mode: 0644]
bgp/rib-spi/pom.xml [new file with mode: 0644]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AbstractAdjRIBsIn.java [new file with mode: 0644]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsIn.java [new file with mode: 0644]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInFactory.java [new file with mode: 0644]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInFactoryRegistry.java [new file with mode: 0644]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/Peer.java [new file with mode: 0644]

index d9b2ee6e50a27dbc4c4e4b6f8fee6a71b85aebb1..eb217cc51261909c2bedeb58ed8674d07412ded0 100644 (file)
@@ -23,6 +23,7 @@
         <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>
index 816979cd49a1036dafb1073a44aeadf9aab4d535..ac3b83181a8e8329e3babebae4e29b64c6aed87f 100644 (file)
@@ -29,10 +29,6 @@ module bgp-rib {
         }
 
        grouping route {
-               container next-hop {
-                       uses bgp-t:next-hop;
-               }
-
                container attributes {
                        uses bgp-msg:path-attributes;
                }
@@ -63,29 +59,29 @@ module bgp-rib {
                                        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;
index eb687858114577824f5fa3d8c2465a733a78b60f..130cbe9120e81cf43d3e6a1def811f15c959ffd5 100644 (file)
                <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>
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBsInFactoryRegistryImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBsInFactoryRegistryImpl.java
new file mode 100644 (file)
index 0000000..6015f0c
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * 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));
+       }
+}
index bf15c3ebfd46e5b6b43abd01b61100b08b166186..0be37b9fbe4073848f0813b59a8c6837455b1004 100644 (file)
@@ -9,7 +9,7 @@ package org.opendaylight.protocol.bgp.rib.impl;
 
 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;
 
 
 /**
@@ -19,15 +19,18 @@ import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
  * 
  * @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 :-)
index ed9a811615927a557fcfdd90d1c624ae4fcbf814..496f401dfe2a591192de9e0238b25665dbb07d5f 100644 (file)
@@ -13,7 +13,9 @@ import org.opendaylight.protocol.bgp.parser.BGPSession;
 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;
@@ -26,9 +28,9 @@ import com.google.common.base.Preconditions;
  * 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;
 
@@ -39,9 +41,8 @@ public final class BGPPeer implements BGPSessionListener {
 
        @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());
                }
@@ -50,14 +51,20 @@ public final class BGPPeer implements BGPSessionListener {
        @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
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBEntry.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBEntry.java
deleted file mode 100644 (file)
index c6952d7..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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;
-       }
-}
index b2239119056c37f3d639130f6d90a694e5b31479..91a2d8b2ab370e6cbdc18493297555a691871f83 100644 (file)
@@ -7,29 +7,25 @@
  */
 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;
@@ -37,64 +33,63 @@ import com.google.common.base.Preconditions;
 
 @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();
                }
        }
 
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBTable.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBTable.java
deleted file mode 100644 (file)
index 6990073..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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;
-       }
-}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBTables.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBTables.java
new file mode 100644 (file)
index 0000000..eeb9f57
--- /dev/null
@@ -0,0 +1,39 @@
+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;
+       }
+
+}
diff --git a/bgp/rib-spi/.project b/bgp/rib-spi/.project
new file mode 100644 (file)
index 0000000..cb38ddf
--- /dev/null
@@ -0,0 +1,24 @@
+<?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>
diff --git a/bgp/rib-spi/pom.xml b/bgp/rib-spi/pom.xml
new file mode 100644 (file)
index 0000000..efd1914
--- /dev/null
@@ -0,0 +1,87 @@
+<?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>
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AbstractAdjRIBsIn.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AbstractAdjRIBsIn.java
new file mode 100644 (file)
index 0000000..622a634
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * 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);
+               }
+       }
+}
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsIn.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsIn.java
new file mode 100644 (file)
index 0000000..ea77e0c
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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);
+}
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInFactory.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInFactory.java
new file mode 100644 (file)
index 0000000..d3ac136
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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);
+}
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInFactoryRegistry.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInFactoryRegistry.java
new file mode 100644 (file)
index 0000000..891d096
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/Peer.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/Peer.java
new file mode 100644 (file)
index 0000000..7e4d769
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * 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 {
+
+}