BUG-1116: Finish up egress path API changes 22/9122/26
authorMilos Fabian <milfabia@cisco.com>
Tue, 5 Aug 2014 11:54:45 +0000 (13:54 +0200)
committerMilos Fabian <milfabia@cisco.com>
Tue, 5 Aug 2014 12:47:39 +0000 (14:47 +0200)
This finishes the API-level changes required to support route
dissemination. The codepath should just work, but more testing is
needed.

Change-Id: I79ace174c78f0653b057b0bad1c685ecd5e9d0cb
Signed-off-by: Robert Varga <rovarga@cisco.com>
Signed-off-by: Milos Fabian <milfabia@cisco.com>
27 files changed:
bgp/linkstate/pom.xml
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/LinkstateAdjRIBsIn.java
bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/RIBActivator.java
bgp/linkstate/src/test/java/org/opendaylight/protocol/bgp/linkstate/LinkstateAdjRIBsInTest.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractAdjRIBsOut.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBOutEntry.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBsTransactionImpl.java [moved from bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBsInTransactionImpl.java with 64% similarity]
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/BGPSessionImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/Ipv4AdjRIBsIn.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/Ipv6AdjRIBsIn.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBActivator.java
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/RIBTables.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/SessionRIBsOut.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/AdjRIBsOut.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/AdjRIBsOutRegistration.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/RIB.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BestPathSelectionTest.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AbstractAdjRIBs.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsFactory.java [moved from bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInFactory.java with 83% similarity]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsIn.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsTransaction.java [moved from bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInTransaction.java with 67% similarity]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/RIBExtensionConsumerContext.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/RIBExtensionProviderContext.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/RouteEncoder.java [new file with mode: 0644]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/SimpleRIBExtensionProviderContext.java

index 57c922f8f35bd18c0690322fd9155c828bfe6644..894062418f93f505e1ef5da3d2c7bb030b728a44 100644 (file)
              <artifactId>bgp-parser-spi</artifactId>
              <type>test-jar</type>
          </dependency>
+         <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
     </dependencies>
 
     <build>
index a1b044810445c74086c984029eaef62153b34037..fd5dad0f9192f9e19de141d240459b664a9accdd 100644 (file)
@@ -13,7 +13,7 @@ import com.google.common.collect.Lists;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import org.opendaylight.protocol.bgp.rib.spi.AbstractAdjRIBs;
-import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInTransaction;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsTransaction;
 import org.opendaylight.protocol.bgp.rib.spi.Peer;
 import org.opendaylight.protocol.util.ByteArray;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
@@ -120,7 +120,7 @@ final class LinkstateAdjRIBsIn extends AbstractAdjRIBs<CLinkstateDestination, Li
     }
 
     @Override
