BUG-5511: Support Route Refresh operation from BGP 55/36555/14
authorIveta Halanova <ihalanov@cisco.com>
Tue, 22 Mar 2016 14:35:31 +0000 (15:35 +0100)
committerIveta Halanova <ihalanov@cisco.com>
Tue, 12 Apr 2016 11:38:55 +0000 (11:38 +0000)
Created module for peer-rpc request.
Implemented class for handling input.
Updated unit tests

Change-Id: I1e0f24acc9eb713c9c60f4ab977e7efd892f563a
Signed-off-by: Iveta Halanova <ihalanov@cisco.com>
15 files changed:
bgp/controller-config/src/main/resources/initial/41-bgp-example.xml
bgp/rib-api/src/main/yang/bgp-peer-rpc.yang [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPApplicationPeerModule.java
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.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/BGPSessionImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BgpPeerRpc.java [new file with mode: 0644]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ChannelOutputLimiter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/RIB.java
bgp/rib-impl/src/main/yang/odl-bgp-rib-impl-cfg.yang
bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/AbstractRIBImplModuleTest.java
bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModuleTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BgpPeerRpcTest.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserToSalTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java

index 4e159fcea8152fa77a74c760940c0581299e544a..e1d3671292fdc4671663a5d8f250060d89af17cc 100755 (executable)
                         <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:bgp:rib:impl">prefix:bgp-peer-registry</type>
                         <name>global-bgp-peer-registry</name>
                     </peer-registry>
+                    <rpc-registry>
+                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+                        <name>binding-rpc-broker</name>
+                    </rpc-registry>
                     <advertized-table>
                         <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:bgp:rib:impl">prefix:bgp-table-type</type>
                         <name>ipv4-unicast</name>
diff --git a/bgp/rib-api/src/main/yang/bgp-peer-rpc.yang b/bgp/rib-api/src/main/yang/bgp-peer-rpc.yang
new file mode 100644 (file)
index 0000000..5a0d6a1
--- /dev/null
@@ -0,0 +1,57 @@
+module bgp-peer-rpc {
+    namespace "urn:opendaylight:params:xml:ns:yang:bgp-peer-rpc";
+    prefix "bgp-rpc";
+
+    import bgp-multiprotocol { prefix bgp-mp; revision-date 2013-09-19; }
+    import bgp-rib { prefix rib; revision-date 2013-09-25; }
+    import yang-ext { prefix ext; revision-date "2013-07-09"; }
+
+    organization "Cisco Systems, Inc.";
+    contact "Iveta Halanova <ihalanov@cisco.com>";
+
+    description
+        "Module contains rpc for route refresh request, which is described in rfc2918.
+
+        Copyright (c) 2016 Cisco Systems, Inc. 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";
+
+    revision 2016-03-22 {
+        description "Initial revision";
+    }
+
+    identity peer-context {
+        description "Identity used to mark the Peer context for binding RPCs in a particular RIB.";
+    }
+
+    typedef peer-ref {
+        type instance-identifier;
+        ext:context-reference "peer-context";
+    }
+
+    grouping peer-reference {
+        leaf peer-ref {
+            type peer-ref;
+            mandatory true;
+            ext:context-reference "peer-context";
+        }
+    }
+
+    grouping rr-msg-args {
+        uses peer-reference;
+        uses bgp-mp:bgp-table-type;
+    }
+
+    rpc route-refresh-request {
+        input {
+            uses rr-msg-args;
+        }
+    }
+
+    augment "/rib:bgp-rib/rib:rib/rib:peer" {
+        ext:context-instance "peer-context";
+    }
+}
\ No newline at end of file
index 92b60a9cc89e26caa0e46892df5ee773d46fc9e5..21ab950b1397d015a5e2f43f6ccadd19cd208741 100755 (executable)
@@ -79,7 +79,7 @@ public class BGPApplicationPeerModule extends org.opendaylight.controller.config
         final RIB r = getTargetRibDependency();
 
         final IpAddress bgpPeerId = new IpAddress(getBgpPeerId());
-        final BGPPeer bgpClientPeer = new BGPPeer(bgpPeerId.getIpv4Address().getValue(), r, PeerRole.Internal);
+        final BGPPeer bgpClientPeer = new BGPPeer(bgpPeerId.getIpv4Address().getValue(), r, PeerRole.Internal, null);
 
         final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), 0, r.getBgpIdentifier(),
             r.getLocalAs(), Collections.emptyList());
