BUG-4931: Simple routing policy 36/38636/1
authorClaudio D. Gasparini <cgaspari@cisco.com>
Thu, 28 Apr 2016 12:47:54 +0000 (14:47 +0200)
committerClaudio D. Gasparini <cgaspari@cisco.com>
Tue, 10 May 2016 14:41:58 +0000 (16:41 +0200)
New BGP Peer routing policy
+LearnNone  : dont listen any peer from this peer.
+AnnounceNone : dont advertise any route to this peer.
If none of this status is applied, default policy
will be applied.

Change-Id: I1634bb4f19e7bfc78ab78b055610eff727f3b051
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
17 files changed:
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/AddPathAbstractRouteEntry.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/base/BaseAbstractRouteEntry.java
bgp/rib-api/src/main/yang/bgp-rib.yang
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/AbstractPeerRoleTracker.java [deleted file]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.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/ExportPolicyPeerTrackerImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ImportPolicyPeerTracker.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriter.java
bgp/rib-impl/src/main/yang/odl-bgp-rib-impl-cfg.yang
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibsInWriterTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriterTest.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/ExportPolicyPeerTracker.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/PeerRoleUtil.java [new file with mode: 0644]

index 610ac0d9ce734df62aec211759b2a9fd7e465d63..419e9d6f1978303caf35772deeeed7682a5c2425 100644 (file)
@@ -158,9 +158,6 @@ public abstract class AddPathAbstractRouteEntry extends AbstractRouteEntry {
          * multiple times.
          */
         for (final PeerRole role : PeerRole.values()) {
-            if (PeerRole.Internal.equals(role)) {
-                continue;
-            }
             final PeerExportGroup peerGroup = peerPT.getPeerGroup(role);
             if (peerGroup != null) {
                 final ContainerNode effectiveAttributes = peerGroup.effectiveAttributes(routePeerId, attributes);
index d86bfee898e3900ccb70a751b709a2d491686e91..83588cd79f4a02166ccbf12be31e23a7f9caf967 100644 (file)
@@ -179,9 +179,6 @@ abstract class BaseAbstractRouteEntry extends AbstractRouteEntry {
          * multiple times.
          */
         for (final PeerRole role : PeerRole.values()) {
-            if (PeerRole.Internal.equals(role)) {
-                continue;
-            }
             final PeerExportGroup peerGroup = peerPT.getPeerGroup(role);
             if (peerGroup != null) {
                 final ContainerNode effAttrib = peerGroup.effectiveAttributes(routePeerId, attributes);
index 3432241a29463a7c99ab2978503a3f99ff7de551..0133a4968316ef02b1cf7abb53623c3a6c2e4fb6 100644 (file)
@@ -53,6 +53,13 @@ module bgp-rib {
         }
     }
 
+    typedef simple-routing-policy {
+        type enumeration {
+            enum announce-none { description "Don't announce routes to this peer"; }
+            enum learn-none { description "Don't learn routes from this peer"; }
+        }
+    }
+
     grouping route {
         uses bgp-msg:path-attributes;
     }
@@ -104,6 +111,9 @@ module bgp-rib {
                     type peer-role;
                     mandatory true;
                 }
+                leaf simple-routing-policy {
+                    type simple-routing-policy;
+                }
                 list supported-tables {
                     key "afi safi";
                     uses bgp-mp:bgp-add-path-table-type;
index 34adf15ff5a2a83751679c2ed507dde66100ee41..e3611b8c68be63513d558272a354fd5f59a76206 100755 (executable)
@@ -27,6 +27,7 @@ import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRib;
 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.SimpleRoutingPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -79,7 +80,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, null);
+        final BGPPeer bgpClientPeer = new BGPPeer(bgpPeerId.getIpv4Address().getValue(), r, PeerRole.Internal, SimpleRoutingPolicy.AnnounceNone, null);
 
         final BGPSessionPreferences prefs = new BGPSessionPreferences(r.getLocalAs(), 0, r.getBgpIdentifier(),
             r.getLocalAs(), Collections.emptyList());
index 69b256e11213a164169907e8373e19aa448a2918..06a830d4b4fe38e87c38ca7393588f8542f0f7ea 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(), getRpcRegistryDependency());
+            bgpClientPeer = new BGPPeer(peerName(host), r, getPeerRole(), getSimpleRoutingPolicy(), getRpcRegistryDependency());
         } else {
-            bgpClientPeer = new BGPPeer(peerName(host), r, PeerRole.Ibgp, getRpcRegistryDependency());
+            bgpClientPeer = new BGPPeer(peerName(host), r, PeerRole.Ibgp, getSimpleRoutingPolicy(), getRpcRegistryDependency());
         }
 
         bgpClientPeer.registerRootRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractPeerRoleTracker.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractPeerRoleTracker.java
deleted file mode 100644 (file)
index bb39dd3..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2015 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.Optional;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-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.Peer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTables;
-import org.opendaylight.yangtools.yang.binding.BindingMapping;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Maintains the mapping of PeerId -> Role. Subclasses get notified of changes and can do their
- * own thing.
- */
-abstract class AbstractPeerRoleTracker {
-
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractPeerRoleTracker.class);
-
-    public void onDataTreeChanged(final DataTreeCandidateNode change, final YangInstanceIdentifier peerPath) {
-        // Check for removal
-        final Optional<NormalizedNode<?, ?>> maybePeerRole = change.getDataAfter();
-        LOG.debug("Data Changed for Peer role {} path {}, dataBefore {}, dataAfter {}", change.getIdentifier(),
-            peerPath , change.getDataBefore(), maybePeerRole);
-
-        final PeerRole role;
-        if (maybePeerRole.isPresent()) {
-            final LeafNode<?> peerRoleLeaf = (LeafNode<?>) maybePeerRole.get();
-            // We could go for a codec, but this is simpler and faster
-            role = PeerRole.valueOf(BindingMapping.getClassName((String) peerRoleLeaf.getValue()));
-        } else {
-            role = null;
-        }
-        peerRoleChanged(peerPath, role);
-    }
-
-    static final NodeIdentifier PEER_ROLE_NID = new NodeIdentifier(QName.create(Peer.QNAME, "peer-role").intern());
-    static final NodeIdentifier PEER_TABLES = new NodeIdentifier(SupportedTables.QNAME);
-
-    protected AbstractPeerRoleTracker() {
-    }
-
-    /**
-     * Invoked whenever a peer role changes.
-     *
-     * @param peerPath Peer's path
-     * @param role Peer's new role, null indicates the peer has disappeared.
-     */
-    protected abstract void peerRoleChanged(@Nonnull YangInstanceIdentifier peerPath, @Nullable PeerRole role);
-}
index b1533452db325fef60d916cab7b8b22a849f56e4..85ba578f354df65a3ac5e801696ee52f6f05498a 100644 (file)
@@ -15,6 +15,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
@@ -26,6 +27,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
 import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
+import org.opendaylight.protocol.bgp.rib.spi.PeerRoleUtil;
 import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.SendReceive;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.add.path.capability.AddressFamilies;
@@ -33,6 +35,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.update.attributes.MpUnreachNlri;
 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.SimpleRoutingPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibIn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibOut;
@@ -78,6 +81,7 @@ final class AdjRibInWriter {
     private static final NodeIdentifier PEER_TABLES = new NodeIdentifier(SupportedTables.QNAME);
     private static final NodeIdentifier TABLES = new NodeIdentifier(Tables.QNAME);
     private static final QName SEND_RECEIVE = QName.create(SupportedTables.QNAME, "send-receive").intern();
+    static final NodeIdentifier SIMPLE_ROUTING_POLICY_NID = new NodeIdentifier(QName.create(Peer.QNAME, "simple-routing-policy").intern());
 
     // FIXME: is there a utility method to construct this?
     private static final ContainerNode EMPTY_ADJRIBIN = Builders.containerBuilder().withNodeIdentifier(ADJRIBIN).addChild(ImmutableNodes.mapNodeBuilder(Tables.QNAME).build()).build();
@@ -88,43 +92,29 @@ final class AdjRibInWriter {
     private final YangInstanceIdentifier peerPath;
     private final YangInstanceIdentifier ribPath;
     private final DOMTransactionChain chain;
-    private final PeerId peerId;
-    private final String role;
+    private final PeerRole role;
+    private final Optional<SimpleRoutingPolicy> simpleRoutingPolicy;
 
-    private AdjRibInWriter(final YangInstanceIdentifier ribPath, final DOMTransactionChain chain, final PeerId peerId, final String role, final YangInstanceIdentifier peerPath, final Map<TablesKey, TableContext> tables) {
+    private AdjRibInWriter(final YangInstanceIdentifier ribPath, final DOMTransactionChain chain, final PeerRole role,
+        final Optional<SimpleRoutingPolicy> simpleRoutingPolicy, final YangInstanceIdentifier peerPath, final Map<TablesKey, TableContext> tables) {
         this.ribPath = Preconditions.checkNotNull(ribPath);
         this.chain = Preconditions.checkNotNull(chain);
         this.tables = Preconditions.checkNotNull(tables);
         this.role = Preconditions.checkNotNull(role);
+        this.simpleRoutingPolicy = simpleRoutingPolicy;
         this.peerPath = peerPath;
-        this.peerId = peerId;
-    }
-
-    // We could use a codec, but this should be fine, too
-    private static String roleString(final PeerRole role) {
-        switch (role) {
-        case Ebgp:
-            return "ebgp";
-        case Ibgp:
-            return "ibgp";
-        case RrClient:
-            return "rr-client";
-        case Internal:
-            return "internal";
-        default:
-            throw new IllegalArgumentException("Unhandled role " + role);
-        }
     }
 
     /**
      * Create a new writer using a transaction chain.
      *
      * @param role peer's role
-     * @param chain transaction chain
-     * @return A fresh writer instance
+     * @param simpleRoutingPolicy simple Routing Policy {@link SimpleRoutingPolicy}
+     *@param chain transaction chain  @return A fresh writer instance
      */
-    static AdjRibInWriter create(@Nonnull final YangInstanceIdentifier ribId, @Nonnull final PeerRole role, @Nonnull final DOMTransactionChain chain) {
-        return new AdjRibInWriter(ribId, chain, null, roleString(role), null, Collections.<TablesKey, TableContext>emptyMap());
+    static AdjRibInWriter create(@Nonnull final YangInstanceIdentifier ribId, @Nonnull final PeerRole role, final Optional<SimpleRoutingPolicy> simpleRoutingPolicy,
+        @Nonnull final DOMTransactionChain chain) {
+        return new AdjRibInWriter(ribId, chain, role, simpleRoutingPolicy, null, Collections.emptyMap());
     }
 
     /**
@@ -139,28 +129,27 @@ final class AdjRibInWriter {
      * @return New writer
      */
     AdjRibInWriter transform(final PeerId newPeerId, final RIBSupportContextRegistry registry, final Set<TablesKey> tableTypes,
-        final List<AddressFamilies> addPathTablesType, final boolean isAppPeer) {
+        final List<AddressFamilies> addPathTablesType) {
         final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
 
         final YangInstanceIdentifier newPeerPath;
-        newPeerPath = createEmptyPeerStructure(newPeerId, isAppPeer, tx);
-        final ImmutableMap<TablesKey, TableContext> tb = createNewTableInstances(newPeerPath, isAppPeer, registry, tableTypes, addPathTablesType, tx);
+        newPeerPath = createEmptyPeerStructure(newPeerId, tx);
+        final ImmutableMap<TablesKey, TableContext> tb = createNewTableInstances(newPeerPath, registry, tableTypes, addPathTablesType, tx);
         tx.submit();
 
-        return new AdjRibInWriter(this.ribPath, this.chain, newPeerId, this.role, newPeerPath, tb);
+        return new AdjRibInWriter(this.ribPath, this.chain, this.role, this.simpleRoutingPolicy, newPeerPath, tb);
     }
 
     /**
      * Create new table instances, potentially creating their empty entries
      * @param newPeerPath
-     * @param isAppPeer
      * @param registry
      * @param tableTypes
      * @param addPathTablesType
      * @param tx
      * @return
      */
-    private ImmutableMap<TablesKey, TableContext> createNewTableInstances(final YangInstanceIdentifier newPeerPath, final boolean isAppPeer,
+    private ImmutableMap<TablesKey, TableContext> createNewTableInstances(final YangInstanceIdentifier newPeerPath,
         final RIBSupportContextRegistry registry, final Set<TablesKey> tableTypes, final List<AddressFamilies> addPathTablesType,
         final DOMDataWriteTransaction tx) {
 
@@ -174,7 +163,7 @@ final class AdjRibInWriter {
                 LOG.warn("No support for table type {}, skipping it", tableKey);
                 continue;
             }
-            installAdjRibsOutTables(isAppPeer, newPeerPath, rs, instanceIdentifierKey, tableKey, addPathTableMaps.get(tableKey), tx);
+            installAdjRibsOutTables(newPeerPath, rs, instanceIdentifierKey, tableKey, addPathTableMaps.get(tableKey), tx);
             installAdjRibInTables(newPeerPath, tableKey, rs, instanceIdentifierKey, tx, tb);
         }
         return tb.build();
@@ -199,10 +188,10 @@ final class AdjRibInWriter {
         tb.put(tableKey, ctx);
     }
 
-    private void installAdjRibsOutTables(final boolean isAppPeer, final YangInstanceIdentifier newPeerPath, final RIBSupportContext rs,
+    private void installAdjRibsOutTables(final YangInstanceIdentifier newPeerPath, final RIBSupportContext rs,
         final NodeIdentifierWithPredicates instanceIdentifierKey, final TablesKey tableKey, final SendReceive sendReceive,
         final DOMDataWriteTransaction tx) {
-        if (!isAppPeer) {
+        if (!isAnnounceNone(this.simpleRoutingPolicy)) {
             final NodeIdentifierWithPredicates supTablesKey = RibSupportUtils.toYangKey(SupportedTables.QNAME, tableKey);
             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> tt = Builders.mapEntryBuilder().withNodeIdentifier(supTablesKey);
             for (final Entry<QName, Object> e : supTablesKey.getKeyValues().entrySet()) {
@@ -216,25 +205,30 @@ final class AdjRibInWriter {
         }
     }
 
-    private YangInstanceIdentifier createEmptyPeerStructure(final PeerId newPeerId, final boolean isAppPeer, final DOMDataWriteTransaction tx) {
+    private YangInstanceIdentifier createEmptyPeerStructure(final PeerId newPeerId, final DOMDataWriteTransaction tx) {
         final NodeIdentifierWithPredicates peerKey = IdentifierUtils.domPeerId(newPeerId);
         final YangInstanceIdentifier newPeerPath = this.ribPath.node(Peer.QNAME).node(peerKey);
 
-        tx.put(LogicalDatastoreType.OPERATIONAL, newPeerPath, peerSkeleton(peerKey, newPeerId.getValue(), isAppPeer));
+        tx.put(LogicalDatastoreType.OPERATIONAL, newPeerPath, peerSkeleton(peerKey, newPeerId.getValue()));
         LOG.debug("New peer {} structure installed.", newPeerPath);
         return newPeerPath;
     }
 
     @VisibleForTesting
-    MapEntryNode peerSkeleton(final NodeIdentifierWithPredicates peerKey, final String peerId, final boolean isAppPeer) {
+    MapEntryNode peerSkeleton(final NodeIdentifierWithPredicates peerKey, final String peerId) {
         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> pb = Builders.mapEntryBuilder();
         pb.withNodeIdentifier(peerKey);
         pb.withChild(ImmutableNodes.leafNode(PEER_ID, peerId));
-        pb.withChild(ImmutableNodes.leafNode(PEER_ROLE, this.role));
+        pb.withChild(ImmutableNodes.leafNode(PEER_ROLE, PeerRoleUtil.roleForString(this.role)));
+        if (this.simpleRoutingPolicy.isPresent() && this.role != PeerRole.Internal) {
+            pb.withChild(ImmutableNodes.leafNode(SIMPLE_ROUTING_POLICY_NID, simpleRoutingPolicyString(this.simpleRoutingPolicy.get())));
+        }
         pb.withChild(ImmutableMapNodeBuilder.create().withNodeIdentifier(PEER_TABLES).build());
         pb.withChild(EMPTY_ADJRIBIN);
-        pb.withChild(EMPTY_EFFRIBIN);
-        if (!isAppPeer) {
+        if(!isLearnNone(this.simpleRoutingPolicy)) {
+            pb.withChild(EMPTY_EFFRIBIN);
+        }
+        if (!isAnnounceNone(this.simpleRoutingPolicy)) {
             pb.withChild(EMPTY_ADJRIBOUT);
         }
         return pb.build();
@@ -255,10 +249,8 @@ final class AdjRibInWriter {
 
     void markTableUptodate(final TablesKey tableTypes) {
         final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
-
         final TableContext ctx = this.tables.get(tableTypes);
         tx.merge(LogicalDatastoreType.OPERATIONAL, ctx.getTableId().node(Attributes.QNAME).node(ATTRIBUTES_UPTODATE_TRUE.getNodeType()), ATTRIBUTES_UPTODATE_TRUE);
-
         tx.submit();
     }
 
@@ -289,4 +281,22 @@ final class AdjRibInWriter {
         tx.submit();
     }
 
+    static boolean isAnnounceNone(final java.util.Optional<SimpleRoutingPolicy> peerStatus) {
+        return peerStatus.isPresent() && peerStatus.get() == SimpleRoutingPolicy.AnnounceNone;
+    }
+
+    static boolean isLearnNone(final java.util.Optional<SimpleRoutingPolicy> peerStatus) {
+        return peerStatus.isPresent() && peerStatus.get() == SimpleRoutingPolicy.LearnNone;
+    }
+
+    private static String simpleRoutingPolicyString(final SimpleRoutingPolicy simpleRoutingPolicy) {
+        switch (simpleRoutingPolicy) {
+        case AnnounceNone:
+            return "announce-none";
+        case LearnNone:
+            return "learn-none";
+        default:
+            throw new IllegalArgumentException("Unhandled Simple Routing Policy " + simpleRoutingPolicy);
+        }
+    }
 }
index 82218f4949423c30e9288c6ae3cff7bb3e5b089f..7b3d04fc070a51b901795497182b1c74a81ee5da 100644 (file)
@@ -13,6 +13,7 @@ import com.google.common.net.InetAddresses;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Optional;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
@@ -26,6 +27,7 @@ import org.opendaylight.protocol.bgp.rib.spi.RouterIds;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 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.SimpleRoutingPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibIn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
@@ -76,9 +78,9 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
         this.effectiveRibInWriter = EffectiveRibInWriter.create(targetRib.getService(), targetRib.createPeerChain(this), peerIId,
             targetRib.getImportPolicyPeerTracker(), targetRib.getRibSupportContext(), PeerRole.Internal);
         this.writerChain = targetRib.createPeerChain(this);
-        this.writer = AdjRibInWriter.create(targetRib.getYangRibId(), PeerRole.Internal, this.writerChain);
+        this.writer = AdjRibInWriter.create(targetRib.getYangRibId(), PeerRole.Internal, Optional.of(SimpleRoutingPolicy.AnnounceNone), this.writerChain);
         this.writer = this.writer.transform(RouterIds.createPeerId(ipAddress), targetRib.getRibSupportContext(), targetRib.getLocalTablesKeys(),
-            Collections.emptyList(), true);
+            Collections.emptyList());
         this.moduleTracker = moduleTracker;
         if (moduleTracker != null) {
             moduleTracker.onInstanceCreate();
index 059b0130e425e718f1eb5ee77a8a6093baaaac9d..9e332413d2ac451c2ca93ff894f211f6af2586cb 100644 (file)
@@ -7,6 +7,9 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl;
 
+import static org.opendaylight.protocol.bgp.rib.impl.AdjRibInWriter.isAnnounceNone;
+import static org.opendaylight.protocol.bgp.rib.impl.AdjRibInWriter.isLearnNone;
+
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Preconditions;
@@ -18,7 +21,9 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Collectors;
 import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerRuntimeMXBean;
 import org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerRuntimeRegistration;
@@ -51,7 +56,6 @@ 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.path.attributes.AttributesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
-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.RouteRefresh;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.add.path.capability.AddressFamilies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri;
@@ -64,6 +68,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer
 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.SimpleRoutingPolicy;
 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;
@@ -106,16 +111,22 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
     private final RpcProviderRegistry rpcRegistry;
     private RoutedRpcRegistration<BgpPeerRpcService> rpcRegistration;
     private final PeerRole peerRole;
+    private final Optional<SimpleRoutingPolicy> simpleRoutingPolicy;
 
-    public BGPPeer(final String name, final RIB rib, final PeerRole role, final RpcProviderRegistry rpcRegistry) {
+    public BGPPeer(final String name, final RIB rib, final PeerRole role, final SimpleRoutingPolicy peerStatus, final RpcProviderRegistry rpcRegistry) {
         this.peerRole = role;
+        this.simpleRoutingPolicy = Optional.ofNullable(peerStatus);
         this.rib = Preconditions.checkNotNull(rib);
         this.name = name;
         this.chain = rib.createPeerChain(this);
-        this.ribWriter = AdjRibInWriter.create(rib.getYangRibId(), role, this.chain);
+        this.ribWriter = AdjRibInWriter.create(rib.getYangRibId(), this.peerRole, this.simpleRoutingPolicy, this.chain);
         this.rpcRegistry = rpcRegistry;
     }
 
+    public BGPPeer(final String name, final RIB rib, final PeerRole role, final RpcProviderRegistry rpcRegistry) {
+        this(name, rib, role, null, rpcRegistry);
+    }
+
     @Override
     public synchronized void close() {
         releaseConnection();
@@ -239,11 +250,20 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
 
         this.rawIdentifier = InetAddresses.forString(session.getBgpId().getValue()).getAddress();
         final PeerId peerId = RouterIds.createPeerId(session.getBgpId());
-        final YangInstanceIdentifier peerIId = this.rib.getYangRibId().node(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer.QNAME).node(IdentifierUtils.domPeerId(peerId));
-        createAdjRibOutListener(peerId);
-        this.effRibInWriter = EffectiveRibInWriter.create(this.rib.getService(), this.rib.createPeerChain(this), peerIId, ((RIBImpl)this.rib).getImportPolicyPeerTracker(),
-            this.rib.getRibSupportContext(), this.peerRole);
-        this.ribWriter = this.ribWriter.transform(peerId, this.rib.getRibSupportContext(), this.tables, addPathTablesType, false);
+
+        this.tables.addAll(this.session.getAdvertisedTableTypes().stream().map(t -> new TablesKey(t.getAfi(), t.getSafi())).collect(Collectors.toList()));
+        final boolean announceNone = isAnnounceNone(this.simpleRoutingPolicy);
+        if(!announceNone) {
+            createAdjRibOutListener(peerId);
+        }
+        addBgp4Support(peerId, announceNone);
+
+        if(!isLearnNone(this.simpleRoutingPolicy)) {
+            final YangInstanceIdentifier peerIId = this.rib.getYangRibId().node(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer.QNAME).node(IdentifierUtils.domPeerId(peerId));
+            this.effRibInWriter = EffectiveRibInWriter.create(this.rib.getService(), this.rib.createPeerChain(this), peerIId, ((RIBImpl) this.rib).getImportPolicyPeerTracker(),
+                this.rib.getRibSupportContext(), this.peerRole);
+        }
+        this.ribWriter = this.ribWriter.transform(peerId, this.rib.getRibSupportContext(), this.tables, addPathTablesType);
         this.sessionEstablishedCounter++;
         if (this.registrator != null) {
             this.runtimeReg = this.registrator.register(this);
@@ -258,20 +278,14 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
     }
 
     private void createAdjRibOutListener(final PeerId peerId) {
-        for (final BgpTableType t : this.session.getAdvertisedTableTypes()) {
-            final TablesKey key = new TablesKey(t.getAfi(), t.getSafi());
-            if (this.tables.add(key)) {
-                createAdjRibOutListener(peerId, key, true);
-            }
-        }
-
-        addBgp4Support(peerId);
+        this.tables.forEach(key->createAdjRibOutListener(peerId, key, true));
     }
 
     //try to add a support for old-school BGP-4, if peer did not advertise IPv4-Unicast MP capability
-    private void addBgp4Support(final PeerId peerId) {
+    private void addBgp4Support(final PeerId peerId, final boolean announceNone) {
         final TablesKey key = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
-        if (this.tables.add(key)) {
+        this.tables.add(key);
+        if (!announceNone) {
             createAdjRibOutListener(peerId, key, false);
         }
     }
@@ -417,7 +431,7 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
         LOG.error("Transaction chain failed.", cause);
         this.chain.close();
         this.chain = this.rib.createPeerChain(this);
-        this.ribWriter = AdjRibInWriter.create(this.rib.getYangRibId(), this.peerRole, this.chain);
+        this.ribWriter = AdjRibInWriter.create(this.rib.getYangRibId(), this.peerRole, this.simpleRoutingPolicy, this.chain);
         releaseConnection();
     }
 
index 480c0690114be6095fbda07cbd7c736ccf14ffff..35b1d78c5e61b87a1bb4198e4017f708e459848c 100644 (file)
@@ -24,6 +24,8 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup;
@@ -44,7 +46,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class ExportPolicyPeerTrackerImpl extends AbstractPeerRoleTracker implements ExportPolicyPeerTracker {
+final class ExportPolicyPeerTrackerImpl implements ExportPolicyPeerTracker {
     private static final Logger LOG = LoggerFactory.getLogger(ExportPolicyPeerTrackerImpl.class);
     private static final Function<YangInstanceIdentifier, Entry<PeerId, YangInstanceIdentifier>> GENERATE_PEER_ID = new Function<YangInstanceIdentifier, Entry<PeerId, YangInstanceIdentifier>>() {
         @Override
@@ -54,7 +56,7 @@ final class ExportPolicyPeerTrackerImpl extends AbstractPeerRoleTracker implemen
         }
     };
     private static final QName SEND_RECEIVE = QName.create(SupportedTables.QNAME, "send-receive").intern();
-    private static final NodeIdentifier SEND_RECEIVE_NID = new YangInstanceIdentifier.NodeIdentifier(SEND_RECEIVE);
+    private static final NodeIdentifier SEND_RECEIVE_NID = new NodeIdentifier(SEND_RECEIVE);
     private final Map<YangInstanceIdentifier, PeerRole> peerRoles = new HashMap<>();
     private final Set<PeerId> peerTables = Sets.newHashSet();
     private final PolicyDatabase policyDatabase;
@@ -95,7 +97,7 @@ final class ExportPolicyPeerTrackerImpl extends AbstractPeerRoleTracker implemen
     }
 
     @Override
-    protected void peerRoleChanged(final YangInstanceIdentifier peerPath, final PeerRole role) {
+    public void peerRoleChanged(@Nonnull final YangInstanceIdentifier peerPath, @Nullable final PeerRole role) {
         /*
          * This is a sledgehammer approach to the problem: modify the role map first,
          * then construct the group map from scratch.
index 2f45ddb6bced6d322487852ffd442c1c4fdbd378..caa736df08f908f69ea2472145288951a011513e 100644 (file)
@@ -21,7 +21,7 @@ import org.slf4j.LoggerFactory;
 /**
  * Tracks import policy corresponding to a particular peer.
  */
-final class ImportPolicyPeerTracker extends AbstractPeerRoleTracker {
+final class ImportPolicyPeerTracker {
     private static final Logger LOG = LoggerFactory.getLogger(ImportPolicyPeerTracker.class);
 
     private final Map<PeerId, AbstractImportPolicy> policies = new ConcurrentHashMap<>();
@@ -32,7 +32,12 @@ final class ImportPolicyPeerTracker extends AbstractPeerRoleTracker {
         this.policyDatabase = Preconditions.checkNotNull(policyDatabase);
     }
 
-    @Override
+    /**
+     * Invoked whenever a peer role changes.
+     *
+     * @param peerPath Peer's path
+     * @param role Peer's new role, null indicates the peer has disappeared.
+     */
     protected void peerRoleChanged(final YangInstanceIdentifier peerPath, final PeerRole role) {
         final PeerId peer = IdentifierUtils.peerId((NodeIdentifierWithPredicates) peerPath.getLastPathArgument());
 
index 305f97537d970b96ccc13bb8638052e5e096f48f..0519a9a930d436bbc46a8ecfd1ae33765c744658 100644 (file)
@@ -7,6 +7,9 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl;
 
+import static org.opendaylight.protocol.bgp.rib.impl.AdjRibInWriter.SIMPLE_ROUTING_POLICY_NID;
+import static org.opendaylight.protocol.bgp.rib.spi.PeerRoleUtil.PEER_ROLE_NID;
+
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.primitives.UnsignedInteger;
@@ -28,20 +31,24 @@ import org.opendaylight.protocol.bgp.rib.spi.CacheDisconnectedPeers;
 import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup;
+import org.opendaylight.protocol.bgp.rib.spi.PeerRoleUtil;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
 import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
 import org.opendaylight.protocol.bgp.rib.spi.RouterIds;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 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.SimpleRoutingPolicy;
 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.bgp.rib.rib.Peer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.EffectiveRibIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
 import org.opendaylight.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.Routes;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -64,6 +71,7 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
     private static final LeafNode<Boolean> ATTRIBUTES_UPTODATE_TRUE = ImmutableNodes.leafNode(QName.create(Attributes.QNAME, "uptodate"), Boolean.TRUE);
     private static final NodeIdentifier EFFRIBIN_NID = new NodeIdentifier(EffectiveRibIn.QNAME);
     private static final NodeIdentifier TABLES_NID = new NodeIdentifier(Tables.QNAME);
+    private static final NodeIdentifier PEER_TABLES = new NodeIdentifier(SupportedTables.QNAME);
 
     private final Map<PathArgument, RouteEntry> routeEntries = new HashMap<>();
     private final YangInstanceIdentifier locRibTarget;
@@ -177,7 +185,7 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
     }
 
     private void filterOutChangesToSupportedTables(final PeerId peerIdOfNewPeer, final DataTreeCandidateNode rootNode) {
-        final DataTreeCandidateNode tablesChange = rootNode.getModifiedChild(AbstractPeerRoleTracker.PEER_TABLES);
+        final DataTreeCandidateNode tablesChange = rootNode.getModifiedChild(PEER_TABLES);
         if (tablesChange != null) {
             this.peerPolicyTracker.onTablesChanged(peerIdOfNewPeer, tablesChange);
         }
@@ -195,13 +203,35 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
     }
 
     private void filterOutPeerRole(final PeerId peerId, final DataTreeCandidateNode rootNode, final YangInstanceIdentifier rootPath) {
-        final DataTreeCandidateNode roleChange = rootNode.getModifiedChild(AbstractPeerRoleTracker.PEER_ROLE_NID);
+        final DataTreeCandidateNode roleChange = rootNode.getModifiedChild(PEER_ROLE_NID);
         if (roleChange != null) {
-            if (!rootNode.getModificationType().equals(ModificationType.DELETE)) {
+            if (rootNode.getModificationType() != ModificationType.DELETE) {
                 this.cacheDisconnectedPeers.reconnected(peerId);
             }
-            this.peerPolicyTracker.onDataTreeChanged(roleChange, IdentifierUtils.peerPath(rootPath));
+
+            // Check for removal
+            final Optional<NormalizedNode<?, ?>> maybePeerRole = roleChange.getDataAfter();
+            final YangInstanceIdentifier peerPath = IdentifierUtils.peerPath(rootPath);
+            LOG.debug("Data Changed for Peer role {} path {}, dataBefore {}, dataAfter {}", roleChange.getIdentifier(),
+                peerPath , roleChange.getDataBefore(), maybePeerRole);
+            final PeerRole role = PeerRoleUtil.roleForChange(maybePeerRole);
+            SimpleRoutingPolicy srp = getSimpleRoutingPolicy(rootNode);
+            if(PeerRole.Internal == role || SimpleRoutingPolicy.AnnounceNone == srp) {
+                return;
+            }
+            this.peerPolicyTracker.peerRoleChanged(peerPath, role);
+        }
+    }
+
+    private SimpleRoutingPolicy getSimpleRoutingPolicy(final DataTreeCandidateNode rootNode) {
+        final DataTreeCandidateNode statusChange = rootNode.getModifiedChild(SIMPLE_ROUTING_POLICY_NID);
+        if (statusChange != null) {
+            final Optional<NormalizedNode<?, ?>> maybePeerStatus = statusChange.getDataAfter();
+            if (maybePeerStatus.isPresent()) {
+                return SimpleRoutingPolicy.valueOf(BindingMapping.getClassName((String) (maybePeerStatus.get()).getValue()));
+            }
         }
+        return null;
     }
 
     private void updateNodes(final DataTreeCandidateNode table, final PeerId peerId, final DOMDataWriteTransaction tx,
index 85823de97a2d134284490e741cce44ca2c96c2bf..1d5ac44b44ed23e8a110aefd558584d2c6741a71 100644 (file)
@@ -367,6 +367,10 @@ module odl-bgp-rib-impl-cfg {
                 default ibgp;
             }
 
+            leaf simple-routing-policy {
+                type rib:simple-routing-policy;
+            }
+
             leaf initiate-connection {
                 description "If true, connection will be initiated right away from current device.
                     If not, the peer will only be registered to peer registry and available for incomming bgp connections.";
index 5170b1b8fa8a0ffe1c742495e05c8159d2645e3b..420cbe4221bb550a211ed92a6cacb37f9dd88096 100644 (file)
@@ -8,11 +8,13 @@
 package org.opendaylight.protocol.bgp.rib.impl;
 
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.never;
 
 import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.CheckedFuture;
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import org.junit.Before;
 import org.junit.Test;
@@ -32,6 +34,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.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.Rib;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.SimpleRoutingPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibIn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTables;
@@ -70,29 +73,50 @@ public class AdjRibsInWriterTest {
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        this.writer = AdjRibInWriter.create(YangInstanceIdentifier.of(Rib.QNAME), PeerRole.Ebgp, this.chain);
-        assertNotNull(this.writer);
         Mockito.doReturn("MockedTrans").when(this.tx).toString();
         Mockito.doReturn(this.tx).when(this.chain).newWriteOnlyTransaction();
         Mockito.doReturn(Mockito.mock(CheckedFuture.class)).when(this.tx).submit();
-    }
-
-    @Test
-    public void testTransform() {
-        final YangInstanceIdentifier peerPath = YangInstanceIdentifier.builder().node(Rib.QNAME).node(Peer.QNAME).nodeWithKey(Peer.QNAME, AdjRibInWriter.PEER_ID_QNAME, this.peerIp).build();
         Mockito.doNothing().when(this.tx).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
         Mockito.doNothing().when(this.tx).merge(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
         Mockito.doReturn(this.context).when(this.registry).getRIBSupportContext(Mockito.any(TablesKey.class));
         Mockito.doNothing().when(this.context).createEmptyTableStructure(Mockito.eq(this.tx), Mockito.any(YangInstanceIdentifier.class));
+    }
 
-        this.writer.transform(new PeerId(this.peerIp), this.registry, this.tableTypes, this.addPathTablesType, false);
-
-        // verify peer skeleton was inserted correctly
-        Mockito.verify(this.tx).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(peerPath), Mockito.eq(this.writer.peerSkeleton(IdentifierUtils.peerKey(peerPath), this.peerIp, false)));
+    @Test
+    public void testTransform() {
+        this.writer = AdjRibInWriter.create(YangInstanceIdentifier.of(Rib.QNAME), PeerRole.Ebgp, Optional.empty(), this.chain);
+        assertNotNull(this.writer);
+        final YangInstanceIdentifier peerPath = YangInstanceIdentifier.builder().node(Rib.QNAME).node(Peer.QNAME).nodeWithKey(Peer.QNAME,
+            AdjRibInWriter.PEER_ID_QNAME, this.peerIp).build();
+        this.writer.transform(new PeerId(this.peerIp), this.registry, this.tableTypes, this.addPathTablesType);
+        verifyPeerSkeletonInsertedCorrectly(peerPath);
         // verify supported tables were inserted for ipv4
         Mockito.verify(this.tx).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(peerPath.node(SupportedTables.QNAME).node(RibSupportUtils.toYangKey(SupportedTables.QNAME, k4))), Mockito.any(NormalizedNode.class));
-        // verify uptodate set to false
-        final YangInstanceIdentifier path = peerPath.node(AdjRibIn.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(k4)).node(Attributes.QNAME).node(AdjRibInWriter.ATTRIBUTES_UPTODATE_FALSE.getNodeType());
+        verifyUptodateSetToFalse(peerPath);
+    }
+
+    private void verifyUptodateSetToFalse(final YangInstanceIdentifier peerPath) {
+        final YangInstanceIdentifier path = peerPath.node(AdjRibIn.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(k4))
+            .node(Attributes.QNAME).node(AdjRibInWriter.ATTRIBUTES_UPTODATE_FALSE.getNodeType());
         Mockito.verify(this.tx).merge(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(path), Mockito.eq(AdjRibInWriter.ATTRIBUTES_UPTODATE_FALSE));
     }
+
+    private void verifyPeerSkeletonInsertedCorrectly(final YangInstanceIdentifier peerPath) {
+        Mockito.verify(this.tx).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(peerPath),
+            Mockito.eq(this.writer.peerSkeleton(IdentifierUtils.peerKey(peerPath), this.peerIp)));
+    }
+
+    @Test
+    public void testAnnounceNoneTransform() {
+        this.writer = AdjRibInWriter.create(YangInstanceIdentifier.of(Rib.QNAME), PeerRole.Ebgp, Optional.of(SimpleRoutingPolicy.AnnounceNone), this.chain);
+        assertNotNull(this.writer);
+        final YangInstanceIdentifier peerPath = YangInstanceIdentifier.builder().node(Rib.QNAME).node(Peer.QNAME).nodeWithKey(Peer.QNAME,
+            AdjRibInWriter.PEER_ID_QNAME, this.peerIp).build();
+        this.writer.transform(new PeerId(this.peerIp), this.registry, this.tableTypes, this.addPathTablesType);
+        verifyPeerSkeletonInsertedCorrectly(peerPath);
+        // verify supported tables were not inserted for ipv4, AnnounceNone
+        Mockito.verify(this.tx, never()).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(peerPath.node(SupportedTables.QNAME).node(RibSupportUtils.toYangKey(SupportedTables.QNAME, k4))), Mockito.any(NormalizedNode.class));
+        verifyUptodateSetToFalse(peerPath);
+
+    }
 }
\ No newline at end of file
index ed21b1e5c94fbfa8ae93a79224bec852c541351a..f85982c35c912d60bb5693ed54a1e60dce1c9869 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl;
 
+import static org.opendaylight.protocol.bgp.rib.spi.PeerRoleUtil.PEER_ROLE_NID;
+
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.CheckedFuture;
@@ -147,7 +149,7 @@ public class LocRibWriterTest {
         Mockito.doReturn(Lists.newArrayList(table)).when(tableChange).getChildNodes();
         Mockito.doReturn("table change").when(tableChange).toString();
         Mockito.doReturn(tableChange).when(node).getModifiedChild(YangInstanceIdentifier.of(SupportedTables.QNAME).getLastPathArgument());
-        Mockito.doReturn(null).when(node).getModifiedChild(AbstractPeerRoleTracker.PEER_ROLE_NID);
+        Mockito.doReturn(null).when(node).getModifiedChild(PEER_ROLE_NID);
         Mockito.doReturn(null).when(node).getModifiedChild(YangInstanceIdentifier.of(EffectiveRibIn.QNAME).getLastPathArgument());
         Mockito.doReturn(node).when(candidate).getRootNode();
         Mockito.doReturn(ModificationType.SUBTREE_MODIFIED).when(node).getModificationType();
index fc505a7892f74fee5fc90ceaa0b369e7c405fd00..dc4cc019511bc68327575c0630b563a2f213416b 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.protocol.bgp.rib.spi;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 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.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -44,16 +46,18 @@ public interface ExportPolicyPeerTracker {
      */
     PeerRole getRole(YangInstanceIdentifier peerId);
 
-    /**
-     * @param change data change
-     * @param peerPath YII of peer
-     */
-    void onDataTreeChanged(DataTreeCandidateNode change, YangInstanceIdentifier peerPath);
-
     /**
      * Check whether Peer supports Add Path
      * @param peerId
      * @return true if add-path is supported
      */
     boolean isAddPathSupportedByPeer(PeerId peerId);
+
+    /**
+     * Invoked whenever a peer role changes.
+     *
+     * @param peerPath Peer's path
+     * @param role Peer's new role, null indicates the peer has disappeared.
+     */
+    void peerRoleChanged(@Nonnull YangInstanceIdentifier peerPath,  @Nullable PeerRole role);
 }
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/PeerRoleUtil.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/PeerRoleUtil.java
new file mode 100644 (file)
index 0000000..ef71448
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.spi;
+
+import com.google.common.base.Optional;
+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.Peer;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+final public class PeerRoleUtil {
+    public static final NodeIdentifier PEER_ROLE_NID = new NodeIdentifier(QName.create(Peer.QNAME, "peer-role").intern());
+
+    private PeerRoleUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    public static PeerRole roleForChange(final Optional<NormalizedNode<?, ?>> maybePeerRole) {
+        if (maybePeerRole.isPresent()) {
+            final LeafNode<?> peerRoleLeaf = (LeafNode<?>) maybePeerRole.get();
+            return PeerRole.valueOf(BindingMapping.getClassName((String) peerRoleLeaf.getValue()));
+        }
+        return null;
+    }
+
+    public static String roleForString(final PeerRole role) {
+        switch (role) {
+        case Ebgp:
+            return "ebgp";
+        case Ibgp:
+            return "ibgp";
+        case RrClient:
+            return "rr-client";
+        case Internal:
+            return "internal";
+        default:
+            throw new IllegalArgumentException("Unhandled role " + role);
+        }
+    }
+}