<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:bgp:rib:impl">prefix:bgp-table-type</type>
<name>ipv4-l3vpn</name>
</advertized-table>
+ <add-path>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:bgp:rib:impl">prefix:add-path</type>
+ <name>ipv4-unicast-both</name>
+ </add-path>
</module>
-->
}
}
+ grouping bgp-add-path-table-type {
+ uses bgp-table-type;
+ leaf send-receive {
+ type send-receive;
+ }
+ }
+
grouping destination {
choice destination-type {
// to be augmented
container add-path-capability {
reference "http://tools.ietf.org/html/draft-ietf-idr-add-paths-13#section-4";
list address-families {
- uses bgp-table-type;
- leaf send-receive {
- type send-receive;
- }
+ uses bgp-add-path-table-type;
}
}
container route-refresh-capability {
}
private boolean isTableSupported(final PeerId destPeer, final ExportPolicyPeerTracker peerPT, final TablesKey localTK) {
- if (!peerPT.isTableSupported(destPeer, localTK)) {
+ if (!peerPT.isTableSupported(destPeer)) {
LOG.trace("Route rejected, peer {} does not support this table type {}", destPeer, localTK);
return false;
}
}
list supported-tables {
key "afi safi";
- uses bgp-mp:bgp-table-type;
+ uses bgp-mp:bgp-add-path-table-type;
}
container adj-rib-in {
description "Routes as we have received them from the peer.";
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
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.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri;
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;
private static final NodeIdentifier PEER_ROLE = new NodeIdentifier(PEER_ROLE_QNAME);
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();
// 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();
* @param newPeerId new peer BGP identifier
* @param registry RIB extension registry
* @param tableTypes New tables, must not be null
+ * @param addPathTablesType
* @return New writer
*/
- AdjRibInWriter transform(final PeerId newPeerId, final RIBSupportContextRegistry registry, final Set<TablesKey> tableTypes, final boolean isAppPeer) {
+ AdjRibInWriter transform(final PeerId newPeerId, final RIBSupportContextRegistry registry, final Set<TablesKey> tableTypes,
+ final List<AddressFamilies> addPathTablesType, final boolean isAppPeer) {
final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
final YangInstanceIdentifier newPeerPath;
newPeerPath = createEmptyPeerStructure(newPeerId, isAppPeer, tx);
- final ImmutableMap<TablesKey, TableContext> tb = createNewTableInstances(newPeerPath, isAppPeer, registry, tableTypes, tx);
+ final ImmutableMap<TablesKey, TableContext> tb = createNewTableInstances(newPeerPath, isAppPeer, registry, tableTypes, addPathTablesType, tx);
tx.submit();
return new AdjRibInWriter(this.ribPath, this.chain, newPeerId, this.role, newPeerPath, tb);
* @param isAppPeer
* @param registry
* @param tableTypes
+ * @param addPathTablesType
* @param tx
* @return
*/
private ImmutableMap<TablesKey, TableContext> createNewTableInstances(final YangInstanceIdentifier newPeerPath, final boolean isAppPeer,
- final RIBSupportContextRegistry registry, final Set<TablesKey> tableTypes, final DOMDataWriteTransaction tx) {
+ final RIBSupportContextRegistry registry, final Set<TablesKey> tableTypes, final List<AddressFamilies> addPathTablesType,
+ final DOMDataWriteTransaction tx) {
+ final Map<TablesKey, SendReceive> addPathTableMaps = mapTableTypesFamilies(addPathTablesType);
final Builder<TablesKey, TableContext> tb = ImmutableMap.builder();
for (final TablesKey tableKey : tableTypes) {
final RIBSupportContext rs = registry.getRIBSupportContext(tableKey);
LOG.warn("No support for table type {}, skipping it", tableKey);
continue;
}
- installAdjRibsOutTables(isAppPeer, newPeerPath, rs, instanceIdentifierKey, tableKey, tx);
+ installAdjRibsOutTables(isAppPeer, newPeerPath, rs, instanceIdentifierKey, tableKey, addPathTableMaps.get(tableKey), tx);
installAdjRibInTables(newPeerPath, tableKey, rs, instanceIdentifierKey, tx, tb);
}
return tb.build();
}
+ private Map<TablesKey, SendReceive> mapTableTypesFamilies(final List<AddressFamilies> addPathTablesType) {
+ return Collections.unmodifiableMap(addPathTablesType.stream().collect(Collectors.toMap(af -> new TablesKey(af.getAfi(), af.getSafi()),
+ af -> af.getSendReceive())));
+ }
+
private void installAdjRibInTables(final YangInstanceIdentifier newPeerPath, final TablesKey tableKey, final RIBSupportContext rs,
final NodeIdentifierWithPredicates instanceIdentifierKey, final DOMDataWriteTransaction tx, final Builder<TablesKey, TableContext> tb) {
// We will use table keys very often, make sure they are optimized
}
private void installAdjRibsOutTables(final boolean isAppPeer, final YangInstanceIdentifier newPeerPath, final RIBSupportContext rs,
- final NodeIdentifierWithPredicates instanceIdentifierKey, final TablesKey tableKey, final DOMDataWriteTransaction tx) {
+ final NodeIdentifierWithPredicates instanceIdentifierKey, final TablesKey tableKey, final SendReceive sendReceive,
+ final DOMDataWriteTransaction tx) {
if (!isAppPeer) {
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()) {
tt.withChild(ImmutableNodes.leafNode(e.getKey(), e.getValue()));
}
+ if(sendReceive != null) {
+ tt.withChild(ImmutableNodes.leafNode(SEND_RECEIVE, sendReceive.toString().toLowerCase()));
+ }
tx.put(LogicalDatastoreType.OPERATIONAL, newPeerPath.node(PEER_TABLES).node(supTablesKey), tt.build());
rs.createEmptyTableStructure(tx, newPeerPath.node(EMPTY_ADJRIBOUT.getIdentifier()).node(TABLES).node(instanceIdentifierKey));
}
import com.google.common.net.InetAddresses;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
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;
private final DOMTransactionChain chain;
private final DOMTransactionChain writerChain;
private final BGPConfigModuleTracker moduleTracker;
-
private AdjRibInWriter writer;
public ApplicationPeer(final ApplicationRibId applicationRibId, final Ipv4Address ipAddress, final RIBImpl rib, final BGPConfigModuleTracker
this.chain = targetRib.createPeerChain(this);
this.writerChain = targetRib.createPeerChain(this);
this.writer = AdjRibInWriter.create(targetRib.getYangRibId(), PeerRole.Internal, this.writerChain);
- this.writer = this.writer.transform(RouterIds.createPeerId(ipAddress), targetRib.getRibSupportContext(), targetRib.getLocalTablesKeys(), true);
+ this.writer = this.writer.transform(RouterIds.createPeerId(ipAddress), targetRib.getRibSupportContext(), targetRib.getLocalTablesKeys(),
+ Collections.emptyList(), true);
this.moduleTracker = moduleTracker;
if (moduleTracker != null) {
moduleTracker.onInstanceCreate();
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.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
@Override
public synchronized void onSessionUp(final BGPSession session) {
- LOG.info("Session with peer {} went up with tables: {}", this.name, session.getAdvertisedTableTypes());
+ final List<AddressFamilies> addPathTablesType = session.getAdvertisedAddPathTableTypes();
+ LOG.info("Session with peer {} went up with tables {} and Add Path tables {}", this.name, addPathTablesType,
+ session.getAdvertisedAddPathTableTypes());
this.session = session;
this.rawIdentifier = InetAddresses.forString(session.getBgpId().getValue()).getAddress();
final PeerId peerId = RouterIds.createPeerId(session.getBgpId());
createAdjRibOutListener(peerId);
- this.ribWriter = this.ribWriter.transform(peerId, this.rib.getRibSupportContext(), this.tables, false);
+ this.ribWriter = this.ribWriter.transform(peerId, this.rib.getRibSupportContext(), this.tables, addPathTablesType, false);
this.sessionEstablishedCounter++;
if (this.registrator != null) {
this.runtimeReg = this.registrator.register(this);
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.SimpleChannelInboundHandler;
import java.io.IOException;
import java.util.Date;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.GuardedBy;
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.CParameters1;
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.open.bgp.parameters.optional.capabilities.c.parameters.AddPathCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.slf4j.Logger;
private State state = State.OPEN_CONFIRM;
private final Set<BgpTableType> tableTypes;
+ private final List<AddressFamilies> addPathTypes;
private final int holdTimerValue;
private final int keepAlive;
private final AsNumber asNumber;
public BGPSessionImpl(final BGPSessionListener listener, final Channel channel, final Open remoteOpen, final BGPSessionPreferences localPreferences,
final BGPPeerRegistry peerRegistry) {
this(listener, channel, remoteOpen, localPreferences.getHoldTime(), peerRegistry);
- this.sessionStats = new BGPSessionStats(remoteOpen, this.holdTimerValue, this.keepAlive, channel, Optional.of(localPreferences), this.tableTypes);
+ this.sessionStats = new BGPSessionStats(remoteOpen, this.holdTimerValue, this.keepAlive, channel, Optional.of(localPreferences), this.tableTypes, this.addPathTypes);
}
public BGPSessionImpl(final BGPSessionListener listener, final Channel channel, final Open remoteOpen, final int localHoldTimer,
final Set<TablesKey> tts = Sets.newHashSet();
final Set<BgpTableType> tats = Sets.newHashSet();
+ final List<AddressFamilies> addPathCapabilitiesList = Lists.newArrayList();
if (remoteOpen.getBgpParameters() != null) {
for (final BgpParameters param : remoteOpen.getBgpParameters()) {
for (final OptionalCapabilities optCapa : param.getOptionalCapabilities()) {
final CParameters cParam = optCapa.getCParameters();
- if ( cParam.getAugmentation(CParameters1.class) == null ||
- cParam.getAugmentation(CParameters1.class).getMultiprotocolCapability() == null ) {
+ if ( cParam.getAugmentation(CParameters1.class) == null) {
continue;
}
- final MultiprotocolCapability multi = cParam.getAugmentation(CParameters1.class).getMultiprotocolCapability();
- final TablesKey tt = new TablesKey(multi.getAfi(), multi.getSafi());
- LOG.trace("Added table type to sync {}", tt);
- tts.add(tt);
- tats.add(new BgpTableTypeImpl(tt.getAfi(), tt.getSafi()));
+ if(cParam.getAugmentation(CParameters1.class).getMultiprotocolCapability() != null) {
+ final MultiprotocolCapability multi = cParam.getAugmentation(CParameters1.class).getMultiprotocolCapability();
+ final TablesKey tt = new TablesKey(multi.getAfi(), multi.getSafi());
+ LOG.trace("Added table type to sync {}", tt);
+ tts.add(tt);
+ tats.add(new BgpTableTypeImpl(tt.getAfi(), tt.getSafi()));
+ } else if (cParam.getAugmentation(CParameters1.class).getAddPathCapability() != null) {
+ final AddPathCapability addPathCap = cParam.getAugmentation(CParameters1.class).getAddPathCapability();
+ addPathCapabilitiesList.addAll(addPathCap.getAddressFamilies());
+ }
}
}
}
this.sync = new BGPSynchronization(this.listener, tts);
this.tableTypes = tats;
+ this.addPathTypes = addPathCapabilitiesList;
if (this.holdTimerValue != 0) {
channel.eventLoop().schedule(new Runnable() {
}
this.bgpId = remoteOpen.getBgpIdentifier();
this.sessionStats = new BGPSessionStats(remoteOpen, this.holdTimerValue, this.keepAlive, channel, Optional.<BGPSessionPreferences>absent(),
- this.tableTypes);
+ this.tableTypes, this.addPathTypes);
}
@Override
return this.tableTypes;
}
+ @Override
+ public List<AddressFamilies> getAdvertisedAddPathTableTypes() {
+ return this.addPathTypes;
+ }
+
protected synchronized void sessionUp() {
this.sessionStats.startSessionStopwatch();
this.state = State.UP;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import org.opendaylight.controller.config.yang.bgp.rib.impl.AdvertisedAddPathTableTypes;
import org.opendaylight.controller.config.yang.bgp.rib.impl.AdvertizedTableTypes;
import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState;
import org.opendaylight.controller.config.yang.bgp.rib.impl.ErrorMsgs;
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.CParameters1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies;
final class BGPSessionStats {
private final Stopwatch sessionStopwatch;
private final ErrorMsgs errMsgs = new ErrorMsgs();
public BGPSessionStats(final Open remoteOpen, final int holdTimerValue, final int keepAlive, final Channel channel,
- final Optional<BGPSessionPreferences> localPreferences, final Collection<BgpTableType> tableTypes) {
+ final Optional<BGPSessionPreferences> localPreferences, final Collection<BgpTableType> tableTypes, final List<AddressFamilies> addPathTypes) {
this.sessionStopwatch = Stopwatch.createUnstarted();
this.stats = new BgpSessionState();
this.stats.setHoldtimeCurrent(holdTimerValue);
this.stats.setKeepaliveCurrent(keepAlive);
- this.stats.setPeerPreferences(setPeerPref(remoteOpen, channel, tableTypes));
+ this.stats.setPeerPreferences(setPeerPref(remoteOpen, channel, tableTypes, addPathTypes));
this.stats.setSpeakerPreferences(setSpeakerPref(channel, localPreferences));
initMsgs();
}
return att;
}
+ private static AdvertisedAddPathTableTypes addAddPathTableType(final AddressFamilies addressFamilies) {
+ Preconditions.checkNotNull(addressFamilies);
+ final AdvertisedAddPathTableTypes att = new AdvertisedAddPathTableTypes();
+ att.setAfi(addressFamilies.getAfi().getSimpleName());
+ att.setSafi(addressFamilies.getSafi().getSimpleName());
+ att.setSendReceive(addressFamilies.getSendReceive().toString());
+ return att;
+ }
+
private static SpeakerPreferences setSpeakerPref(final Channel channel, final Optional<BGPSessionPreferences> localPreferences) {
Preconditions.checkNotNull(channel);
final SpeakerPreferences pref = new SpeakerPreferences();
return pref;
}
- private static PeerPreferences setPeerPref(final Open remoteOpen, final Channel channel, final Collection<BgpTableType> tableTypes) {
+ private static PeerPreferences setPeerPref(final Open remoteOpen, final Channel channel, final Collection<BgpTableType> tableTypes,
+ final List<AddressFamilies> addPathTypes) {
Preconditions.checkNotNull(remoteOpen);
Preconditions.checkNotNull(channel);
final PeerPreferences pref = new PeerPreferences();
pref.setBgpId(remoteOpen.getBgpIdentifier().getValue());
pref.setAs(remoteOpen.getMyAsNumber().longValue());
pref.setHoldtime(remoteOpen.getHoldTimer());
- final List<AdvertizedTableTypes> tt = new ArrayList<>();
- for (final BgpTableType t : tableTypes) {
- tt.add(addTableType(t));
- }
+
+ final List<AdvertizedTableTypes> tt = tableTypes.stream().map(BGPSessionStats::addTableType).collect(Collectors.toList());
+ final List<AdvertisedAddPathTableTypes> addPathTableTypeList = addPathTypes.stream().map(BGPSessionStats::addAddPathTableType)
+ .collect(Collectors.toList());
+
if (remoteOpen.getBgpParameters() != null) {
for (final BgpParameters param : remoteOpen.getBgpParameters()) {
for (final OptionalCapabilities capa : param.getOptionalCapabilities()) {
}
}
pref.setAdvertizedTableTypes(tt);
+ pref.setAdvertisedAddPathTableTypes(addPathTableTypeList);
return pref;
}
}
package org.opendaylight.protocol.bgp.rib.impl;
import com.google.common.base.Function;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Collections2;
-import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
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.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.rib.rev130925.PeerId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+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.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+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 {
private static final Logger LOG = LoggerFactory.getLogger(ExportPolicyPeerTrackerImpl.class);
- private static final Function<YangInstanceIdentifier, Entry<PeerId, YangInstanceIdentifier>> GENERATE_PEERID = new Function<YangInstanceIdentifier, Entry<PeerId, YangInstanceIdentifier>>() {
+ private static final Function<YangInstanceIdentifier, Entry<PeerId, YangInstanceIdentifier>> GENERATE_PEER_ID = new Function<YangInstanceIdentifier, Entry<PeerId, YangInstanceIdentifier>>() {
@Override
public Entry<PeerId, YangInstanceIdentifier> apply(final YangInstanceIdentifier input) {
final PeerId peerId = IdentifierUtils.peerId((NodeIdentifierWithPredicates) input.getLastPathArgument());
return new AbstractMap.SimpleImmutableEntry<>(peerId, input);
}
};
-
+ 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 final Map<YangInstanceIdentifier, PeerRole> peerRoles = new HashMap<>();
- private final HashMultimap<PeerId, NodeIdentifierWithPredicates> peerTables = HashMultimap.create();
- private volatile Map<PeerRole, PeerExportGroup> groups = Collections.emptyMap();
+ private final Set<PeerId> peerTables = Sets.newHashSet();
private final PolicyDatabase policyDatabase;
+ private final Map<PeerId, SendReceive> peerAddPathTables = new HashMap<>();
+ private final TablesKey localTableKey;
+ private volatile Map<PeerRole, PeerExportGroup> groups = Collections.emptyMap();
- ExportPolicyPeerTrackerImpl(final PolicyDatabase policyDatabase) {
+ ExportPolicyPeerTrackerImpl(final PolicyDatabase policyDatabase, final TablesKey localTablesKey) {
this.policyDatabase = Preconditions.checkNotNull(policyDatabase);
+ this.localTableKey = localTablesKey;
}
private Map<PeerRole, PeerExportGroup> createGroups(final Map<YangInstanceIdentifier, PeerRole> peerPathRoles) {
final Map<PeerRole, PeerExportGroup> ret = new EnumMap<>(PeerRole.class);
for (final Entry<PeerRole, Collection<YangInstanceIdentifier>> e : roleToIds.asMap().entrySet()) {
final AbstractExportPolicy policy = this.policyDatabase.exportPolicyForRole(e.getKey());
- final Collection<Entry<PeerId, YangInstanceIdentifier>> peers = ImmutableList.copyOf(Collections2.transform(e.getValue(), GENERATE_PEERID));
+ final Collection<Entry<PeerId, YangInstanceIdentifier>> peers = ImmutableList.copyOf(Collections2.transform(e.getValue(), GENERATE_PEER_ID));
ret.put(e.getKey(), new PeerExportGroupImpl(peers, allPeerRoles, policy));
}
}
}
+ @Override
+ public void onTablesChanged(final PeerId peerId, final DataTreeCandidateNode tablesChange) {
+ final NodeIdentifierWithPredicates supTablesKey = RibSupportUtils.toYangKey(SupportedTables.QNAME, this.localTableKey);
+ final DataTreeCandidateNode localTableNode = tablesChange.getModifiedChild(supTablesKey);
+ if (localTableNode != null) {
+ final Optional<NormalizedNode<?, ?>> dataAfter = localTableNode.getDataAfter();
+ processSupportedSendReceiveTables(localTableNode.getModifiedChild(SEND_RECEIVE_NID), peerId);
+ if (dataAfter.isPresent()) {
+ final boolean added = this.peerTables.add(peerId);
+ if (added) {
+ LOG.debug("Supported table {} added to peer {}", this.localTableKey, peerId);
+ }
+ } else {
+ final NodeIdentifierWithPredicates value = (NodeIdentifierWithPredicates) localTableNode.getIdentifier();
+ this.peerTables.remove(peerId);
+ LOG.debug("Removed tables {} from peer {}", value, peerId);
+ }
+ }
+ }
+
@Override
public PeerExportGroup getPeerGroup(final PeerRole role) {
return this.groups.get(Preconditions.checkNotNull(role));
}
@Override
- public void onTablesChanged(final PeerId peerId, final DataTreeCandidateNode node) {
- if (node.getDataAfter().isPresent()) {
- final NodeIdentifierWithPredicates value = (NodeIdentifierWithPredicates) node.getDataAfter().get().getIdentifier();
- final boolean added = this.peerTables.put(peerId, value);
- if (added) {
- LOG.debug("Supported table {} added to peer {}", value, peerId);
+ public PeerRole getRole(final YangInstanceIdentifier peerId) {
+ return this.peerRoles.get(peerId);
+ }
+
+ private void processSupportedSendReceiveTables(final DataTreeCandidateNode sendReceiveModChild, final PeerId peerId) {
+ if (sendReceiveModChild != null) {
+ if (sendReceiveModChild.getModificationType().equals(ModificationType.DELETE)) {
+ final Optional<NormalizedNode<?, ?>> sendReceiveNode = sendReceiveModChild.getDataBefore();
+ if (sendReceiveNode.isPresent()) {
+ final SendReceive sendReceiveValue = SendReceive.valueOf(BindingMapping.getClassName((String) sendReceiveNode.get().getValue()));
+ this.peerAddPathTables.remove(peerId);
+ LOG.debug("Supported Add BestPath table {} removed to peer {}", sendReceiveValue, peerId);
+ }
+ } else {
+ final Optional<NormalizedNode<?, ?>> sendReceiveNode = sendReceiveModChild.getDataAfter();
+ if (sendReceiveNode.isPresent()) {
+ final SendReceive sendReceiveValue = SendReceive.valueOf(BindingMapping.getClassName((String) sendReceiveNode.get().getValue()));
+ this.peerAddPathTables.put(peerId, sendReceiveValue);
+ LOG.debug("Supported Add BestPath table {} added to peer {}", sendReceiveValue, peerId);
+ }
}
- } else {
- final NodeIdentifierWithPredicates value = (NodeIdentifierWithPredicates) node.getIdentifier();
- this.peerTables.remove(peerId,value);
- LOG.debug("Removed tables {} from peer {}", value, peerId);
}
}
@Override
- public boolean isTableSupported(final PeerId peerId, final TablesKey tablesKey) {
- return this.peerTables.get(peerId).contains(RibSupportUtils.toYangKey(SupportedTables.QNAME, tablesKey));
+ public boolean isTableSupported(final PeerId peerId) {
+ return this.peerTables.contains(peerId);
}
- public PeerRole getRole(final YangInstanceIdentifier peerId) {
- return this.peerRoles.get(peerId);
+ @Override
+ public boolean isAddPathSupportedByPeer(final PeerId peerId) {
+ final SendReceive sendReceive = this.peerAddPathTables.get(peerId);
+ return sendReceive != null && (sendReceive.equals(SendReceive.Both) || sendReceive.equals(SendReceive.Receive));
}
}
\ No newline at end of file
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import javax.annotation.Nonnull;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.bgp.rib.rib.loc.rib.tables.routes.Ipv4RoutesCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.prefixes.DestinationIpv4;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
final class IPv4RIBSupport extends AbstractIPRIBSupport {
@VisibleForTesting
static final QName PREFIX_QNAME = QName.create(Ipv4Route.QNAME, "prefix").intern();
+ private static final QName PATHID_QNAME = QName.create(Ipv4Route.QNAME, "path-id").intern();
private static final IPv4RIBSupport SINGLETON = new IPv4RIBSupport();
private static final ImmutableCollection<Class<? extends DataObject>> CACHEABLE_NLRI_OBJECTS =
ImmutableSet.<Class<? extends DataObject>>of(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.Ipv4Prefix.class);
private final NodeIdentifier ipv4Route = new NodeIdentifier(Ipv4Route.QNAME);
private final NodeIdentifier nlriRoutesList = new NodeIdentifier(Ipv4Prefixes.QNAME);
private final NodeIdentifier routeKeyLeaf = new NodeIdentifier(PREFIX_QNAME);
+ private final NodeIdentifier pathIdLeaf = new NodeIdentifier(PATHID_QNAME);
private IPv4RIBSupport() {
super(Ipv4RoutesCase.class, Ipv4Routes.class, Ipv4Route.class);
return CACHEABLE_NLRI_OBJECTS;
}
+ @Nonnull
+ @Override
+ public PathArgument getRouteIdAddPath(final long pathId, final PathArgument routeId) {
+ final String prefix = (String) (((NodeIdentifierWithPredicates) routeId).getKeyValues()).get(PREFIX_QNAME);
+ final ImmutableMap<QName, Object> keyValues = ImmutableMap.of(PATHID_QNAME, pathId, PREFIX_QNAME, prefix);
+
+ return new NodeIdentifierWithPredicates(Ipv4Route.QNAME, keyValues);
+ }
+
+ @Override
+ public long extractPathId(final NormalizedNode<?, ?> data) {
+ final NormalizedNode<?, ?> pathId = NormalizedNodes.findNode(data, pathIdLeaf).orNull();
+ if (pathId == null) {
+ return 0;
+ }
+ return (Long) pathId.getValue();
+ }
+
private List<Ipv4Prefixes> extractPrefixes(final Collection<MapEntryNode> routes) {
final List<Ipv4Prefixes> prefs = new ArrayList<>(routes.size());
for (final MapEntryNode route : routes) {
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;
this.ourAs = Preconditions.checkNotNull(ourAs);
this.ribSupport = registry.getRIBSupportContext(tablesKey).getRibSupport();
this.attributesIdentifier = this.ribSupport.routeAttributesIdentifier();
- this.peerPolicyTracker = new ExportPolicyPeerTrackerImpl(pd);
+ this.peerPolicyTracker = new ExportPolicyPeerTrackerImpl(pd, this.localTablesKey);
this.cacheDisconnectedPeers = cacheDisconnectedPeers;
this.pathSelectionMode = pathSelectionMode;
LOG.trace("Skipping change {}", rootNode.getIdentifier());
return;
}
- initializeTableWithExistenRoutes(table, peerId, rootPath, tx);
+ initializeTableWithExistentRoutes(table, peerId, rootPath, tx);
updateNodes(table, peerId, tx, ret);
}
private void filterOutChangesToSupportedTables(final PeerId peerIdOfNewPeer, final DataTreeCandidateNode rootNode) {
final DataTreeCandidateNode tablesChange = rootNode.getModifiedChild(AbstractPeerRoleTracker.PEER_TABLES);
if (tablesChange != null) {
- final NodeIdentifierWithPredicates supTablesKey = RibSupportUtils.toYangKey(SupportedTables.QNAME, this.localTablesKey);
- final DataTreeCandidateNode containsLocalKeyTable = tablesChange.getModifiedChild(supTablesKey);
- if (containsLocalKeyTable != null) {
- this.peerPolicyTracker.onTablesChanged(peerIdOfNewPeer, containsLocalKeyTable);
- }
+ this.peerPolicyTracker.onTablesChanged(peerIdOfNewPeer, tablesChange);
}
}
- private void initializeTableWithExistenRoutes(final DataTreeCandidateNode table, final PeerId peerIdOfNewPeer, final YangInstanceIdentifier rootPath,
+ private void initializeTableWithExistentRoutes(final DataTreeCandidateNode table, final PeerId peerIdOfNewPeer, final YangInstanceIdentifier rootPath,
final DOMDataWriteTransaction tx) {
- if (!table.getDataBefore().isPresent() && this.peerPolicyTracker.isTableSupported(peerIdOfNewPeer, this.localTablesKey)) {
+ if (!table.getDataBefore().isPresent() && this.peerPolicyTracker.isTableSupported(peerIdOfNewPeer)) {
LOG.debug("Peer {} table has been created, inserting existent routes", peerIdOfNewPeer);
final PeerRole newPeerRole = this.peerPolicyTracker.getRole(IdentifierUtils.peerPath(rootPath));
final PeerExportGroup peerGroup = this.peerPolicyTracker.getPeerGroup(newPeerRole);
}
}
+ grouping afi-safi {
+ leaf afi {
+ description "Address Family Identifier.";
+ type string;
+ default "";
+ }
+ leaf safi {
+ description "Subsequent Address Family Identifier.";
+ type string;
+ default "";
+ }
+ }
+
grouping preferences {
leaf bgp-id {
description "The BGP Identifier.";
list advertized-table-types {
description "The BGP Table-type capabilities advertized by the BGP peer.";
- leaf afi {
- description "Address Family Identifier.";
- type string;
- default "";
- }
- leaf safi {
- description "Subsequent Address Family Identifier.";
+ uses afi-safi;
+ }
+
+ list advertised-add-path-table-types {
+ description "The BGP Table-type capabilities advertized by the BGP peer.";
+ uses afi-safi;
+ leaf send-receive {
+ description "Send Receive Add Path Configuration.";
type string;
default "";
}
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.CheckedFuture;
+import java.util.Collections;
+import java.util.List;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
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.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamiliesBuilder;
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;
private static final TablesKey k4 = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
private final Set<TablesKey> tableTypes = Sets.newHashSet(k4);
+
+ private static final AddressFamilies addressFamilies = new AddressFamiliesBuilder().setAfi(Ipv4AddressFamily.class)
+ .setSafi(UnicastSubsequentAddressFamily.class).setSendReceive(SendReceive.Both).build();
+ private final List<AddressFamilies> addPathTablesType = Collections.singletonList(addressFamilies);
private final String peerIp = "12.34.56.78";
@Before
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, false);
+ 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)));
*/
package org.opendaylight.protocol.bgp.rib.mock;
+import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import io.netty.channel.ChannelHandlerContext;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParameters;
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.CParameters1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.AddPathCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies;
import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.slf4j.Logger;
listener.onSessionTerminated(null, null);
} else if (message instanceof Open) {
final Set<BgpTableType> tts = Sets.newHashSet();
+ final List<AddressFamilies> addPathCapabilitiesList = Lists.newArrayList();
for (final BgpParameters param : ((Open) message).getBgpParameters()) {
for (final OptionalCapabilities capa : param.getOptionalCapabilities()) {
final CParameters cParam = capa.getCParameters();
- if (cParam.getAugmentation(CParameters1.class) != null && cParam.getAugmentation(CParameters1.class)
- .getMultiprotocolCapability() != null) {
+ if (cParam.getAugmentation(CParameters1.class) == null) {
+ continue;
+ }
+ if (cParam.getAugmentation(CParameters1.class).getMultiprotocolCapability() != null) {
final MultiprotocolCapability p = cParam.getAugmentation(CParameters1.class).getMultiprotocolCapability();
LOG.debug("Adding open parameter {}", p);
final BgpTableType type = new BgpTableTypeImpl(p.getAfi(), p.getSafi());
tts.add(type);
+ } else if (cParam.getAugmentation(CParameters1.class).getAddPathCapability() != null) {
+ final AddPathCapability addPathCap = cParam.getAugmentation(CParameters1.class).getAddPathCapability();
+ addPathCapabilitiesList.addAll(addPathCap.getAddressFamilies());
}
}
}
return new AsNumber(AS);
}
+ @Override
+ public List<AddressFamilies> getAdvertisedAddPathTableTypes() {
+ return Collections.emptyList();
+ }
+
});
}
}
import java.util.Collection;
import java.util.Collections;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.UpdateBuilder;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+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;
}
}
+ @Nullable
+ @Override
+ /**
+ * Return null for non supporting Add path models
+ */
+ public PathArgument getRouteIdAddPath(final long pathId, final PathArgument routeId) {
+ return null;
+ }
+
+ @Override
+ public long extractPathId(final NormalizedNode<?, ?> data) {
+ return 0;
+ }
}
--- /dev/null
+/*
+ * 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 javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Interface implemented to be extended by RibSupport.
+ * This interface exposes methods to access to Add Path information
+ */
+public interface AddPathRibSupport {
+ /**
+ * Extract PathId from route change received
+ *
+ * @param normalizedNode
+ * @return pathId The path identifier from data change, in case its not provided or supported return 0 by default
+ */
+ long extractPathId(NormalizedNode<?, ?> normalizedNode);
+
+ /**
+ * Construct a PathArgument to an AddPathRoute
+ *
+ * @param pathId The path identifier
+ * @param routeId PathArgument leaf path
+ * @return routeId PathArgument + pathId or Null in case Add-path is not supported
+ */
+ @Nullable PathArgument getRouteIdAddPath(long pathId, PathArgument routeId);
+}
package org.opendaylight.protocol.bgp.rib.spi;
import io.netty.channel.ChannelInboundHandler;
+import java.util.List;
import java.util.Set;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
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.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies;
/**
* BGP Session represents the finite state machine in BGP, including timers and its purpose is to create a BGP
* @return Peer's AS Number
*/
AsNumber getAsNumber();
+ /**
+ * Return a list with Add Path tables supported advertised and corresponding SendReceive mode.
+ *
+ * @return AddPathTables supported
+ */
+ List<AddressFamilies> getAdvertisedAddPathTableTypes();
+
}
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.TablesKey;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
/**
* check whether the peer supports the table
* @param peerId of peer
- * @param tablesKey to be checked
* @return true if peer supports table
*/
- boolean isTableSupported(PeerId peerId, TablesKey tablesKey);
+ boolean isTableSupported(PeerId peerId);
/**
* @param peerId of peer
* @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);
}
* to register an implementation of this class and the RIB core then calls into it
* to inquire about details specific to that particular model.
*/
-public interface RIBSupport {
+public interface RIBSupport extends AddPathRibSupport {
/**
* Return the table-type-specific empty routes container, as augmented into the
* bgp-rib model under /rib/tables/routes choice node. This needs to include all
package org.opendaylight.protocol.bgp.rib.spi;
import com.google.common.collect.ImmutableMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpAddPathTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTablesKey;
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.types.rev130919.AddressFamily;
private static final QName AFI_QNAME = QName.create(Tables.QNAME, "afi").intern();
private static final QName SAFI_QNAME = QName.create(Tables.QNAME, "safi").intern();
+ private static final QName ADD_PATH_AFI_QNAME = QName.create(BgpAddPathTableType.QNAME, "afi").intern();
+ private static final QName ADD_PATH_SAFI_QNAME = QName.create(BgpAddPathTableType.QNAME, "safi").intern();
private RibSupportUtils() {
throw new UnsupportedOperationException("Utility class");
return new NodeIdentifierWithPredicates(id, keyValues);
}
+
+ /**
+ * Creates Yang Instance Identifier path argument from supplied AFI and SAFI
+ *
+ * @param id QNAME representing node
+ * @param afi Class representing AFI
+ * @param safi Class representing SAFI
+ * @return NodeIdentifierWithPredicates of 'id' for specified AFI, SAFI combination.
+ */
+ public static NodeIdentifierWithPredicates toYangPathKey(final QName id, final Class<? extends AddressFamily> afi,
+ final Class<? extends SubsequentAddressFamily> safi) {
+ final ImmutableMap<QName, Object> keyValues = ImmutableMap.<QName, Object>of(
+ ADD_PATH_AFI_QNAME, BindingReflections.findQName(afi),
+ ADD_PATH_SAFI_QNAME, BindingReflections.findQName(safi));
+ return new NodeIdentifierWithPredicates(id, keyValues);
+ }
+
/**
* Creates Yang Instance Identifier path argument from supplied {@link TablesKey}
*
return toYangKey(id, k.getAfi(), k.getSafi());
}
+ /**
+ * Creates Yang Instance Identifier path argument from supplied {@link TablesKey}
+ *
+ * @param id QNAME representing node
+ * @param k Add PAth Tables key representing table.
+ * @return NodeIdentifierWithPredicates of 'id' for specified AFI, SAFI combination.
+ */
+ public static NodeIdentifierWithPredicates toYangKey(final QName id, final SupportedTablesKey k) {
+ return toYangPathKey(id, k.getAfi(), k.getSafi());
+ }
+
/**
* Creates Yang Instance Identifier path argument from supplied {@link TablesKey}
*
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.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
return null;
}
+ @Override
+ public PathArgument getRouteIdAddPath(final long pathId, final PathArgument routeId) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
protected NodeIdentifier destinationContainerIdentifier() {
return new NodeIdentifier(DestinationIpv4.QNAME);
return false;
}
+ @Override
+ public long extractPathId(final NormalizedNode<?, ?> normalizedNode) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
protected MpReachNlri buildReach(final Collection<MapEntryNode> routes, final CNextHop hop) {
return null;