@@ -105,26 +105,26 @@ public class BGPApplicationPeerModule extends org.opendaylight.controller.config
 
         public AppPeerModuleTracker(final Optional<BGPOpenConfigProvider> openConfigProvider) {
             if (openConfigProvider.isPresent()) {
-                appProvider = openConfigProvider.get().getOpenConfigMapper(BGPAppPeerInstanceConfiguration.class);
+                this.appProvider = openConfigProvider.get().getOpenConfigMapper(BGPAppPeerInstanceConfiguration.class);
             } else {
-                appProvider = null;
+                this.appProvider = null;
             }
             final InstanceConfigurationIdentifier identifier = new InstanceConfigurationIdentifier(getIdentifier().getInstanceName());
-            bgpAppPeerInstanceConfiguration = new BGPAppPeerInstanceConfiguration(identifier, getApplicationRibId().getValue(),
+            this.bgpAppPeerInstanceConfiguration = new BGPAppPeerInstanceConfiguration(identifier, getApplicationRibId().getValue(),
                     Rev130715Util.getIpv4Address(getBgpPeerId()));
         }
 
         @Override
         public void onInstanceCreate() {
-            if (appProvider != null) {
-                appProvider.writeConfiguration(this.bgpAppPeerInstanceConfiguration);
+            if (this.appProvider != null) {
+                this.appProvider.writeConfiguration(this.bgpAppPeerInstanceConfiguration);
             }
         }
 
         @Override
         public void onInstanceClose() {
-            if (appProvider != null) {
-                appProvider.removeConfiguration(this.bgpAppPeerInstanceConfiguration);
+            if (this.appProvider != null) {
+                this.appProvider.removeConfiguration(this.bgpAppPeerInstanceConfiguration);
             }
         }
 
index 359c8f661678b26eb2312abbd73786ad5398d9c0..cb673e032fc4137316da7cbd4bcd6e35b7c1c1cf 100755 (executable)
@@ -134,9 +134,9 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
         final BGPPeer bgpClientPeer;
         final IpAddress host = getNormalizedHost();
         if (getPeerRole() != null) {
-            bgpClientPeer = new BGPPeer(peerName(host), r, getPeerRole());
+            bgpClientPeer = new BGPPeer(peerName(host), r, getPeerRole(), getRpcRegistryDependency());
         } else {
-            bgpClientPeer = new BGPPeer(peerName(host), r, PeerRole.Ibgp);
+            bgpClientPeer = new BGPPeer(peerName(host), r, PeerRole.Ibgp, getRpcRegistryDependency());
         }
 
         bgpClientPeer.registerRootRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
index 336f36f7f6586ac6350d062a9b985b443d08b45c..9214214a083c5ad6230aeb993a9b8fadea02184d 100644 (file)
@@ -30,6 +30,8 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionStatistics;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
@@ -57,13 +59,17 @@ 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.attributes.MpUnreachNlriBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev160322.BgpPeerRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev160322.PeerContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.PeerKey;
 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.SubsequentAddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -93,16 +99,15 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
     private BGPPeerRuntimeRegistration runtimeReg;
     private long sessionEstablishedCounter = 0L;
     private final Map<TablesKey, AdjRibOutListener> adjRibOutListenerSet = new HashMap();
+    private final RpcProviderRegistry rpcRegistry;
+    private RoutedRpcRegistration<BgpPeerRpcService> rpcRegistration;
 
-    public BGPPeer(final String name, final RIB rib) {
-        this(name, rib, PeerRole.Ibgp);
-    }
-
-    public BGPPeer(final String name, final RIB rib, final PeerRole role) {
+    public BGPPeer(final String name, final RIB rib, final PeerRole role, final RpcProviderRegistry rpcRegistry) {
         this.rib = Preconditions.checkNotNull(rib);
         this.name = name;
         this.chain = rib.createPeerChain(this);
         this.ribWriter = AdjRibInWriter.create(rib.getYangRibId(), role, this.chain);
+        this.rpcRegistry = rpcRegistry;
     }
 
     @Override
@@ -225,6 +230,7 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
         LOG.info("Session with peer {} went up with tables {} and Add Path tables {}", this.name, addPathTablesType,
             session.getAdvertisedAddPathTableTypes());
         this.session = session;
+
         this.rawIdentifier = InetAddresses.forString(session.getBgpId().getValue()).getAddress();
         final PeerId peerId = RouterIds.createPeerId(session.getBgpId());
         createAdjRibOutListener(peerId);
@@ -234,6 +240,13 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
         if (this.registrator != null) {
             this.runtimeReg = this.registrator.register(this);
         }
+
+        if (this.rpcRegistry != null) {
+            this.rpcRegistration = this.rpcRegistry.addRoutedRpcImplementation(BgpPeerRpcService.class, new BgpPeerRpc(session, this.tables));
+            final KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer, PeerKey> path =
+                this.rib.getInstanceIdentifier().child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer.class, new PeerKey(peerId));
+            this.rpcRegistration.registerPath(PeerContext.class, path);
+        }
     }
 
     private void createAdjRibOutListener(final PeerId peerId) {
@@ -309,6 +322,9 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
 
     @Override
     public void releaseConnection() {
+        if (this.rpcRegistration != null) {
+            this.rpcRegistration.close();
+        }
         addPeerToDisconnectedSharedList();
         cleanup();
         dropConnection();
index 7f8812066a890b6277f55ae56ce155e0a1892303..ce8f658cf1d3991241aee1cf61166e2acbde5d43 100644 (file)
@@ -252,7 +252,7 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
     }
 
     @GuardedBy("this")
-    private void writeEpilogue(final ChannelFuture future, final Notification msg) {
+    private ChannelFuture writeEpilogue(final ChannelFuture future, final Notification msg) {
         future.addListener(
                 new ChannelFutureListener() {
                     @Override
@@ -271,6 +271,7 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
         } else if (msg instanceof Notify) {
             this.sessionStats.updateSentMsgErr((Notify) msg);
         }
+        return future;
     }
 
     void flush() {
@@ -285,8 +286,8 @@ public class BGPSessionImpl extends SimpleChannelInboundHandler<Notification> im
         }
     }
 
-    synchronized void writeAndFlush(final Notification msg) {
-        writeEpilogue(this.channel.writeAndFlush(msg), msg);
+    synchronized ChannelFuture writeAndFlush(final Notification msg) {
+        return writeEpilogue(this.channel.writeAndFlush(msg), msg);
     }
 
     private synchronized void closeWithoutMessage() {
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BgpPeerRpc.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BgpPeerRpc.java
new file mode 100644 (file)
index 0000000..26a12fb
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 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.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import io.netty.channel.ChannelFuture;
+import java.util.Set;
+import java.util.concurrent.Future;
+import org.opendaylight.protocol.bgp.rib.spi.BGPSession;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefresh;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefreshBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev160322.BgpPeerRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev160322.RouteRefreshRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpPeerRpc implements BgpPeerRpcService {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BgpPeerRpc.class);
+    private static final String FAILURE_MSG = "Failed to send Route Refresh message";
+
+    private final BGPSession session;
+    private final Set<TablesKey> supportedFamilies;
+
+    BgpPeerRpc(final BGPSession session, final Set<TablesKey> supportedFamilies) {
+        this.session = Preconditions.checkNotNull(session);
+        this.supportedFamilies = Preconditions.checkNotNull(supportedFamilies);
+    }
+
+    @Override
+    public Future<RpcResult<Void>> routeRefreshRequest(final RouteRefreshRequestInput input) {
+        final ChannelFuture f = sendRRMessage(input);
+        if (f != null) {
+            return Futures.transform(JdkFutureAdapters.listenInPoolThread(f), new Function<Void, RpcResult<Void>>() {
+                @Override
+                public RpcResult<Void> apply(final Void input) {
+                    if (f.isSuccess()) {
+                        return RpcResultBuilder.<Void>success().build();
+                    } else {
+                        return RpcResultBuilder.<Void>failed().withError(ErrorType.RPC, FAILURE_MSG).build();
+                    }
+                }
+            });
+        }
+        return RpcResultBuilder.<Void>failed().withError(ErrorType.RPC, FAILURE_MSG + " due to unsupported address families.").buildFuture();
+    }
+
+    private ChannelFuture sendRRMessage(final RouteRefreshRequestInput input) {
+        if (!this.supportedFamilies.contains(new TablesKey(input.getAfi(), input.getSafi()))) {
+            LOG.info("Unsupported afi/safi: {}, {}.", input.getAfi(), input.getSafi());
+            return null;
+        }
+        final RouteRefresh msg = new RouteRefreshBuilder().setAfi(input.getAfi()).setSafi(input.getSafi()).build();
+        return ((BGPSessionImpl) this.session).getLimiter().writeAndFlush(msg);
+    }
+
+}
index 21150b9431bc9b6fddeb25ac645425edae7deec7..bf1d253ef66ab4be6a2f4583764eae06d129e62b 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.protocol.bgp.rib.impl;
 
 import com.google.common.base.Preconditions;
+import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import javax.annotation.concurrent.ThreadSafe;
@@ -30,35 +31,35 @@ final class ChannelOutputLimiter extends ChannelInboundHandlerAdapter {
     }
 
     private void ensureWritable() {
-        if (blocked) {
-            LOG.trace("Blocked slow path tripped on session {}", session);
+        if (this.blocked) {
+            LOG.trace("Blocked slow path tripped on session {}", this.session);
             synchronized (this) {
-                while (blocked) {
+                while (this.blocked) {
                     try {
-                        LOG.debug("Waiting for session {} to become writable", session);
+                        LOG.debug("Waiting for session {} to become writable", this.session);
                         this.wait();
-                    } catch (InterruptedException e) {
+                    } catch (final InterruptedException e) {
                         throw new IllegalStateException("Interrupted while waiting for channel to come back", e);
                     }
                 }
 
-                LOG.debug("Resuming write on session {}", session);
+                LOG.debug("Resuming write on session {}", this.session);
             }
         }
     }
 
     void write(final Notification msg) {
         ensureWritable();
-        session.write(msg);
+        this.session.write(msg);
     }
 
-    void writeAndFlush(final Notification msg) {
+    ChannelFuture writeAndFlush(final Notification msg) {
         ensureWritable();
-        session.writeAndFlush(msg);
+        return this.session.writeAndFlush(msg);
     }
 
     void flush() {
-        session.flush();
+        this.session.flush();
     }
 
     @Override
@@ -66,8 +67,8 @@ final class ChannelOutputLimiter extends ChannelInboundHandlerAdapter {
         final boolean w = ctx.channel().isWritable();
 
         synchronized (this) {
-            blocked = !w;
-            LOG.debug("Writes on session {} {}", session, w ? "unblocked" : "blocked");
+            this.blocked = !w;
+            LOG.debug("Writes on session {} {}", this.session, w ? "unblocked" : "blocked");
 
             if (w) {
                 this.notifyAll();
@@ -82,7 +83,7 @@ final class ChannelOutputLimiter extends ChannelInboundHandlerAdapter {
     @Override
     public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
         synchronized (this) {
-            blocked = false;
+            this.blocked = false;
             this.notifyAll();
         }
 
index b356349b42144aeba781846a82b2d0eb810c6ff4..c8c086d9f75091cd5e5b646f1d77ceeefe602ba2 100755 (executable)
@@ -13,6 +13,7 @@ import javax.annotation.Nonnull;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigProvider;
+import org.opendaylight.protocol.bgp.rib.RibReference;
 import org.opendaylight.protocol.bgp.rib.spi.CacheDisconnectedPeers;
 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
@@ -24,7 +25,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 /**
  * Internal reference to a RIB instance.
  */
-public interface RIB {
+public interface RIB  extends RibReference {
     AsNumber getLocalAs();
 
     Ipv4Address getBgpIdentifier();
index 6828a0fbc7f6ac68dfeddf28269cec70f2a84c42..801d563e92cf9ced0b781ef6be291bc888a946f2 100644 (file)
@@ -429,6 +429,14 @@ module odl-bgp-rib-impl-cfg {
                     }
                 }
             }
+            container rpc-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsb:binding-rpc-registry;
+                    }
+                }
+            }
         }
     }
 
index c4e590c18ff52f31f3e9bb2dca5b2d1dae6e6a63..eee2809f011479b0f20db06d0bbc0765f99ee1fe 100755 (executable)
@@ -9,7 +9,6 @@ package org.opendaylight.controller.config.yang.bgp.rib.impl;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
-
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.io.ByteSource;
@@ -44,8 +43,14 @@ import org.opendaylight.controller.config.yang.bgp.rib.spi.RIBExtensionsImplModu
 import org.opendaylight.controller.config.yang.bgp.rib.spi.RIBExtensionsImplModuleMXBean;
 import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingAsyncDataBrokerImplModuleFactory;
 import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingAsyncDataBrokerImplModuleMXBean;
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingBrokerImplModuleFactory;
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingBrokerImplModuleMXBean;
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.ForwardedCompatibleDataBrokerImplModuleFactory;
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.ForwardedCompatibleDataBrokerImplModuleMXBean;
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.NotificationBrokerImplModuleFactory;
 import org.opendaylight.controller.config.yang.md.sal.binding.impl.RuntimeMappingModuleFactory;
 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplModuleFactory;
+import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplModuleMXBean;
 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleFactory;
 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleMXBean;
 import org.opendaylight.controller.config.yang.md.sal.dom.impl.SchemaServiceImplSingletonModuleFactory;
@@ -92,6 +97,9 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
     private static final String DOM_BROKER_INSTANCE_NAME = "dom-broker-impl";
     private static final String BINDING_ASYNC_BROKER_INSTANCE_NAME = "binding-async-broker-instance";
     private static final String DOM_ASYNC_DATA_BROKER_INSTANCE = "dom-inmemory-data-broker";
+    private static final String BINDING_BROKER_INSTANCE_NAME = "binding-broker-impl";
+    private static final String COMPATIBLE_DATA_BROKER_INSTANCE_NAME = "binding-data-compatible-broker-instance";
+    private static final String NOTIFICATION_BROKER_INSTANCE_NAME = "notification-broker-impl";
 
     @Mock
     private ReadWriteTransaction mockedTransaction;
@@ -177,7 +185,9 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
                 new SimpleBGPExtensionProviderContextModuleFactory(),
                 new RIBExtensionsImplModuleFactory(), new DomBrokerImplModuleFactory(), new RuntimeMappingModuleFactory(),
                 new HashedWheelTimerModuleFactory(), new BindingAsyncDataBrokerImplModuleFactory(),
-                new DomInmemoryDataBrokerModuleFactory(), new SchemaServiceImplSingletonModuleFactory());
+                new DomInmemoryDataBrokerModuleFactory(), new SchemaServiceImplSingletonModuleFactory(),
+                new NotificationBrokerImplModuleFactory(), new ForwardedCompatibleDataBrokerImplModuleFactory(),
+                new BindingBrokerImplModuleFactory());
     }
 
     @Override
@@ -324,4 +334,55 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
 
         return resources;
     }
+
+    public ObjectName createBindingBrokerImpl(final ConfigTransactionJMXClient transaction, final ObjectName dataBrokerON,
+        final ObjectName notificationBrokerON) throws Exception {
+        final ObjectName objectName = transaction.createModule(BindingBrokerImplModuleFactory.NAME, BINDING_BROKER_INSTANCE_NAME);
+        final BindingBrokerImplModuleMXBean mxBean = transaction.newMXBeanProxy(objectName, BindingBrokerImplModuleMXBean.class);
+        mxBean.setDataBroker(dataBrokerON);
+        mxBean.setNotificationService(notificationBrokerON);
+        mxBean.setBindingMappingService(lookupMappingServiceInstance(transaction));
+        mxBean.setDomAsyncBroker(lookupDomBrokerInstance(transaction));
+        return objectName;
+    }
+
+    public static ObjectName lookupDomBrokerInstance(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
+        try {
+            return transaction.lookupConfigBean(DomBrokerImplModuleFactory.NAME, DOM_BROKER_INSTANCE_NAME);
+        } catch (final InstanceNotFoundException e) {
+            try {
+                final ObjectName nameCreated = transaction.createModule(DomBrokerImplModuleFactory.NAME, DOM_BROKER_INSTANCE_NAME);
+                final DomBrokerImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, DomBrokerImplModuleMXBean.class);
+                mxBean.setAsyncDataBroker(lookupDomAsyncDataBroker(transaction));
+                return nameCreated;
+            } catch (final InstanceAlreadyExistsException e1) {
+                throw new IllegalStateException(e1);
+            }
+        }
+    }
+
+    public ObjectName createCompatibleDataBrokerInstance(final ConfigTransactionJMXClient transaction)
+        throws InstanceAlreadyExistsException, InstanceNotFoundException {
+        final ObjectName nameCreated = transaction.createModule(ForwardedCompatibleDataBrokerImplModuleFactory.NAME, COMPATIBLE_DATA_BROKER_INSTANCE_NAME);
+        final ForwardedCompatibleDataBrokerImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, ForwardedCompatibleDataBrokerImplModuleMXBean.class);
+        mxBean.setDataBroker(lookupDataBrokerInstance(transaction));
+        return nameCreated;
+    }
+
+    private static ObjectName lookupDataBrokerInstance(final ConfigTransactionJMXClient transaction) {
+        try {
+            return transaction.lookupConfigBean(BindingAsyncDataBrokerImplModuleFactory.NAME, BINDING_ASYNC_BROKER_INSTANCE_NAME);
+        } catch (final InstanceNotFoundException e) {
+            try {
+                return transaction.createModule(RuntimeMappingModuleFactory.NAME, RuntimeMappingModuleFactory.SINGLETON_NAME);
+            } catch (final InstanceAlreadyExistsException e1) {
+                throw new IllegalStateException(e1);
+            }
+        }
+    }
+
+    public ObjectName createNotificationBrokerInstance(final ConfigTransactionJMXClient transaction) throws Exception {
+        final ObjectName objectName = transaction.createModule(NotificationBrokerImplModuleFactory.NAME, NOTIFICATION_BROKER_INSTANCE_NAME);
+        return objectName;
+    }
 }