-    public void addRoutes(final AdjRIBsInTransaction trans, final Peer peer, final MpReachNlri nlri,
+    public void addRoutes(final AdjRIBsTransaction trans, final Peer peer, final MpReachNlri nlri,
             final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes attributes) {
         LOG.debug("Passed nlri {}", nlri);
         final LinkstateDestination keys = ((DestinationLinkstateCase) nlri.getAdvertizedRoutes().getDestinationType()).getDestinationLinkstate();
@@ -209,7 +209,7 @@ final class LinkstateAdjRIBsIn extends AbstractAdjRIBs<CLinkstateDestination, Li
     }
 
     @Override
-    public void removeRoutes(final AdjRIBsInTransaction trans, final Peer peer, final MpUnreachNlri nlri) {
+    public void removeRoutes(final AdjRIBsTransaction trans, final Peer peer, final MpUnreachNlri nlri) {
         final DestinationLinkstate keys = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase) nlri.getWithdrawnRoutes().getDestinationType()).getDestinationLinkstate();
 
         for (final CLinkstateDestination key : keys.getCLinkstateDestination()) {
index 1ad7b67ed4808353c36a2d7aede62205bd266a9b..fadd1398dd805edf5c6dd313028b51b7cb8162be 100644 (file)
@@ -12,8 +12,8 @@ import com.google.common.collect.Lists;
 import java.util.List;
 
 import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBExtensionProviderActivator;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsFactory;
 import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
-import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInFactory;
 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateAddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateSubsequentAddressFamily;
@@ -27,9 +27,9 @@ import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 public final class RIBActivator extends AbstractRIBExtensionProviderActivator {
     @Override
     protected List<AutoCloseable> startRIBExtensionProviderImpl(final RIBExtensionProviderContext context) {
-        return Lists.newArrayList(context.registerAdjRIBsInFactory(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class, new AdjRIBsInFactory() {
+        return Lists.newArrayList(context.registerAdjRIBsInFactory(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class, new AdjRIBsFactory() {
             @Override
-            public AdjRIBsIn createAdjRIBsIn(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
+            public AdjRIBsIn<?, ?> createAdjRIBs(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
                 return new LinkstateAdjRIBsIn(basePath);
             }
         }));
index cc783d46b3f3045eefc47a864f062cf623da2f63..dbf27d185fe2310d2ab38225ec4600a1bfdaa8ba 100644 (file)
@@ -7,11 +7,8 @@
  */
 package org.opendaylight.protocol.bgp.linkstate;
 
-import static org.junit.Assert.assertEquals;
-
 import java.math.BigInteger;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
@@ -21,10 +18,14 @@ import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.protocol.bgp.rib.RibReference;
-import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInTransaction;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsTransaction;
 import org.opendaylight.protocol.bgp.rib.spi.BGPObjectComparator;
 import org.opendaylight.protocol.bgp.rib.spi.Peer;
+import org.opendaylight.protocol.bgp.rib.spi.RouteEncoder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
@@ -54,20 +55,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mult
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.BgpRib;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.Rib;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Attributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.AttributesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
-public class LinkstateAdjRIBsInTest {
+public class LinkstateAdjRIBsInTest extends AbstractDataBrokerTest {
 
     private static final AsNumber TEST_AS_NUMBER = new AsNumber(35L);
 
@@ -78,7 +79,10 @@ public class LinkstateAdjRIBsInTest {
     private Peer peer;
 
     @Mock
-    private AdjRIBsInTransaction adjRibTx;
+    private AdjRIBsTransaction adjRibTx;
+
+    @Mock
+    private RouteEncoder encoder;
 
     private LinkstateAdjRIBsIn lrib;
 
@@ -88,47 +92,50 @@ public class LinkstateAdjRIBsInTest {
 
     private final List<CLinkstateDestination> destinations = new ArrayList<>();
 
-    private final HashMap<InstanceIdentifier<?>, DataObject> data = new HashMap<>();
-
     private final BGPObjectComparator bgpComparator = new BGPObjectComparator(TEST_AS_NUMBER);
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
         final InstanceIdentifier<Rib> iid = InstanceIdentifier.builder(BgpRib.class).child(Rib.class, new RibKey(new RibId("test-rib"))).toInstance();
         final KeyedInstanceIdentifier<Tables, TablesKey> key = iid.child(LocRib.class).child(Tables.class, new TablesKey(LinkstateAddressFamily.class,
                 LinkstateSubsequentAddressFamily.class));
+
         Mockito.doAnswer(new Answer<Void>() {
+            @SuppressWarnings("unchecked")
             @Override
             public Void answer(final InvocationOnMock invocation) throws Throwable {
                 final Object[] args = invocation.getArguments();
-                LinkstateAdjRIBsInTest.this.data.put((InstanceIdentifier<?>)args[0], (DataObject)args[1]);
+                final InstanceIdentifier<Route> ii = (InstanceIdentifier<Route>) args[2];
+                final Route data = (Route) args[4];
+                wTx.put(LogicalDatastoreType.OPERATIONAL, ii, data, true);
                 return null;
             }
 
-        }).when(this.adjRibTx).advertise(Mockito.<InstanceIdentifier<DataObject>>any(), Mockito.any(DataObject.class));
+        }).when(this.adjRibTx).advertise(Mockito.<RouteEncoder>any(), Mockito.any(), Mockito.<InstanceIdentifier<Route>>any(), Mockito.<Peer>any(), Mockito.any(Route.class));
 
         Mockito.doAnswer(new Answer<Void>() {
+            @SuppressWarnings("unchecked")
             @Override
             public Void answer(final InvocationOnMock invocation) throws Throwable {
                 final Object[] args = invocation.getArguments();
-                LinkstateAdjRIBsInTest.this.data.remove(args[0]);
+                final InstanceIdentifier<Route> ii = (InstanceIdentifier<Route>) args[2];
+                wTx.delete(LogicalDatastoreType.OPERATIONAL, ii);
                 return null;
             }
 
-        }).when(this.adjRibTx).withdraw(Matchers.any(InstanceIdentifier.class));
+        }).when(this.adjRibTx).withdraw(Mockito.<RouteEncoder>any(), Mockito.any(), Mockito.<InstanceIdentifier<Route>>any());
 
         Mockito.doAnswer(new Answer<Void>() {
             @SuppressWarnings("unchecked")
             @Override
             public Void answer(final InvocationOnMock invocation) throws Throwable {
                 final Object[] args = invocation.getArguments();
-                final InstanceIdentifier<Tables> base = (InstanceIdentifier<Tables>) args[0];
-                final Tables tables = (Tables) LinkstateAdjRIBsInTest.this.data.get(key);
-                if(tables != null) {
-                    LinkstateAdjRIBsInTest.this.data.put(base,
-                            new TablesBuilder(tables).setAttributes(new AttributesBuilder().setUptodate((Boolean) args[1]).build()).build());
-                }
+                final InstanceIdentifier<Tables> basePath = (InstanceIdentifier<Tables>) args[0];
+                final Boolean uptodate = (Boolean) args[1];
+                final InstanceIdentifier<Attributes> aid = basePath.child(Attributes.class);
+                wTx.merge(LogicalDatastoreType.OPERATIONAL, aid, new AttributesBuilder().setUptodate(uptodate).build());
                 return null;
             }
         }).when(this.adjRibTx).setUptodate(Matchers.<InstanceIdentifier<Tables>>any(), Mockito.anyBoolean());
@@ -161,10 +168,8 @@ public class LinkstateAdjRIBsInTest {
 
         this.lrib.addRoutes(this.adjRibTx, this.peer, this.builder.build(), pa.build());
 
-        Mockito.verify(this.adjRibTx, Mockito.times(1)).advertise(Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.any(DataObject.class));
+        Mockito.verify(this.adjRibTx, Mockito.times(1)).advertise(Mockito.<RouteEncoder>any(), Mockito.any(), Mockito.<InstanceIdentifier<Route>>any(), Mockito.<Peer>any(), Mockito.any(Route.class));
         Mockito.verify(this.adjRibTx, Mockito.times(1)).setUptodate(Matchers.<InstanceIdentifier<Tables>>any(), Matchers.anyBoolean());
-
-        assertEquals(1, this.data.size());
     }
 
     @Test
@@ -184,9 +189,8 @@ public class LinkstateAdjRIBsInTest {
 
         this.lrib.addRoutes(this.adjRibTx, this.peer, this.builder.build(), pa.build());
 
-        Mockito.verify(this.adjRibTx, Mockito.times(1)).advertise(Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.any(DataObject.class));
+        Mockito.verify(this.adjRibTx, Mockito.times(1)).advertise(Mockito.<RouteEncoder>any(), Mockito.any(), Mockito.<InstanceIdentifier<Route>>any(), Mockito.<Peer>any(), Mockito.any(Route.class));
         Mockito.verify(this.adjRibTx, Mockito.times(1)).setUptodate(Matchers.<InstanceIdentifier<Tables>>any(), Matchers.anyBoolean());
-        assertEquals(1, this.data.size());
     }
 
     @Test
@@ -208,11 +212,9 @@ public class LinkstateAdjRIBsInTest {
 
         this.lrib.addRoutes(this.adjRibTx, this.peer, this.builder.build(), pa.build());
 
-        Mockito.verify(this.adjRibTx, Mockito.times(1)).advertise(Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.any(DataObject.class));
+        Mockito.verify(this.adjRibTx, Mockito.times(1)).advertise(Mockito.<RouteEncoder>any(), Mockito.any(), Mockito.<InstanceIdentifier<Route>>any(), Mockito.<Peer>any(), Mockito.any(Route.class));
         Mockito.verify(this.adjRibTx, Mockito.times(1)).setUptodate(Matchers.<InstanceIdentifier<Tables>>any(), Matchers.anyBoolean());
 
-        assertEquals(1, this.data.size());
-
         final MpUnreachNlriBuilder builder = new MpUnreachNlriBuilder();
         builder.setAfi(LinkstateAddressFamily.class);
         builder.setSafi(LinkstateSubsequentAddressFamily.class);
@@ -222,7 +224,6 @@ public class LinkstateAdjRIBsInTest {
                                 this.destinations).build()).build()).build());
         this.lrib.removeRoutes(this.adjRibTx, this.peer, builder.build());
 
-        Mockito.verify(this.adjRibTx, Mockito.times(1)).withdraw(Matchers.any(InstanceIdentifier.class));
-        assertEquals(0, this.data.size());
+        Mockito.verify(this.adjRibTx, Mockito.times(1)).withdraw(Mockito.<RouteEncoder>any(), Mockito.any(), Matchers.<InstanceIdentifier<Route>>any());
     }
 }
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractAdjRIBsOut.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractAdjRIBsOut.java
new file mode 100644 (file)
index 0000000..3b7eebb
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014 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 com.google.common.base.Preconditions;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.protocol.bgp.rib.impl.spi.AdjRIBsOut;
+import org.opendaylight.protocol.bgp.rib.spi.RouteEncoder;
+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.rib.rev130925.Route;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * A per-peer collection of data which needs to be sent out. This class is kept lockfree
+ * on purpose.
+ */
+abstract class AbstractAdjRIBsOut implements AdjRIBsOut {
+    private final ConcurrentMap<Object, AdjRIBOutEntry<Object, Route>> data = new ConcurrentHashMap<>();
+    private final Queue<Object> queue = new ConcurrentLinkedQueue<>();
+
+    /**
+     * Callback invoked from RIB backend when new data becomes available. Implementations
+     * are expected to be able to handle multiple notifications and perform state
+     * compression as appropriate.
+     */
+    protected abstract void wantWrite();
+
+    /**
+     * Write a single PDU onto the peer. This callback is issued from {@link #process()}.
+     *
+     * @param pdu Update message
+     * @return True if the peer is ready to accept another PDU.
+     */
+    protected abstract boolean writePDU(Update pdu);
+
+    @Override
+    public void put(final RouteEncoder ribOut, final Object key, final Route newValue) {
+        AdjRIBOutEntry<Object, Route> e = data.get(key);
+        if (e == null) {
+            if (newValue == null) {
+                // Already not advertised, nothing to do
+                return;
+            }
+
+            e = new AdjRIBOutEntry<Object, Route>(ribOut);
+        }
+
+        // Make sure the new value is visible to the advertiser thread
+        final DataObject oldValue = e.getAndSetCurrent(newValue);
+
+        // Now read what is being currently advertised
+        final DataObject advValue = e.getAdverised();
+
+        if (advValue == newValue) {
+            /*
+             * We raced with the advertiser, which has sent out the this advertisement.
+             * This means our job is done.
+             */
+            return;
+        }
+
+        if (newValue != null && AdjRIBOutEntry.isNone(advValue)) {
+            /*
+             * We are advertising a new value and this is not a entry: need to put
+             * it into the map.
+             */
+            data.put(key, e);
+        }
+
+        if (oldValue == advValue) {
+            /*
+             * The old value was being advertised, so the advertiser is not aware that
+             * this key needs updating. Enqueue the key, so it will see it.
+             */
+            queue.add(key);
+            wantWrite();
+        }
+    }
+
+    /**
+     * Call this method from superclass when you are ready to process outgoing PDUs.
+     */
+    protected final void process() {
+        boolean writable = true;
+
+        while (writable) {
+            final Object key = queue.poll();
+            if (key == null) {
+                break;
+            }
+
+            final AdjRIBOutEntry<Object, Route> e = data.get(key);
+            if (e == null) {
+                /*
+                 * This was a notification for a value which has already been withdrawn,
+                 * nothing to do, continue to next key.
+                 */
+                continue;
+            }
+
+            // First read what is it that we are advertising
+            final DataObject oldValue = e.getAdverised();
+            Preconditions.checkState(oldValue != null, "Unexpected withdrawn entry %s for %s", e, key);
+
+            // Now read what we should be advertising
+            final Route newValue = e.getCurrent();
+
+            if (!oldValue.equals(newValue)) {
+                /*
+                 * The advertised value is not the same as what we want to advertise,
+                 * so we need to send it out.
+                 */
+                writable = writePDU(e.getRibOut().updateMessageFor(key, newValue));
+            }
+
+            /*
+             * Save what we are advertising. We need to store this even for withdrawals,
+             * as the entry may have been picked up again.
+             */
+            e.setAdverised(newValue);
+
+            /*
+             * Ready to clean the entry. Just a tiny check first: has the new value
+             * changed? If it has, we need to keep the entry, as there is an incoming
+             * update.
+             */
+            if (newValue == null && e.getCurrent() == newValue) {
+                data.remove(key, e);
+            }
+        }
+    }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBOutEntry.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBOutEntry.java
new file mode 100644 (file)
index 0000000..018a7da
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014 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 com.google.common.base.Preconditions;
+
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+import org.opendaylight.protocol.bgp.rib.spi.RouteEncoder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.route.Attributes;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+
+final class AdjRIBOutEntry<K, V extends Route> {
+    @SuppressWarnings("rawtypes")
+    private static final AtomicReferenceFieldUpdater<AdjRIBOutEntry, Route> NLRIENTRY_ADV_UPDATER = AtomicReferenceFieldUpdater.newUpdater(AdjRIBOutEntry.class, Route.class, "advertisedValue");
+    @SuppressWarnings("rawtypes")
+    private static final AtomicReferenceFieldUpdater<AdjRIBOutEntry, Route> NLRIENTRY_CUR_UPDATER = AtomicReferenceFieldUpdater.newUpdater(AdjRIBOutEntry.class, Route.class, "currentValue");
+
+    /*
+     * Marker object for uninitialized value. Distinct from null.
+     */
+    private static final Route NLRIENTRY_NONE_VALUE = new Route() {
+        @Override
+        public Class<? extends DataContainer> getImplementedInterface() {
+            throw new IllegalStateException("This method should never be invoked");
+        }
+
+        @Override
+        public Attributes getAttributes() {
+            throw new IllegalStateException("This method should never be invoked");
+        }
+    };
+
+    // Referenced via AtomicReferenceFieldUpdaters
+    @SuppressWarnings("unused")
+    private volatile Route currentValue = NLRIENTRY_NONE_VALUE;
+    @SuppressWarnings("unused")
+    private volatile Route advertisedValue = NLRIENTRY_NONE_VALUE;
+    private final RouteEncoder ribOut;
+
+    AdjRIBOutEntry(final RouteEncoder ribOut) {
+        this.ribOut = Preconditions.checkNotNull(ribOut);
+    }
+
+    Route getAdverised() {
+        return NLRIENTRY_ADV_UPDATER.get(this);
+    }
+
+    void setAdverised(final V value) {
+        NLRIENTRY_ADV_UPDATER.set(this, value);
+    }
+
+    @SuppressWarnings("unchecked")
+    V getCurrent() {
+        final Route o = NLRIENTRY_CUR_UPDATER.get(this);
+        Preconditions.checkState(!isNone(o), "Value cannot be NONE here");
+        return (V) o;
+    }
+
+    Route getAndSetCurrent(final V value) {
+        return NLRIENTRY_CUR_UPDATER.getAndSet(this, value);
+    }
+
+    RouteEncoder getRibOut() {
+        return ribOut;
+    }
+
+    static final boolean isNone(final Object o) {
+        return o == NLRIENTRY_NONE_VALUE;
+    }
+}
\ No newline at end of file
similarity index 64%
rename from bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBsInTransactionImpl.java
rename to bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRIBsTransactionImpl.java
index bb027dc57746c6c505f049475766490962bba0e0..95d4b193b5bfd0dd2692edfebbd2aa0f440cd48b 100644 (file)
@@ -9,27 +9,36 @@ package org.opendaylight.protocol.bgp.rib.impl;
 
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.CheckedFuture;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInTransaction;
+import org.opendaylight.protocol.bgp.rib.impl.spi.AdjRIBsOut;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsTransaction;
 import org.opendaylight.protocol.bgp.rib.spi.BGPObjectComparator;
+import org.opendaylight.protocol.bgp.rib.spi.Peer;
+import org.opendaylight.protocol.bgp.rib.spi.RouteEncoder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
 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.tables.Attributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.AttributesBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-class AdjRIBsInTransactionImpl implements AdjRIBsInTransaction {
-    private static final Logger LOG = LoggerFactory.getLogger(AdjRIBsInTransactionImpl.class);
+class AdjRIBsTransactionImpl implements AdjRIBsTransaction {
+    private static final Logger LOG = LoggerFactory.getLogger(AdjRIBsTransactionImpl.class);
     private final BGPObjectComparator comparator;
     private final WriteTransaction trans;
+    private final Map<Peer, AdjRIBsOut> ribs;
 
-    AdjRIBsInTransactionImpl(final BGPObjectComparator comparator, final WriteTransaction writeTransaction) {
+    AdjRIBsTransactionImpl(final Map<Peer, AdjRIBsOut> ribs, final BGPObjectComparator comparator, final WriteTransaction writeTransaction) {
         this.comparator = Preconditions.checkNotNull(comparator);
         this.trans = Preconditions.checkNotNull(writeTransaction);
+        this.ribs = Preconditions.checkNotNull(ribs);
     }
 
     @Override
@@ -44,17 +53,25 @@ class AdjRIBsInTransactionImpl implements AdjRIBsInTransaction {
     }
 
     @Override
-    public <T extends DataObject> void advertise(final InstanceIdentifier<T> id, final T obj) {
-        trans.put(LogicalDatastoreType.OPERATIONAL, id, obj, true);
+    public BGPObjectComparator comparator() {
+        return comparator;
     }
 
     @Override
-    public void withdraw(final InstanceIdentifier<?> id) {
-        trans.delete(LogicalDatastoreType.OPERATIONAL, id);
+    public <K, V extends Route> void advertise(final RouteEncoder ribOut, final K key, final InstanceIdentifier<V> id, final Peer peer, final V obj) {
+        trans.put(LogicalDatastoreType.OPERATIONAL, id, obj, true);
+        for (Entry<Peer, AdjRIBsOut> e : ribs.entrySet()) {
+            if (e.getKey() != peer) {
+                e.getValue().put(ribOut, key, obj);
+            }
+        }
     }
 
     @Override
-    public BGPObjectComparator comparator() {
-        return comparator;
+    public <K, V extends Route> void withdraw(final RouteEncoder ribOut, final K key, final InstanceIdentifier<V> id) {
+        trans.delete(LogicalDatastoreType.OPERATIONAL, id);
+        for (AdjRIBsOut r : ribs.values()) {
+            r.put(ribOut, key, null);
+        }
     }
 }
index 7497e3b3e81289c41ee8f4f995b587288aea2708..a3949d4d872d64a824f4c534b23ea4f352b6bd86 100644 (file)
@@ -18,6 +18,7 @@ import java.util.Set;
 
 import javax.annotation.concurrent.GuardedBy;
 
+import org.opendaylight.protocol.bgp.rib.impl.spi.AdjRIBsOutRegistration;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.protocol.bgp.rib.impl.spi.ReusableBGPPeer;
 import org.opendaylight.protocol.bgp.rib.spi.BGPSession;
@@ -43,8 +44,12 @@ public class BGPPeer implements ReusableBGPPeer, Peer, AutoCloseable {
     private final RIB rib;
     private final String name;
 
+    @GuardedBy("this")
     private BGPSession session;
+    @GuardedBy("this")
     private byte[] rawIdentifier;
+    @GuardedBy("this")
+    private AdjRIBsOutRegistration reg;
 
     public BGPPeer(final String name, final RIB rib) {
         this.rib = Preconditions.checkNotNull(rib);
@@ -79,6 +84,11 @@ public class BGPPeer implements ReusableBGPPeer, Peer, AutoCloseable {
             this.tables.add(key);
             this.rib.initTable(this, key);
         }
+
+        // Not particularly nice, but what can
+        if (session instanceof BGPSessionImpl) {
+            reg = rib.registerRIBsOut(this, new SessionRIBsOut((BGPSessionImpl) session));
+        }
     }
 
     private synchronized void cleanup() {
@@ -87,6 +97,11 @@ public class BGPPeer implements ReusableBGPPeer, Peer, AutoCloseable {
             this.rib.clearTable(this, key);
         }
 
+        if (reg != null) {
+            reg.close();
+            reg = null;
+        }
+
         this.tables.clear();
         this.session = null;
     }
@@ -129,6 +144,7 @@ public class BGPPeer implements ReusableBGPPeer, Peer, AutoCloseable {
         cleanup();
     }
 
+    @GuardedBy("this")
     private void dropConnection() {
         if (this.session != null) {
             this.session.close();
@@ -137,7 +153,7 @@ public class BGPPeer implements ReusableBGPPeer, Peer, AutoCloseable {
     }
 
     @Override
-    public byte[] getRawIdentifier() {
+    public synchronized byte[] getRawIdentifier() {
         return rawIdentifier;
     }
 }
index d940f7dc67f781af5e226bc1987729a8928aa46e..4c1cf57c67da2e01e86ef66bc033539774fe2e5c 100644 (file)
@@ -170,10 +170,10 @@ public class BGPSessionImpl extends AbstractProtocolSession<Notification> implem
         } else if (msg instanceof Notify) {
             // Notifications are handled internally
             LOG.info("Session closed because Notification message received: {} / {}", ((Notify) msg).getErrorCode(),
-                ((Notify) msg).getErrorSubcode());
+                    ((Notify) msg).getErrorSubcode());
             this.closeWithoutMessage();
             this.listener.onSessionTerminated(this, new BGPTerminationReason(BGPError.forValue(((Notify) msg).getErrorCode(),
-                ((Notify) msg).getErrorSubcode())));
+                    ((Notify) msg).getErrorSubcode())));
         } else if (msg instanceof Keepalive) {
             // Keepalives are handled internally
             LOG.trace("Received KeepAlive messsage.");
@@ -312,4 +312,14 @@ public class BGPSessionImpl extends AbstractProtocolSession<Notification> implem
     public final AsNumber getAsNumber() {
         return this.asNumber;
     }
+
+    synchronized boolean isWritable() {
+        return channel != null && channel.isWritable();
+    }
+
+    synchronized void schedule(final Runnable task) {
+        Preconditions.checkState(channel != null);
+        channel.eventLoop().submit(task);
+
+    }
 }
index 19d1e80d4b274275abcd894f84014892b895aa9e..00d2472ef87ce6d372eb4ea2dad877c40fabec31 100644 (file)
@@ -10,7 +10,7 @@ package org.opendaylight.protocol.bgp.rib.impl;
 import com.google.common.collect.Lists;
 
 import org.opendaylight.protocol.bgp.rib.spi.AbstractAdjRIBs;
-import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInTransaction;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsTransaction;
 import org.opendaylight.protocol.bgp.rib.spi.Peer;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.destination.destination.type.DestinationIpv4Case;
@@ -46,7 +46,7 @@ final class Ipv4AdjRIBsIn extends AbstractAdjRIBs<Ipv4Prefix, Ipv4Route, Ipv4Rou
     }
 
     @Override
-    public void addRoutes(final AdjRIBsInTransaction trans, final Peer peer, final MpReachNlri nlri,
+    public void addRoutes(final AdjRIBsTransaction trans, final Peer peer, final MpReachNlri nlri,
             final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes attributes) {
         final RIBEntryData<Ipv4Prefix, Ipv4Route, Ipv4RouteKey> data = new RIBEntryData<Ipv4Prefix, Ipv4Route, Ipv4RouteKey>(peer, attributes) {
             @Override
@@ -61,7 +61,7 @@ final class Ipv4AdjRIBsIn extends AbstractAdjRIBs<Ipv4Prefix, Ipv4Route, Ipv4Rou
     }
 
     @Override
-    public void removeRoutes(final AdjRIBsInTransaction trans, final Peer peer, final MpUnreachNlri nlri) {
+    public void removeRoutes(final AdjRIBsTransaction trans, final Peer peer, final MpUnreachNlri nlri) {
         for (final Ipv4Prefix id : ((DestinationIpv4Case) nlri.getWithdrawnRoutes().getDestinationType()).getDestinationIpv4().getIpv4Prefixes()) {
             super.remove(trans, peer, id);
         }
index 167f66ab7eceb389dab83bb5d05514b47f0187d4..3f1ebc61c162abfdc701287dba5e8c96b294c87c 100644 (file)
@@ -11,7 +11,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 
 import org.opendaylight.protocol.bgp.rib.spi.AbstractAdjRIBs;
-import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInTransaction;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsTransaction;
 import org.opendaylight.protocol.bgp.rib.spi.Peer;
 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.multiprotocol.rev130919.destination.destination.type.DestinationIpv6Case;
@@ -47,7 +47,7 @@ final class Ipv6AdjRIBsIn extends AbstractAdjRIBs<Ipv6Prefix, Ipv6Route, Ipv6Rou
     }
 
     @Override
-    public void addRoutes(final AdjRIBsInTransaction trans, final Peer peer, final MpReachNlri nlri,
+    public void addRoutes(final AdjRIBsTransaction trans, final Peer peer, final MpReachNlri nlri,
             final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes attributes) {
         final RIBEntryData<Ipv6Prefix, Ipv6Route, Ipv6RouteKey> data = new RIBEntryData<Ipv6Prefix, Ipv6Route, Ipv6RouteKey>(peer, attributes) {
             @Override
@@ -62,7 +62,7 @@ final class Ipv6AdjRIBsIn extends AbstractAdjRIBs<Ipv6Prefix, Ipv6Route, Ipv6Rou
     }
 
     @Override
-    public void removeRoutes(final AdjRIBsInTransaction trans, final Peer peer, final MpUnreachNlri nlri) {
+    public void removeRoutes(final AdjRIBsTransaction trans, final Peer peer, final MpUnreachNlri nlri) {
         for (final Ipv6Prefix id : ((DestinationIpv6) nlri.getWithdrawnRoutes().getDestinationType()).getIpv6Prefixes()) {
             super.remove(trans, peer, id);
         }
index d556d727d1a41fd76ef01001f3b6f060102f954e..58741c29f56d75f2e7bc7493e3eebce9434f3f77 100644 (file)
@@ -12,8 +12,8 @@ import com.google.common.collect.Lists;
 import java.util.List;
 
 import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBExtensionProviderActivator;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsFactory;
 import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
-import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInFactory;
 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext;
 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;
@@ -26,16 +26,16 @@ public final class RIBActivator extends AbstractRIBExtensionProviderActivator {
 
     @Override
     protected List<AutoCloseable> startRIBExtensionProviderImpl(final RIBExtensionProviderContext context) {
-        AdjRIBsInFactory adj1 = new AdjRIBsInFactory() {
+        AdjRIBsFactory adj1 = new AdjRIBsFactory() {
             @Override
-            public AdjRIBsIn createAdjRIBsIn(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
+            public AdjRIBsIn<?, ?> createAdjRIBs(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
                 return new Ipv4AdjRIBsIn(basePath);
             }
         };
 
-        AdjRIBsInFactory adj2 = new AdjRIBsInFactory() {
+        AdjRIBsFactory adj2 = new AdjRIBsFactory() {
             @Override
-            public AdjRIBsIn createAdjRIBsIn(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
+            public AdjRIBsIn<?, ?> createAdjRIBs(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
                 return new Ipv6AdjRIBsIn(basePath);
             }
         };
index 182ccf3a7bb9934a610714d28bcbb64a4ca88cab..f7c7236fb50fd12971fe63486ba0b8fd60c46d62 100644 (file)
@@ -17,6 +17,8 @@ import com.google.common.util.concurrent.Futures;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 
 import javax.annotation.concurrent.ThreadSafe;
@@ -26,6 +28,8 @@ import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.protocol.bgp.rib.DefaultRibReference;
+import org.opendaylight.protocol.bgp.rib.impl.spi.AdjRIBsOut;
+import org.opendaylight.protocol.bgp.rib.impl.spi.AdjRIBsOutRegistration;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
@@ -71,6 +75,7 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
     private static final Logger LOG = LoggerFactory.getLogger(RIBImpl.class);
     private static final Update EOR = new UpdateBuilder().build();
     private static final TablesKey IPV4_UNICAST_TABLE = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
+    private final ConcurrentMap<Peer, AdjRIBsOut> ribOuts = new ConcurrentHashMap<>();
     private final ReconnectStrategyFactory tcpStrategyFactory;
     private final ReconnectStrategyFactory sessionStrategyFactory;
     private final BGPObjectComparator comparator;
@@ -136,12 +141,12 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
 
     @Override
     public synchronized void updateTables(final Peer peer, final Update message) {
-        final AdjRIBsInTransactionImpl trans = new AdjRIBsInTransactionImpl(this.comparator, this.dps.newWriteOnlyTransaction());
+        final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(ribOuts, this.comparator, this.dps.newWriteOnlyTransaction());
 
         if (!EOR.equals(message)) {
             final WithdrawnRoutes wr = message.getWithdrawnRoutes();
             if (wr != null) {
-                final AdjRIBsIn ari = this.tables.get(IPV4_UNICAST_TABLE);
+                final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
                 if (ari != null) {
                     ari.removeRoutes(
                             trans,
@@ -161,7 +166,7 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
                 if (mpu != null) {
                     final MpUnreachNlri nlri = mpu.getMpUnreachNlri();
 
-                    final AdjRIBsIn ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
+                    final AdjRIBsIn<?, ?> ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
                     if (ari != null) {
                         ari.removeRoutes(trans, peer, nlri);
                     } else {
@@ -172,7 +177,7 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
 
             final Nlri ar = message.getNlri();
             if (ar != null) {
-                final AdjRIBsIn ari = this.tables.get(IPV4_UNICAST_TABLE);
+                final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
                 if (ari != null) {
                     final MpReachNlriBuilder b = new MpReachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(
                             UnicastSubsequentAddressFamily.class).setAdvertizedRoutes(
@@ -194,7 +199,7 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
                 if (mpr != null) {
                     final MpReachNlri nlri = mpr.getMpReachNlri();
 
-                    final AdjRIBsIn ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
+                    final AdjRIBsIn<?, ?> ari = this.tables.get(new TablesKey(nlri.getAfi(), nlri.getSafi()));
                     if (ari != null) {
                         if (message.equals(ari.endOfRib())) {
                             ari.markUptodate(trans, peer);
@@ -207,7 +212,7 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
                 }
             }
         } else {
-            final AdjRIBsIn ari = this.tables.get(IPV4_UNICAST_TABLE);
+            final AdjRIBsIn<?, ?> ari = this.tables.get(IPV4_UNICAST_TABLE);
             if (ari != null) {
                 ari.markUptodate(trans, peer);
             } else {
@@ -230,9 +235,9 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
 
     @Override
     public synchronized void clearTable(final Peer peer, final TablesKey key) {
-        final AdjRIBsIn ari = this.tables.get(key);
+        final AdjRIBsIn<?, ?> ari = this.tables.get(key);
         if (ari != null) {
-            final AdjRIBsInTransactionImpl trans = new AdjRIBsInTransactionImpl(comparator, this.dps.newWriteOnlyTransaction());
+            final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(ribOuts, comparator, this.dps.newWriteOnlyTransaction());
             ari.clear(trans, peer);
 
             Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
@@ -299,4 +304,18 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
     public void initTable(final Peer bgpPeer, final TablesKey key) {
         // FIXME: BUG-196: support graceful restart
     }
+
+    @Override
+    public AdjRIBsOutRegistration registerRIBsOut(final Peer peer, final AdjRIBsOut aro) {
+        final AdjRIBsOutRegistration reg = new AdjRIBsOutRegistration(aro) {
+            @Override
+            protected void removeRegistration() {
+                ribOuts.remove(peer, aro);
+            }
+        };
+
+        ribOuts.put(peer, aro);
+        // FIXME: schedule a walk over all the tables
+        return reg;
+    }
 }
index 6a92ff840be5c4b1f5b1d30cf9f41cceb65cf602..d41d3b5ef680ed6441cb098e593fe533e28c503b 100644 (file)
@@ -15,8 +15,8 @@ import java.util.Map;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.protocol.bgp.rib.RibReference;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsFactory;
 import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsIn;
-import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInFactory;
 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRib;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
@@ -31,34 +31,34 @@ final class RIBTables {
 
     private static final Logger LOG = LoggerFactory.getLogger(RIBTables.class);
 
-    private final Map<TablesKey, AdjRIBsIn> tables = new HashMap<>();
+    private final Map<TablesKey, AdjRIBsIn<?, ?>> tables = new HashMap<>();
     private final RIBExtensionConsumerContext registry;
 
     RIBTables(final RIBExtensionConsumerContext extensions) {
         this.registry = Preconditions.checkNotNull(extensions);
     }
 
-    public synchronized AdjRIBsIn get(final TablesKey key) {
+    public synchronized AdjRIBsIn<?, ?> get(final TablesKey key) {
         LOG.debug("Looking for key {} in tables {}", key, this.tables);
-        final AdjRIBsIn ret = this.tables.get(key);
+        final AdjRIBsIn<?, ?> ret = this.tables.get(key);
         LOG.trace("Key found {}", ret);
         return ret;
     }
 
-    public synchronized AdjRIBsIn create(final WriteTransaction trans, final RibReference rib, final TablesKey key) {
+    public synchronized AdjRIBsIn<?, ?> create(final WriteTransaction trans, final RibReference rib, final TablesKey key) {
         if (this.tables.containsKey(key)) {
             LOG.warn("Duplicate create request for key {}", key);
             return this.tables.get(key);
         }
 
-        final AdjRIBsInFactory f = this.registry.getAdjRIBsInFactory(key.getAfi(), key.getSafi());
+        final AdjRIBsFactory f = this.registry.getAdjRIBsInFactory(key.getAfi(), key.getSafi());
         if (f == null) {
             LOG.debug("RIBsInFactory not found for key {}, returning null", key);
             return null;
         }
 
         final KeyedInstanceIdentifier<Tables, TablesKey> basePath = rib.getInstanceIdentifier().child(LocRib.class).child(Tables.class, key);
-        final AdjRIBsIn table = Preconditions.checkNotNull(f.createAdjRIBsIn(basePath));
+        final AdjRIBsIn<?, ?> table = Preconditions.checkNotNull(f.createAdjRIBs(basePath));
         LOG.debug("Table {} created for key {}", table, key);
         this.tables.put(key, table);
 
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/SessionRIBsOut.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/SessionRIBsOut.java
new file mode 100644 (file)
index 0000000..352420f
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014 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 com.google.common.base.Preconditions;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
+
+final class SessionRIBsOut extends AbstractAdjRIBsOut implements Runnable {
+    private final AtomicBoolean scheduled = new AtomicBoolean(false);
+    private final BGPSessionImpl session;
+
+    SessionRIBsOut(final BGPSessionImpl session) {
+        this.session = Preconditions.checkNotNull(session);
+    }
+
+    @Override
+    protected void wantWrite() {
+        if (scheduled.compareAndSet(false, true)) {
+            session.schedule(this);
+        }
+    }
+
+    @Override
+    protected boolean writePDU(final Update pdu) {
+        session.sendMessage(pdu);
+        return session.isWritable();
+    }
+
+    @Override
+    public void run() {
+        process();
+    }
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/AdjRIBsOut.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/AdjRIBsOut.java
new file mode 100644 (file)
index 0000000..4bd7943
--- /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.impl.spi;
+
+import org.opendaylight.protocol.bgp.rib.spi.RouteEncoder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
+
+public interface AdjRIBsOut {
+    public void put(final RouteEncoder ribOut, final Object key, final Route newValue);
+}
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/AdjRIBsOutRegistration.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/AdjRIBsOutRegistration.java
new file mode 100644 (file)
index 0000000..6991074
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2014 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.spi;
+
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+
+public abstract class AdjRIBsOutRegistration extends AbstractObjectRegistration<AdjRIBsOut> {
+    protected AdjRIBsOutRegistration(final AdjRIBsOut instance) {
+        super(instance);
+    }
+}
index c60228f3249d0cfee503f645a433bbd86ae3b6c2..6d74d5f5a39bec0cb25c707954b9fc30b6fb5463 100644 (file)
@@ -38,4 +38,6 @@ public interface RIB {
     ReconnectStrategyFactory getTcpStrategyFactory();
 
     ReconnectStrategyFactory getSessionStrategyFactory();
+
+    AdjRIBsOutRegistration registerRIBsOut(Peer bgpPeer, AdjRIBsOut aro);
 }
index 490f04b6f22721b975f9e8f599c797019bb890f9..ae615d69948fcc08017d0aa2a08d514d131fe05a 100644 (file)
@@ -18,7 +18,7 @@ import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.protocol.bgp.rib.spi.AbstractAdjRIBs;
-import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsInTransaction;
+import org.opendaylight.protocol.bgp.rib.spi.AdjRIBsTransaction;
 import org.opendaylight.protocol.bgp.rib.spi.BGPObjectComparator;
 import org.opendaylight.protocol.bgp.rib.spi.Peer;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
@@ -185,13 +185,13 @@ public class BestPathSelectionTest {
         }
 
         @Override
-        public void addRoutes(final AdjRIBsInTransaction trans, final Peer peer, final MpReachNlri nlri,
+        public void addRoutes(final AdjRIBsTransaction trans, final Peer peer, final MpReachNlri nlri,
                 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes attributes) {
             return;
         }
 
         @Override
-        public void removeRoutes(final AdjRIBsInTransaction trans, final Peer peer, final MpUnreachNlri nlri) {
+        public void removeRoutes(final AdjRIBsTransaction trans, final Peer peer, final MpUnreachNlri nlri) {
             return;
         }
 
index a732ffc28829083faea22b048452c37e25b14eaa..5a96fe8701d6e360be3608e64b1412ca2e9f5c6d 100644 (file)
@@ -18,12 +18,16 @@ import java.util.Map;
 import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.ThreadSafe;
 
+import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
 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.BgpTableType;
 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.PathAttributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2Builder;
 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.multiprotocol.rev130919.update.path.attributes.MpUnreachNlriBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
@@ -37,7 +41,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @ThreadSafe
-public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K extends Identifier<D>> implements AdjRIBsIn {
+public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K extends Identifier<D>> implements AdjRIBsIn<I, D>, RouteEncoder {
     protected abstract static class RIBEntryData<I, D extends Identifiable<K> & Route, K extends Identifier<D>> {
         private final PathAttributes attributes;
         private final Peer peer;
@@ -116,17 +120,17 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
             return newState;
         }
 
-        private void electCandidate(final AdjRIBsInTransaction transaction, final RIBEntryData<I, D, K> candidate) {
+        private void electCandidate(final AdjRIBsTransaction transaction, final RIBEntryData<I, D, K> candidate) {
             LOG.trace("Electing state {} to supersede {}", candidate, this.currentState);
 
             if (this.currentState == null || !this.currentState.equals(candidate)) {
                 LOG.trace("Elected new state for {}: {}", getName(), candidate);
-                transaction.advertise(getName(), candidate.getDataObject(this.key, getName().getKey()));
+                transaction.advertise(AbstractAdjRIBs.this, this.key, getName(), candidate.getPeer(), candidate.getDataObject(this.key, getName().getKey()));
                 this.currentState = candidate;
             }
         }
 
-        synchronized boolean removeState(final AdjRIBsInTransaction transaction, final Peer peer) {
+        synchronized boolean removeState(final AdjRIBsTransaction transaction, final Peer peer) {
             final RIBEntryData<I, D, K> data = this.candidates.remove(peer);
             LOG.trace("Removed data {}", data);
 
@@ -135,20 +139,21 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
                 electCandidate(transaction, candidate);
             } else {
                 LOG.trace("Final candidate disappeared, removing entry {}", getName());
-                transaction.withdraw(getName());
+                transaction.withdraw(AbstractAdjRIBs.this, this.key, getName());
             }
 
             return this.candidates.isEmpty();
         }
 
-        synchronized void setState(final AdjRIBsInTransaction transaction, final Peer peer, final RIBEntryData<I, D, K> state) {
+        synchronized void setState(final AdjRIBsTransaction transaction, final Peer peer, final RIBEntryData<I, D, K> state) {
             this.candidates.put(Preconditions.checkNotNull(peer), Preconditions.checkNotNull(state));
             electCandidate(transaction, findCandidate(transaction.comparator(), state));
         }
     }
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractAdjRIBs.class);
-    private final InstanceIdentifier<Tables> basePath;
+    private final KeyedInstanceIdentifier<Tables, TablesKey> basePath;
+    private final BgpTableType tableType;
     private final Update eor;
 
     @GuardedBy("this")
@@ -159,13 +164,15 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
 
     protected AbstractAdjRIBs(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
         this.basePath = Preconditions.checkNotNull(basePath);
+        this.tableType = new BgpTableTypeImpl(basePath.getKey().getAfi(), basePath.getKey().getSafi());
         this.eor = new UpdateBuilder().setPathAttributes(new PathAttributesBuilder().addAugmentation(
-                        PathAttributes1.class, new PathAttributes1Builder().setMpReachNlri(new MpReachNlriBuilder()
-                            .setAfi(basePath.getKey().getAfi()).setSafi(basePath.getKey().getSafi()).build()).build()).build()).build();
+                PathAttributes1.class, new PathAttributes1Builder().setMpReachNlri(new MpReachNlriBuilder(this.tableType)
+                    .build()).build()).build()).build();
+
     }
 
     @Override
-    public final synchronized void clear(final AdjRIBsInTransaction trans, final Peer peer) {
+    public final synchronized void clear(final AdjRIBsTransaction trans, final Peer peer) {
         final Iterator<Map.Entry<I, RIBEntry>> i = this.entries.entrySet().iterator();
         while (i.hasNext()) {
             final Map.Entry<I, RIBEntry> e = i.next();
@@ -211,7 +218,7 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
      * @param id Data store instance identifier
      * @param data Data object to be written
      */
-    protected final synchronized void add(final AdjRIBsInTransaction trans, final Peer peer, final I id, final RIBEntryData<I, D, K> data) {
+    protected final synchronized void add(final AdjRIBsTransaction trans, final Peer peer, final I id, final RIBEntryData<I, D, K> data) {
         LOG.debug("Adding state {} for {} peer {}", data, id, peer);
 
         RIBEntry e = this.entries.get(Preconditions.checkNotNull(id));
@@ -234,7 +241,7 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
      * @param peer Originating peer
      * @param id Data store instance identifier
      */
-    protected final synchronized void remove(final AdjRIBsInTransaction trans, final Peer peer, final I id) {
+    protected final synchronized void remove(final AdjRIBsTransaction trans, final Peer peer, final I id) {
         final RIBEntry e = this.entries.get(id);
         if (e != null && e.removeState(trans, peer)) {
             LOG.debug("Removed last state, removing entry for {}", id);
@@ -243,7 +250,7 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
     }
 
     @Override
-    public final void markUptodate(final AdjRIBsInTransaction trans, final Peer peer) {
+    public final void markUptodate(final AdjRIBsTransaction trans, final Peer peer) {
         this.peers.put(peer, Boolean.TRUE);
         trans.setUptodate(this.basePath, !this.peers.values().contains(Boolean.FALSE));
     }
@@ -252,4 +259,26 @@ public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K ex
     public final Update endOfRib() {
         return this.eor;
     }
+
+    @Override
+    public Update updateMessageFor(final Object key, final Route route) {
+        final UpdateBuilder ub = new UpdateBuilder();
+        final PathAttributesBuilder pab = new PathAttributesBuilder();
+
+        if (route != null) {
+            final MpReachNlriBuilder reach = new MpReachNlriBuilder(this.tableType);
+
+            addAdvertisement(reach, (D)route);
+            pab.fieldsFrom(route.getAttributes());
+            pab.addAugmentation(PathAttributes1.class, new PathAttributes1Builder().setMpReachNlri(reach.build()).build()).build();
+        } else {
+            final MpUnreachNlriBuilder unreach = new MpUnreachNlriBuilder(tableType);
+            addWithdrawal(unreach, (I)key);
+            pab.addAugmentation(PathAttributes2.class, new PathAttributes2Builder().setMpUnreachNlri(unreach.build()).build()).build();
+        }
+
+        ub.setPathAttributes(pab.build());
+        return ub.build();
+    }
+
 }
similarity index 83%
rename from bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInFactory.java
rename to bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsFactory.java
index 1f5cfb252dadf3474d80d3d51199c52ae2ffbc9c..4110ddbb0ecf55aebbcbc7f985e34362c75ab689 100644 (file)
@@ -11,6 +11,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
-public interface AdjRIBsInFactory {
-    AdjRIBsIn createAdjRIBsIn(final KeyedInstanceIdentifier<Tables, TablesKey> basePath);
+public interface AdjRIBsFactory {
+    AdjRIBsIn<?, ?> createAdjRIBs(final KeyedInstanceIdentifier<Tables, TablesKey> basePath);
 }
index b443e17e9891ec8fd5770600d3924cefc2b62c52..0c48e496b869a63d2f1bc54f0c1ee45cb6315af0 100644 (file)
@@ -11,15 +11,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
 
-public interface AdjRIBsIn {
-    void addRoutes(AdjRIBsInTransaction trans, Peer peer, MpReachNlri nlri, PathAttributes attributes);
+public interface AdjRIBsIn<K, V extends Route> {
+    void addRoutes(AdjRIBsTransaction trans, Peer peer, MpReachNlri nlri, PathAttributes attributes);
 
-    void removeRoutes(AdjRIBsInTransaction trans, Peer peer, MpUnreachNlri nlri);
+    void removeRoutes(AdjRIBsTransaction trans, Peer peer, MpUnreachNlri nlri);
 
-    void clear(AdjRIBsInTransaction trans, Peer peer);
+    void clear(AdjRIBsTransaction trans, Peer peer);
 
-    void markUptodate(AdjRIBsInTransaction trans, Peer peer);
+    void markUptodate(AdjRIBsTransaction trans, Peer peer);
 
     Update endOfRib();
 }
similarity index 67%
rename from bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsInTransaction.java
rename to bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AdjRIBsTransaction.java
index a799ce48459295c388fe02d4db74cd258701a570..78c2f0a5b5dae08e4055ff6ab3259f760102ba7f 100644 (file)
@@ -7,18 +7,17 @@
  */
 package org.opendaylight.protocol.bgp.rib.spi;
 
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /**
  * An execution context for a single LocRib transaction.
  */
-public interface AdjRIBsInTransaction {
+public interface AdjRIBsTransaction {
 
     BGPObjectComparator comparator();
     void setUptodate(InstanceIdentifier<Tables> basePath, boolean uptodate);
-    <T extends DataObject> void advertise(final InstanceIdentifier<T> id, final T obj);
-    void withdraw(final InstanceIdentifier<?> id);
-
+    <K, T extends Route> void advertise(RouteEncoder ribOut, K key, InstanceIdentifier<T> id, Peer peer, T obj);
+    <K, T extends Route> void withdraw(RouteEncoder ribOut, K key, InstanceIdentifier<T> id);
 }
index 3abdbb8d32a994a62bcc45147a3f1faad230bc69..08f5b4889f807c0f0c65cb0e28824e2b37d857cd 100644 (file)
@@ -16,5 +16,5 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.type
  * exposes an interface for registration of factories for creating AdjRIBsIn instances, which handle the specifics.
  */
 public interface RIBExtensionConsumerContext {
-    AdjRIBsInFactory getAdjRIBsInFactory(Class<? extends AddressFamily> afi, Class<? extends SubsequentAddressFamily> safi);
+    AdjRIBsFactory getAdjRIBsInFactory(Class<? extends AddressFamily> afi, Class<? extends SubsequentAddressFamily> safi);
 }
\ No newline at end of file
index 71d6816b1ec651aa728f87509ed14d242402e0c6..0995b85e046650f9fbb5c05a78063dc3ffb55a8c 100644 (file)
@@ -25,5 +25,5 @@ public interface RIBExtensionProviderContext extends RIBExtensionConsumerContext
      * @return Registration handle. Call its close() method to remove it.
      */
     AutoCloseable registerAdjRIBsInFactory(Class<? extends AddressFamily> afi, Class<? extends SubsequentAddressFamily> safi,
-            AdjRIBsInFactory factory);
+            AdjRIBsFactory factory);
 }
\ No newline at end of file
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/RouteEncoder.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/RouteEncoder.java
new file mode 100644 (file)
index 0000000..5c44705
--- /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;
+
+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.rib.rev130925.Route;
+
+public interface RouteEncoder {
+    Update updateMessageFor(Object key, Route route);
+}
index 077d813913a89b6649d503de91b0b2ab8c766850..bea86bce9433b307fb2a300a389745b79937c148 100644 (file)
@@ -16,11 +16,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.type
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
 
 public class SimpleRIBExtensionProviderContext implements RIBExtensionProviderContext {
-    private final Map<TablesKey, AdjRIBsInFactory> factories = new ConcurrentHashMap<>();
+    private final Map<TablesKey, AdjRIBsFactory> factories = new ConcurrentHashMap<>();
 
     @Override
     public final synchronized AbstractRegistration registerAdjRIBsInFactory(final Class<? extends AddressFamily> afi,
-            final Class<? extends SubsequentAddressFamily> safi, final AdjRIBsInFactory factory) {
+            final Class<? extends SubsequentAddressFamily> safi, final AdjRIBsFactory factory) {
         final TablesKey key = new TablesKey(afi, safi);
 
         if (this.factories.containsKey(key)) {
@@ -41,7 +41,7 @@ public class SimpleRIBExtensionProviderContext implements RIBExtensionProviderCo
     }
 
     @Override
-    public final synchronized AdjRIBsInFactory getAdjRIBsInFactory(final Class<? extends AddressFamily> afi,
+    public final synchronized AdjRIBsFactory getAdjRIBsInFactory(final Class<? extends AddressFamily> afi,
             final Class<? extends SubsequentAddressFamily> safi) {
         return this.factories.get(new TablesKey(afi, safi));
     }