From 1e5834827493f0cd8b201c754e700f1347b75249 Mon Sep 17 00:00:00 2001 From: "Claudio D. Gasparini" Date: Thu, 28 Apr 2016 14:47:54 +0200 Subject: [PATCH] BUG-4931: Simple routing policy 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 --- .../impl/add/AddPathAbstractRouteEntry.java | 3 - .../impl/base/BaseAbstractRouteEntry.java | 3 - bgp/rib-api/src/main/yang/bgp-rib.yang | 10 ++ .../rib/impl/BGPApplicationPeerModule.java | 3 +- .../yang/bgp/rib/impl/BGPPeerModule.java | 4 +- .../bgp/rib/impl/AbstractPeerRoleTracker.java | 64 ------------- .../protocol/bgp/rib/impl/AdjRibInWriter.java | 92 ++++++++++--------- .../bgp/rib/impl/ApplicationPeer.java | 6 +- .../protocol/bgp/rib/impl/BGPPeer.java | 52 +++++++---- .../rib/impl/ExportPolicyPeerTrackerImpl.java | 8 +- .../bgp/rib/impl/ImportPolicyPeerTracker.java | 9 +- .../protocol/bgp/rib/impl/LocRibWriter.java | 38 +++++++- .../src/main/yang/odl-bgp-rib-impl-cfg.yang | 4 + .../bgp/rib/impl/AdjRibsInWriterTest.java | 50 +++++++--- .../bgp/rib/impl/LocRibWriterTest.java | 4 +- .../bgp/rib/spi/ExportPolicyPeerTracker.java | 16 ++-- .../protocol/bgp/rib/spi/PeerRoleUtil.java | 49 ++++++++++ 17 files changed, 251 insertions(+), 164 deletions(-) delete mode 100644 bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractPeerRoleTracker.java create mode 100644 bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/PeerRoleUtil.java diff --git a/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/AddPathAbstractRouteEntry.java b/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/AddPathAbstractRouteEntry.java index 610ac0d9ce..419e9d6f19 100644 --- a/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/AddPathAbstractRouteEntry.java +++ b/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/AddPathAbstractRouteEntry.java @@ -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); diff --git a/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/base/BaseAbstractRouteEntry.java b/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/base/BaseAbstractRouteEntry.java index d86bfee898..83588cd79f 100644 --- a/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/base/BaseAbstractRouteEntry.java +++ b/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/base/BaseAbstractRouteEntry.java @@ -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); diff --git a/bgp/rib-api/src/main/yang/bgp-rib.yang b/bgp/rib-api/src/main/yang/bgp-rib.yang index 3432241a29..0133a49683 100644 --- a/bgp/rib-api/src/main/yang/bgp-rib.yang +++ b/bgp/rib-api/src/main/yang/bgp-rib.yang @@ -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; diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPApplicationPeerModule.java b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPApplicationPeerModule.java index 34adf15ff5..e3611b8c68 100755 --- a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPApplicationPeerModule.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPApplicationPeerModule.java @@ -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()); diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java index 69b256e112..06a830d4b4 100755 --- a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java @@ -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 index bb39dd3142..0000000000 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractPeerRoleTracker.java +++ /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> 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); -} diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java index b1533452db..85ba578f35 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java @@ -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; - private AdjRibInWriter(final YangInstanceIdentifier ribPath, final DOMTransactionChain chain, final PeerId peerId, final String role, final YangInstanceIdentifier peerPath, final Map tables) { + private AdjRibInWriter(final YangInstanceIdentifier ribPath, final DOMTransactionChain chain, final PeerRole role, + final Optional simpleRoutingPolicy, final YangInstanceIdentifier peerPath, final Map 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.emptyMap()); + static AdjRibInWriter create(@Nonnull final YangInstanceIdentifier ribId, @Nonnull final PeerRole role, final Optional 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 tableTypes, - final List addPathTablesType, final boolean isAppPeer) { + final List addPathTablesType) { final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction(); final YangInstanceIdentifier newPeerPath; - newPeerPath = createEmptyPeerStructure(newPeerId, isAppPeer, tx); - final ImmutableMap tb = createNewTableInstances(newPeerPath, isAppPeer, registry, tableTypes, addPathTablesType, tx); + newPeerPath = createEmptyPeerStructure(newPeerId, tx); + final ImmutableMap 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 createNewTableInstances(final YangInstanceIdentifier newPeerPath, final boolean isAppPeer, + private ImmutableMap createNewTableInstances(final YangInstanceIdentifier newPeerPath, final RIBSupportContextRegistry registry, final Set tableTypes, final List 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 tt = Builders.mapEntryBuilder().withNodeIdentifier(supTablesKey); for (final Entry 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 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 peerStatus) { + return peerStatus.isPresent() && peerStatus.get() == SimpleRoutingPolicy.AnnounceNone; + } + + static boolean isLearnNone(final java.util.Optional 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); + } + } } diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java index 82218f4949..7b3d04fc07 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java @@ -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(); diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java index 059b0130e4..9e332413d2 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java @@ -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 rpcRegistration; private final PeerRole peerRole; + private final Optional 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(); } diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ExportPolicyPeerTrackerImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ExportPolicyPeerTrackerImpl.java index 480c069011..35b1d78c5e 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ExportPolicyPeerTrackerImpl.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ExportPolicyPeerTrackerImpl.java @@ -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> GENERATE_PEER_ID = new Function>() { @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 peerRoles = new HashMap<>(); private final Set 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. diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ImportPolicyPeerTracker.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ImportPolicyPeerTracker.java index 2f45ddb6bc..caa736df08 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ImportPolicyPeerTracker.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ImportPolicyPeerTracker.java @@ -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 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()); diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriter.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriter.java index 305f97537d..0519a9a930 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriter.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriter.java @@ -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 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 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> 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> 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, diff --git a/bgp/rib-impl/src/main/yang/odl-bgp-rib-impl-cfg.yang b/bgp/rib-impl/src/main/yang/odl-bgp-rib-impl-cfg.yang index 85823de97a..1d5ac44b44 100644 --- a/bgp/rib-impl/src/main/yang/odl-bgp-rib-impl-cfg.yang +++ b/bgp/rib-impl/src/main/yang/odl-bgp-rib-impl-cfg.yang @@ -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."; diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibsInWriterTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibsInWriterTest.java index 5170b1b8fa..420cbe4221 100644 --- a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibsInWriterTest.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibsInWriterTest.java @@ -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 diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriterTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriterTest.java index ed21b1e5c9..f85982c35c 100644 --- a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriterTest.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriterTest.java @@ -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(); diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/ExportPolicyPeerTracker.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/ExportPolicyPeerTracker.java index fc505a7892..dc4cc01951 100644 --- a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/ExportPolicyPeerTracker.java +++ b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/ExportPolicyPeerTracker.java @@ -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 index 0000000000..ef714486e1 --- /dev/null +++ b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/PeerRoleUtil.java @@ -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> 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); + } + } +} -- 2.36.6