index 3e858e05e4ace478f36e76753131a5426d2b17da..2880bd925bceadb95a8193e1a9a9db3ef62ac87d 100755 (executable)
@@ -98,7 +98,7 @@ public class BGPPeerModuleTest extends AbstractRIBImplModuleTest {
     public void testCreateBean() throws Exception {
         final CommitStatus status = createBgpPeerInstance();
         assertBeanCount(1, FACTORY_NAME);
-        assertStatus(status, 17, 0, 0);
+        assertStatus(status, 21, 0, 0);
     }
 
     @Test
@@ -106,7 +106,7 @@ public class BGPPeerModuleTest extends AbstractRIBImplModuleTest {
         NativeTestSupport.assumeSupportedPlatform();
         final CommitStatus status = createBgpPeerInstance(true);
         assertBeanCount(1, FACTORY_NAME);
-        assertStatus(status, 19, 0, 0);
+        assertStatus(status, 23, 0, 0);
     }
 
     @Test
@@ -134,7 +134,7 @@ public class BGPPeerModuleTest extends AbstractRIBImplModuleTest {
         assertBeanCount(1, FACTORY_NAME);
         status = transaction.commit();
         assertBeanCount(1, FACTORY_NAME);
-        assertStatus(status, 0, 0, 17);
+        assertStatus(status, 0, 0, 21);
     }
 
     @Test
@@ -147,7 +147,7 @@ public class BGPPeerModuleTest extends AbstractRIBImplModuleTest {
         mxBean.setPort(new PortNumber(10));
         status = transaction.commit();
         assertBeanCount(1, FACTORY_NAME);
-        assertStatus(status, 0, 1, 16);
+        assertStatus(status, 0, 1, 20);
     }
 
     private ObjectName createBgpPeerInstance(final ConfigTransactionJMXClient transaction, final IpAddress host,
@@ -187,6 +187,10 @@ public class BGPPeerModuleTest extends AbstractRIBImplModuleTest {
         mxBean.setAdvertizedTable(Lists.newArrayList(BGPTableTypeImplModuleTest.createTableInstance(transaction,
             new IdentityAttributeRef(Ipv4AddressFamily.QNAME.toString()),
             new IdentityAttributeRef(MplsLabeledVpnSubsequentAddressFamily.QNAME.toString()))));
+
+        final ObjectName notificationBrokerON = createNotificationBrokerInstance(transaction);
+        final ObjectName bindingBrokerON = createBindingBrokerImpl(transaction, createCompatibleDataBrokerInstance(transaction), notificationBrokerON);
+        mxBean.setRpcRegistry(bindingBrokerON);
         return nameCreated;
     }
 
diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BgpPeerRpcTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BgpPeerRpcTest.java
new file mode 100644 (file)
index 0000000..29d343a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import io.netty.channel.ChannelFuture;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev160322.PeerRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev160322.RouteRefreshRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev160322.RouteRefreshRequestInputBuilder;
+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.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.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class BgpPeerRpcTest {
+
+    private final Set<TablesKey> supportedFamilies = new HashSet<TablesKey>();
+    private final BGPSessionImpl session = Mockito.mock(BGPSessionImpl.class);
+    private final BgpPeerRpc rpc = new BgpPeerRpc(this.session, this.supportedFamilies);
+    private final PeerRef peer = Mockito.mock(PeerRef.class);
+
+    private final ChannelOutputLimiter limiter = new ChannelOutputLimiter(this.session);
+    private final ChannelFuture future = Mockito.mock(ChannelFuture.class);
+
+    @Before
+    public void setUp() throws InterruptedException, ExecutionException {
+        this.supportedFamilies.add(new TablesKey(Ipv4AddressFamily.class, SubsequentAddressFamily.class));
+
+        Mockito.doReturn(this.limiter).when(this.session).getLimiter();
+        Mockito.doReturn(this.future).when(this.session).writeAndFlush(Mockito.any(Notification.class));
+        Mockito.doReturn(true).when(this.future).isDone();
+        Mockito.doReturn(null).when(this.future).get();
+        Mockito.doReturn(true).when(this.future).isSuccess();
+    }
+
+    @Test
+    public void testSuccessRequest() throws InterruptedException, ExecutionException {
+        final RouteRefreshRequestInput input = new RouteRefreshRequestInputBuilder()
+            .setAfi(Ipv4AddressFamily.class)
+            .setSafi(SubsequentAddressFamily.class)
+            .setPeerRef(this.peer).build();
+        final Future<RpcResult<Void>> result = this.rpc.routeRefreshRequest(input);
+        assertTrue(result.get().getErrors().isEmpty());
+    }
+
+    @Test
+    public void testFailedRequest() throws InterruptedException, ExecutionException {
+        final RouteRefreshRequestInput input = new RouteRefreshRequestInputBuilder()
+            .setAfi(Ipv6AddressFamily.class)
+            .setSafi(SubsequentAddressFamily.class)
+            .setPeerRef(this.peer).build();
+        final Future<RpcResult<Void>> result = this.rpc.routeRefreshRequest(input);
+        assertEquals(1, result.get().getErrors().size());
+        assertEquals("Failed to send Route Refresh message due to unsupported address families.", result.get().getErrors().iterator().next().getMessage());
+    }
+}
index e5df1cebe58c0286c3a0c65e3e7e18c43d89e08d..6606fb9408ae953e93584e2a8eef595e03a4135d 100755 (executable)
@@ -53,6 +53,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.link
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.routes.linkstate.routes.LinkstateRoute;
 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.rib.rev130925.BgpRib;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
 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.bgp.rib.Rib;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.RibKey;
@@ -136,7 +137,7 @@ public class ParserToSalTest extends AbstractDataBrokerTest {
                 BasePathSelectionModeFactory.createBestPathSelectionStrategy()), GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy());
         assertTablesExists(tables, true);
         rib.onGlobalContextUpdated(this.schemaService.getGlobalContext());
-        final BGPPeer peer = new BGPPeer("peer-" + this.mock.toString(), rib);
+        final BGPPeer peer = new BGPPeer("peer-" + this.mock.toString(), rib, PeerRole.Ibgp, null);
 
         final ListenerRegistration<?> reg = this.mock.registerUpdateListener(peer);
         reg.close();
@@ -151,7 +152,7 @@ public class ParserToSalTest extends AbstractDataBrokerTest {
                 BasePathSelectionModeFactory.createBestPathSelectionStrategy()), GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy());
         rib.onGlobalContextUpdated(this.schemaService.getGlobalContext());
         assertTablesExists(tables, true);
-        final BGPPeer peer = new BGPPeer("peer-" + this.mock.toString(), rib);
+        final BGPPeer peer = new BGPPeer("peer-" + this.mock.toString(), rib, PeerRole.Ibgp, null);
 
         final ListenerRegistration<?> reg = this.mock.registerUpdateListener(peer);
         reg.close();
index eda7772eccd5bdcb000aeca5893b0bfb2035d377..4aff5892fab91b190197678fdb70509d23c956f5 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.protocol.bgp.rib.impl;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.mockito.Matchers.any;
-
 import com.google.common.collect.Lists;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandler;
@@ -51,6 +50,7 @@ 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.mp.capabilities.MultiprotocolCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRibId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
 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.types.rev130919.Ipv4AddressFamily;
@@ -119,7 +119,7 @@ public class PeerTest extends AbstractRIBTestSetup {
 
     @Test
     public void testClassicPeer() throws Exception {
-        this.classic = new BGPPeer("testPeer", getRib());
+        this.classic = new BGPPeer("testPeer", getRib(), PeerRole.Ibgp, null);
         this.mockSession();
         assertEquals("testPeer", this.classic.getName());
         this.classic.onSessionUp(this.session);
@@ -133,7 +133,7 @@ public class PeerTest extends AbstractRIBTestSetup {
         assertEquals(3, this.routes.size());
 
         //create new peer so that it gets advertized routes from RIB
-        try (final BGPPeer testingPeer = new BGPPeer("testingPeer", getRib())) {
+        try (final BGPPeer testingPeer = new BGPPeer("testingPeer", getRib(), PeerRole.Ibgp, null)) {
             testingPeer.onSessionUp(this.session);
             assertEquals(3, this.routes.size());
             assertEquals(1, testingPeer.getBgpPeerState().getSessionEstablishedCount().intValue());