public static SidLabelIndex parseSidLabelIndex(final Size length, final ByteBuf buffer) {
switch (length) {
case LABEL:
- return new LocalLabelCaseBuilder()
- .setLocalLabel(new MplsLabel(Uint32.valueOf(buffer.readUnsignedMedium() & LABEL_MASK))).build();
+ return new LocalLabelCaseBuilder().setLocalLabel(new MplsLabel(readLabel(buffer))).build();
case SID:
return new SidCaseBuilder().setSid(ByteBufUtils.readUint32(buffer)).build();
case IPV6_ADD:
}
}
+ private static Uint32 readLabel(final ByteBuf buffer) {
+ return Uint32.valueOf(buffer.readUnsignedMedium() & LABEL_MASK);
+ }
+
+ /**
+ * Parses SID/Label/Index value into appropriate type based on V-Flag and L-Flag
+ * values. This method is required as some device-side implementations
+ * incorrectly encode SID/Label/Index value using wrong type e.g. Label type to
+ * encode an Index value (V-Flag=false, L-Flag=false).
+ *
+ * @param length length of SID/Label/Index value
+ * @param buffer buffer containing SID/Label/Index value
+ * @param isValue V-Flag value
+ * @param isLocal L-Flag value
+ * @return SID/Label/Index value parsed into the appropriate type
+ */
+ public static SidLabelIndex parseSidLabelIndexByFlags(final Size length, final ByteBuf buffer,
+ final boolean isValue, final boolean isLocal) {
+ switch (length) {
+ case LABEL:
+ return getSidLabelIndexByFlags(readLabel(buffer), isValue, isLocal);
+ case SID:
+ return getSidLabelIndexByFlags(ByteBufUtils.readUint32(buffer), isValue, isLocal);
+ case IPV6_ADD:
+ return new Ipv6AddressCaseBuilder().setIpv6Address(Ipv6Util.addressForByteBuf(buffer)).build();
+ default:
+ return null;
+ }
+ }
+
+ private static SidLabelIndex getSidLabelIndexByFlags(final Uint32 sidLabelIndex, final boolean isValue,
+ final boolean isLocal) {
+ if (isValue && isLocal) {
+ return new LocalLabelCaseBuilder().setLocalLabel(new MplsLabel(sidLabelIndex)).build();
+ } else if (!isValue && !isLocal) {
+ return new SidCaseBuilder().setSid(sidLabelIndex).build();
+ } else {
+ return null;
+ }
+ }
+
static void setFlags(final SidLabelIndex tlv, final BitArray flags, final int value, final int local) {
if (tlv instanceof LocalLabelCase) {
flags.set(value, Boolean.TRUE);
adjFlags = parseFlags(flags, protocolId);
weight = new Weight(ByteBufUtils.readUint8(buffer));
buffer.skipBytes(RESERVED);
- sidValue = SidLabelIndexParser.parseSidLabelIndex(Size.forValue(buffer.readableBytes()), buffer);
+ final boolean isValue;
+ final boolean isLocal;
+ switch (protocolId) {
+ case IsisLevel1:
+ case IsisLevel2:
+ isValue = flags.get(VALUE_ISIS);
+ isLocal = flags.get(LOCAL_ISIS);
+ break;
+ case Ospf:
+ case OspfV3:
+ isValue = flags.get(VALUE_OSPF);
+ isLocal = flags.get(LOCAL_OSPF);
+ break;
+ default:
+ return null;
+ }
+ sidValue = SidLabelIndexParser.parseSidLabelIndexByFlags(Size.forValue(buffer.readableBytes()), buffer,
+ isValue, isLocal);
} else {
adjFlags = null;
weight = null;
final Weight weight;
final SidLabelIndex sidValue;
if (buffer.isReadable()) {
- buffer.skipBytes(FLAGS_BYTE_SIZE);
+ final BitArray flags = BitArray.valueOf(buffer, FLAGS_BITS_SIZE);
weight = new Weight(ByteBufUtils.readUint8(buffer));
buffer.skipBytes(RESERVED);
- sidValue = SidLabelIndexParser.parseSidLabelIndex(Size.forValue(buffer.readableBytes()), buffer);
+ sidValue = SidLabelIndexParser.parseSidLabelIndexByFlags(Size.forValue(buffer.readableBytes()), buffer,
+ flags.get(VALUE_EPE), flags.get(LOCAL_EPE));
} else {
weight = null;
sidValue = null;
srLanAdjIdBuilder.setFlags(parseFlags(flags, protocolId));
srLanAdjIdBuilder.setWeight(new Weight(ByteBufUtils.readUint8(buffer)));
buffer.skipBytes(RESERVED);
+ final boolean isValue;
+ final boolean isLocal;
switch (protocolId) {
case IsisLevel1:
case IsisLevel2:
+ isValue = flags.get(VALUE_ISIS);
+ isLocal = flags.get(LOCAL_ISIS);
srLanAdjIdBuilder.setIsoSystemId(new IsoSystemIdentifier(
ByteArray.readBytes(buffer, ISO_SYSTEM_ID_SIZE)));
break;
case Ospf:
case OspfV3:
+ isValue = flags.get(VALUE_OSPF);
+ isLocal = flags.get(LOCAL_OSPF);
srLanAdjIdBuilder.setNeighborId(Ipv4Util.addressForByteBuf(buffer));
break;
default:
return null;
}
// length determines a type of next field, which is used for parsing
- srLanAdjIdBuilder.setSidLabelIndex(SidLabelIndexParser.parseSidLabelIndex(
- Size.forValue(buffer.readableBytes()), buffer));
+ srLanAdjIdBuilder.setSidLabelIndex(SidLabelIndexParser
+ .parseSidLabelIndexByFlags(Size.forValue(buffer.readableBytes()), buffer, isValue, isLocal));
return srLanAdjIdBuilder.build();
}
}
public static SrPrefix parseSrPrefix(final ByteBuf buffer, final ProtocolId protocol) {
- final SrPrefixBuilder builder = new SrPrefixBuilder();
- builder.setFlags(parsePrefixFlags(BitArray.valueOf(buffer, FLAGS_SIZE), protocol));
- builder.setAlgorithm(Algorithm.forValue(buffer.readUnsignedByte()));
+ final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
+ final SrPrefixBuilder builder = new SrPrefixBuilder()
+ .setFlags(parsePrefixFlags(flags, protocol))
+ .setAlgorithm(Algorithm.forValue(buffer.readUnsignedByte()));
buffer.skipBytes(RESERVED_PREFIX);
- builder.setSidLabelIndex(SidLabelIndexParser.parseSidLabelIndex(Size.forValue(buffer.readableBytes()), buffer));
- return builder.build();
+ return builder.setSidLabelIndex(
+ SidLabelIndexParser.parseSidLabelIndexByFlags(Size.forValue(buffer.readableBytes()), buffer,
+ flags.get(VALUE), flags.get(LOCAL)))
+ .build();
}
private static Flags parsePrefixFlags(final BitArray flags, final ProtocolId protocol) {
<groupId>${project.groupId}</groupId>
<artifactId>topology-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>topology-segment-routing</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>graph-api</artifactId>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>odl-uint24</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.mdsal.model</groupId>
<artifactId>ietf-ted</artifactId>
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.TopologyIdentifier;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.ObjectType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.SrAdjIds;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.LinkCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.NodeCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.PrefixCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.LinkstateRoutes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRoute;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.linkstate.route.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.SrPrefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.prefix.sid.tlv.Flags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.prefix.sid.tlv.flags.IsisPrefixFlagsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.SidLabelIndex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.LocalLabelCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.SidCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.topology.types.rev160524.bgp.linkstate.topology.type.BgpLinkstateTopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.SegmentId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.sr.node.attributes.Segments;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.sr.node.attributes.SegmentsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.sr.node.attributes.SegmentsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.sr.node.attributes.segments.segment.specification.AdjacencyCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.sr.node.attributes.segments.segment.specification.PrefixCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.sr.node.attributes.segments.segment.specification.adjacency._case.AdjacencyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.topology.sr.type.TopologySrBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.DestinationBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
import org.slf4j.LoggerFactory;
public class LinkstateTopologyBuilder extends AbstractTopologyBuilder<LinkstateRoute> {
- private static final TopologyTypes LINKSTATE_TOPOLOGY_TYPE = new TopologyTypesBuilder()
+ @VisibleForTesting
+ static final TopologyTypes LINKSTATE_TOPOLOGY_TYPE = new TopologyTypesBuilder()
.addAugmentation(TopologyTypes1.class, new TopologyTypes1Builder()
.setBgpLinkstateTopology(new BgpLinkstateTopologyBuilder().build()).build()).build();
+ @VisibleForTesting
+ static final TopologyTypes SR_AWARE_LINKSTATE_TOPOLOGY_TYPE = new TopologyTypesBuilder(LINKSTATE_TOPOLOGY_TYPE)
+ .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819
+ .TopologyTypes1.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819
+ .TopologyTypes1Builder().setTopologySr(new TopologySrBuilder().build()).build())
+ .build();
private static final String UNHANDLED_OBJECT_CLASS = "Unhandled object class {}";
removed = this.local.remove(id);
}
if (!removed) {
- LOG.warn("Removed non-reference link {} from TP {} isRemote {}", this.tp.getTpId(), id, isRemote);
+ LOG.warn("Removed non-reference link {} from TP {} isRemote {}", this.tp.getTpId().getValue(),
+ id.getValue(), isRemote);
}
return this.local.isEmpty() && this.remote.isEmpty();
private boolean advertized = false;
private IgpNodeAttributesBuilder inab;
private NodeBuilder nb;
+ private NodeSrHolder sr;
NodeHolder(final NodeId id) {
this.inab = new IgpNodeAttributesBuilder();
if (!this.advertized) {
if (this.tps.isEmpty() && this.prefixes.isEmpty()) {
- LOG.trace("Removing unadvertized unused node {}", this.nb.getNodeId());
+ LOG.trace("Removing unadvertized unused node {}", this.nb.getNodeId().getValue());
return true;
}
- LOG.trace("Node {} is still implied by {} TPs and {} prefixes", this.nb.getNodeId(), this.tps.size(),
- this.prefixes.size());
+ LOG.trace("Node {} is still implied by {} TPs and {} prefixes", this.nb.getNodeId().getValue(),
+ this.tps.size(), this.prefixes.size());
}
// Re-generate termination points
this.inab.setPrefix(Lists.newArrayList(this.prefixes.values()));
// Write the node out
- final Node n = this.nb.addAugmentation(Node1.class, new Node1Builder()
- .setIgpNodeAttributes(this.inab.build()).build()).build();
+ if (this.sr != null && this.sr.getSegmentCount() > 0) {
+ this.nb.addAugmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819
+ .Node1Builder().setSegments(this.sr.getSegments()).build());
+ }
+ final Node n = this.nb
+ .addAugmentation(Node1.class, new Node1Builder().setIgpNodeAttributes(this.inab.build()).build())
+ .build();
trans.put(LogicalDatastoreType.OPERATIONAL, nid, n);
LOG.trace("Created node {} at {}", n, nid);
return false;
if (!this.advertized) {
if (this.tps.isEmpty() && this.prefixes.isEmpty()) {
trans.delete(LogicalDatastoreType.OPERATIONAL, nid);
- LOG.trace("Removing unadvertized unused node {}", this.nb.getNodeId());
+ LOG.trace("Removing unadvertized unused node {}", this.nb.getNodeId().getValue());
return true;
}
- LOG.trace("Node {} is still implied by {} TPs and {} prefixes", this.nb.getNodeId(),
+ LOG.trace("Node {} is still implied by {} TPs and {} prefixes", this.nb.getNodeId().getValue(),
this.tps.size(), this.prefixes.size());
}
return false;
if (h != null) {
if (h.removeLink(link, isRemote)) {
this.tps.remove(tp);
- LOG.trace("Removed TP {}", tp);
+ LOG.trace("Removed TP {}", tp.getValue());
}
} else {
- LOG.warn("Removed non-present TP {} by link {}", tp, link);
+ LOG.warn("Removed non-present TP {} by link {}", tp.getValue(), link.getValue());
}
}
this.inab = new IgpNodeAttributesBuilder();
this.nb = new NodeBuilder().withKey(this.nb.key()).setNodeId(this.nb.getNodeId());
this.advertized = false;
- LOG.debug("Node {} is unadvertized", this.nb.getNodeId());
+ LOG.debug("Node {} is unadvertized", this.nb.getNodeId().getValue());
}
void advertized(final NodeBuilder nodeBuilder, final IgpNodeAttributesBuilder igpNodeAttBuilder) {
this.nb = requireNonNull(nodeBuilder);
this.inab = requireNonNull(igpNodeAttBuilder);
this.advertized = true;
- LOG.debug("Node {} is advertized", nodeBuilder.getNodeId());
+ LOG.debug("Node {} is advertized", nodeBuilder.getNodeId().getValue());
}
NodeId getNodeId() {
return this.nb.getNodeId();
}
+
+ NodeSrHolder getSrHolder() {
+ return this.sr;
+ }
+
+ NodeSrHolder createSrHolderIfRequired() {
+ if (this.sr == null) {
+ this.sr = new NodeSrHolder(this.nb.getNodeId());
+ }
+ return this.sr;
+ }
+ }
+
+ private final class NodeSrHolder {
+ private NodeId nodeId;
+ private Long srgbFirstValue = null;
+ private Integer srgbRangeSize = null;
+ private List<Segments> segments = new ArrayList<>();
+ private Map<IpPrefix, SrPrefix> srPrefixes = new HashMap<>();
+ private Map<IpPrefix, Segments> prefixSegments = new HashMap<>();
+ private Map<LinkId, Segments> adjSegments = new HashMap<>();
+
+ NodeSrHolder(final NodeId nodeId) {
+ this.nodeId = nodeId;
+ }
+
+ void addSrgb(final WriteTransaction trans, final boolean updateNode, final Long srgbFirstVal,
+ final Integer srgbRangeSz) {
+ this.srgbFirstValue = srgbFirstVal;
+ this.srgbRangeSize = srgbRangeSz;
+ this.srPrefixes.entrySet().forEach(entry -> {
+ final IpPrefix ippfx = entry.getKey();
+ final SrPrefix srPrefix = entry.getValue();
+ final SidLabelIndex sidLabelIndex = srPrefix.getSidLabelIndex();
+ if (sidLabelIndex instanceof SidCase) {
+ final Long sidIndex = ((SidCase) sidLabelIndex).getSid().longValue();
+ if (sidIndex >= this.srgbRangeSize) {
+ LOG.warn("Prefix SID index {} is outside the SRGB range of {} for node {}", sidIndex,
+ this.srgbRangeSize, this.nodeId.getValue());
+ return;
+ }
+ final Long prefixSid = this.srgbFirstValue + sidIndex;
+ final boolean isNodeSid = isAssociatedWithNodeSid(ippfx, srPrefix);
+ addPrefixSid(trans, updateNode, ippfx, prefixSid, isNodeSid);
+ }
+ });
+ }
+
+ void removeSrgb(final WriteTransaction trans) {
+ this.srgbFirstValue = null;
+ this.srgbRangeSize = null;
+ this.srPrefixes.entrySet().forEach(entry -> {
+ final IpPrefix ippfx = entry.getKey();
+ final SrPrefix srPrefix = entry.getValue();
+ final SidLabelIndex sidLabelIndex = srPrefix.getSidLabelIndex();
+ if (sidLabelIndex instanceof SidCase) {
+ removePrefixSid(trans, false, ippfx);
+ }
+ });
+ }
+
+ void addSrPrefix(final WriteTransaction trans, final boolean updateNode, final IpPrefix ippfx,
+ final SrPrefix srPrefix) {
+ this.srPrefixes.put(ippfx, srPrefix);
+ final SidLabelIndex sidLabelIndex = srPrefix.getSidLabelIndex();
+ Long prefixSid = null;
+ if (sidLabelIndex instanceof LocalLabelCase) {
+ prefixSid = ((LocalLabelCase) sidLabelIndex).getLocalLabel().getValue().longValue();
+ } else if (sidLabelIndex instanceof SidCase) {
+ if (this.srgbFirstValue != null && this.srgbRangeSize != null) {
+ final Long sidIndex = ((SidCase) sidLabelIndex).getSid().longValue();
+ if (sidIndex >= this.srgbRangeSize) {
+ LOG.warn("Prefix SID index {} is outside the SRGB range of {} for node {}", sidIndex,
+ this.srgbRangeSize, this.nodeId.getValue());
+ return;
+ }
+ prefixSid = this.srgbFirstValue + sidIndex;
+ }
+ }
+ if (prefixSid != null) {
+ final boolean isNodeSid = isAssociatedWithNodeSid(ippfx, srPrefix);
+ addPrefixSid(trans, updateNode, ippfx, prefixSid, isNodeSid);
+ }
+ }
+
+ void removeSrPrefix(final WriteTransaction trans, final IpPrefix ippfx) {
+ if (!this.srPrefixes.containsKey(ippfx)) {
+ return;
+ }
+ removePrefixSid(trans, true, ippfx);
+ this.srPrefixes.remove(ippfx);
+ }
+
+ void addPrefixSid(final WriteTransaction trans, final boolean updateNode, final IpPrefix ippfx,
+ final Long prefixSid, final boolean isNodeSid) {
+ LOG.trace("Adding prefix SID {} for prefix {} on node {}", prefixSid, ippfx.stringValue(),
+ this.nodeId.getValue());
+ final SegmentId segmentId = new SegmentId(Uint32.valueOf(prefixSid));
+ final Segments prefixSegment = new SegmentsBuilder()
+ .setSegmentId(segmentId)
+ .withKey(new SegmentsKey(segmentId))
+ .setSegmentSpecification(new PrefixCaseBuilder()
+ .setPrefix(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr
+ .rev130819.sr.node.attributes.segments.segment.specification.prefix._case.PrefixBuilder()
+ .setPrefix(ippfx).setNodeSid(isNodeSid ? isNodeSid : null).build())
+ .build())
+ .build();
+ this.prefixSegments.put(ippfx, prefixSegment);
+ this.segments.add(prefixSegment);
+ addSegment(trans, updateNode, prefixSegment);
+ }
+
+ void removePrefixSid(final WriteTransaction trans, final boolean updateNode, final IpPrefix ippfx) {
+ if (!this.prefixSegments.containsKey(ippfx)) {
+ return;
+ }
+ LOG.trace("Removing prefix SID for prefix {} on node {}", ippfx.stringValue(),
+ this.nodeId.getValue());
+ final Segments prefixSegment = this.prefixSegments.remove(ippfx);
+ this.segments.remove(prefixSegment);
+ removeSegment(trans, updateNode, prefixSegment);
+ }
+
+ void addAdjacencySid(final WriteTransaction trans, final boolean updateNode, final LinkId linkId,
+ final Long adjSid) {
+ LOG.trace("Adding adjacency SID {} for link {} on node {}", adjSid, linkId.getValue(),
+ this.nodeId.getValue());
+ final SegmentId segmentId = new SegmentId(Uint32.valueOf(adjSid));
+ final SegmentsBuilder sb = new SegmentsBuilder();
+ sb.setSegmentId(segmentId);
+ sb.withKey(new SegmentsKey(segmentId));
+ sb.setSegmentSpecification(new AdjacencyCaseBuilder()
+ .setAdjacency(new AdjacencyBuilder().setAdjacency(linkId).build()).build());
+ final Segments adjSegment = sb.build();
+ this.adjSegments.put(linkId, adjSegment);
+ this.segments.add(adjSegment);
+ addSegment(trans, updateNode, adjSegment);
+ }
+
+ void removeAdjacencySid(final WriteTransaction trans, final LinkId linkId) {
+ if (!this.adjSegments.containsKey(linkId)) {
+ return;
+ }
+ LOG.trace("Removing adjacency SID for link {} on node {}", linkId.getValue(),
+ this.nodeId.getValue());
+ final Segments adjSegment = this.adjSegments.remove(linkId);
+ this.segments.remove(adjSegment);
+ removeSegment(trans, true, adjSegment);
+ }
+
+ void addSegment(final WriteTransaction trans, final boolean updateNode, final Segments segment) {
+ if (updateNode) {
+ final InstanceIdentifier<Node> nodeIId = getNodeInstanceIdentifier(new NodeKey(this.nodeId));
+ final InstanceIdentifier<Segments> segmentIId = nodeIId.builder()
+ .augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr
+ .rev130819.Node1.class)
+ .child(Segments.class, segment.key()).build();
+ trans.put(LogicalDatastoreType.OPERATIONAL, segmentIId, segment);
+ }
+ addSrAwareTopologyType(trans);
+ }
+
+ void removeSegment(final WriteTransaction trans, final boolean updateNode, final Segments segment) {
+ if (updateNode) {
+ final InstanceIdentifier<Node> nodeIId = getNodeInstanceIdentifier(new NodeKey(this.nodeId));
+ final InstanceIdentifier<Segments> segmentIId = nodeIId.builder()
+ .augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr
+ .rev130819.Node1.class)
+ .child(Segments.class, segment.key()).build();
+ trans.delete(LogicalDatastoreType.OPERATIONAL, segmentIId);
+ }
+ removeSrAwareTopologyTypeIfRequired(trans);
+ }
+
+ boolean isAssociatedWithNodeSid(final IpPrefix ippfx, final SrPrefix srPrefix) {
+ if (ippfx.getIpv4Prefix() != null && !ippfx.stringValue().endsWith("/32")
+ || ippfx.getIpv6Prefix() != null && !ippfx.stringValue().endsWith("/128")) {
+ return false;
+ }
+ final Flags prefixFlags = srPrefix.getFlags();
+ if (prefixFlags instanceof IsisPrefixFlagsCase) {
+ return !Boolean.FALSE.equals(((IsisPrefixFlagsCase) prefixFlags).getIsisPrefixFlags().isNodeSid());
+ }
+ return true;
+ }
+
+ List<Segments> getSegments() {
+ return this.segments;
+ }
+
+ int getSegmentCount() {
+ return this.segments.size();
+ }
}
private static final Logger LOG = LoggerFactory.getLogger(LinkstateTopologyBuilder.class);
private final Map<NodeId, NodeHolder> nodes = new HashMap<>();
+ private boolean srAwareTopologyTypeAdded;
public LinkstateTopologyBuilder(final DataBroker dataProvider, final RibReference locRibReference,
final TopologyId topologyId) {
}
final IgpLinkAttributesBuilder ilab = new IgpLinkAttributesBuilder();
+ Long adjSid = null;
if (la != null) {
if (la.getMetric() != null) {
ilab.setMetric(la.getMetric().getValue());
}
ilab.setName(la.getLinkName());
+ if (la.getSrAdjIds() != null && !la.getSrAdjIds().isEmpty()) {
+ final SrAdjIds srAdjIds = la.getSrAdjIds().get(0);
+ if (srAdjIds != null) {
+ final SidLabelIndex sidLabelIndex = srAdjIds.getSidLabelIndex();
+ if (sidLabelIndex instanceof LocalLabelCase) {
+ adjSid = ((LocalLabelCase) sidLabelIndex).getLocalLabel().getValue().longValue();
+ }
+ }
+ }
}
ProtocolUtil.augmentProtocolId(value, ilab, la, linkCase.getLinkDescriptors());
if (snh == null) {
snh = getNode(srcNode);
snh.addTp(srcTp, lb.getLinkId(), false);
+ if (adjSid != null) {
+ snh.createSrHolderIfRequired().addAdjacencySid(trans, false, lb.getLinkId(), adjSid);
+ }
putNode(trans, snh);
} else {
snh.addTp(srcTp, lb.getLinkId(), false);
+ if (adjSid != null) {
+ snh.createSrHolderIfRequired().addAdjacencySid(trans, true, lb.getLinkId(), adjSid);
+ }
final InstanceIdentifier<Node> nid = getNodeInstanceIdentifier(new NodeKey(snh.getNodeId()));
trans.put(LogicalDatastoreType.OPERATIONAL, nid.child(TerminationPoint.class, srcTp.key()), srcTp);
}
+ if (adjSid != null) {
+ lb.addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819
+ .Link1.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819
+ .Link1Builder().setSegment(new SegmentId(Uint32.valueOf(adjSid))).build());
+ }
LOG.debug("Created TP {} as link destination", dstTp);
NodeHolder dnh = this.nodes.get(dstNode);
trans.delete(LogicalDatastoreType.OPERATIONAL, nid.child(TerminationPoint.class,
new TerminationPointKey(tp)));
nh.removeTp(tp, link, isRemote);
+ if (!isRemote) {
+ nh.createSrHolderIfRequired().removeAdjacencySid(trans, link);
+ }
checkNodeForRemoval(trans, nh);
} else {
- LOG.warn("Removed non-existent node {}", node);
+ LOG.warn("Removed non-existent node {}", node.getValue());
}
}
}
final IgpNodeAttributesBuilder inab = new IgpNodeAttributesBuilder();
final List<IpAddress> ids = new ArrayList<>();
+ Long srgbFirstValue = null;
+ Integer srgbRangeSize = null;
if (na != null) {
if (na.getIpv4RouterId() != null) {
ids.add(new IpAddress(na.getIpv4RouterId()));
if (na.getDynamicHostname() != null) {
inab.setName(new DomainName(na.getDynamicHostname()));
}
+ if (na.getSrCapabilities() != null) {
+ final SidLabelIndex sidLabelIndex = na.getSrCapabilities().getSidLabelIndex();
+ if (sidLabelIndex instanceof LocalLabelCase) {
+ srgbFirstValue = ((LocalLabelCase) sidLabelIndex).getLocalLabel().getValue().longValue();
+ }
+ srgbRangeSize = na.getSrCapabilities().getRangeSize() != null
+ ? na.getSrCapabilities().getRangeSize().getValue().intValue()
+ : null;
+ }
}
if (!ids.isEmpty()) {
inab.setRouterId(ids);
nb.withKey(new NodeKey(nb.getNodeId()));
nh.advertized(nb, inab);
+ if (srgbFirstValue != null && srgbRangeSize != null) {
+ nh.createSrHolderIfRequired().addSrgb(trans, false, srgbFirstValue, srgbRangeSize);
+ }
putNode(trans, nh);
}
final NodeHolder nh = this.nodes.get(id);
if (nh != null) {
nh.unadvertized();
+ nh.createSrHolderIfRequired().removeSrgb(trans);
putNode(trans, nh);
} else {
- LOG.warn("Node {} does not have a holder", id);
+ LOG.warn("Node {} does not have a holder", id.getValue());
}
}
LOG.debug("Missing attributes in IP {} prefix {} route {}, skipping it", ippfx, prefixCase, value);
pa = null;
}
- if (pa != null && pa.getPrefixMetric() != null) {
- pb.setMetric(pa.getPrefixMetric().getValue());
+ SrPrefix srPrefix = null;
+ if (pa != null) {
+ if (pa.getPrefixMetric() != null) {
+ pb.setMetric(pa.getPrefixMetric().getValue());
+ }
+ if (pa.getSrPrefix() != null) {
+ srPrefix = pa.getSrPrefix();
+ }
}
ProtocolUtil.augmentProtocolId(value, pa, pb);
if (nh == null) {
nh = getNode(node);
nh.addPrefix(pfx);
+ if (srPrefix != null) {
+ nh.createSrHolderIfRequired().addSrPrefix(trans, false, ippfx, srPrefix);
+ }
putNode(trans, nh);
} else {
nh.addPrefix(pfx);
+ if (srPrefix != null) {
+ nh.createSrHolderIfRequired().addSrPrefix(trans, true, ippfx, srPrefix);
+ }
final InstanceIdentifier<Node> nid = getNodeInstanceIdentifier(new NodeKey(nh.getNodeId()));
final InstanceIdentifier<IgpNodeAttributes> inaId = nid.builder().augmentation(Node1.class)
.child(IgpNodeAttributes.class).build();
final PrefixKey pk = new PrefixKey(ippfx);
trans.delete(LogicalDatastoreType.OPERATIONAL, inaId.child(Prefix.class, pk));
nh.removePrefix(prefixCase);
+ nh.createSrHolderIfRequired().removeSrPrefix(trans, ippfx);
checkNodeForRemoval(trans, nh);
} else {
- LOG.warn("Removing prefix from non-existing node {}", node);
+ LOG.warn("Removing prefix from non-existing node {}", node.getValue());
}
}
.topology.topology.Node.class, nodeKey);
}
+ protected void addSrAwareTopologyType(final WriteTransaction trans) {
+ if (this.srAwareTopologyTypeAdded) {
+ return;
+ }
+ LOG.debug("Adding SR-aware topology-type for topology {}",
+ getInstanceIdentifier().firstKeyOf(Topology.class).getTopologyId().getValue());
+ trans.put(LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier().child(TopologyTypes.class),
+ SR_AWARE_LINKSTATE_TOPOLOGY_TYPE);
+ this.srAwareTopologyTypeAdded = true;
+ }
+
+ protected void removeSrAwareTopologyTypeIfRequired(final WriteTransaction trans) {
+ if (!this.srAwareTopologyTypeAdded) {
+ return;
+ }
+ final boolean isSidPresent = this.nodes.values().stream().filter(nh -> nh.getSrHolder() != null)
+ .map(nh -> nh.getSrHolder().getSegmentCount()).anyMatch(cnt -> cnt != 0);
+ if (isSidPresent) {
+ return;
+ }
+ LOG.debug("Removing SR-aware topology-type from topology {}",
+ getInstanceIdentifier().firstKeyOf(Topology.class).getTopologyId().getValue());
+ trans.put(LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier().child(TopologyTypes.class),
+ LINKSTATE_TOPOLOGY_TYPE);
+ this.srAwareTopologyTypeAdded = false;
+ }
+
@Override
protected void createObject(final ReadWriteTransaction trans,
final InstanceIdentifier<LinkstateRoute> id, final LinkstateRoute value) {
@Override
protected void clearTopology() {
this.nodes.clear();
+ this.srAwareTopologyTypeAdded = false;
}
}
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ProtocolId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.TopologyIdentifier;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.SrAdjIdsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LinkDescriptorsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.linkstate.route.Attributes1Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.IsisNodeCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.isis.node._case.IsisNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.state.SrCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.SrPrefixBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.OriginBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.LocRib;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.LocalLabelCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.SidCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpOrigin;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.SrlgId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.uint24.rev200104.Uint24;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpLinkAttributes1;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpNodeAttributes1;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
public class LinkstateTopologyBuilderTest extends AbstractTopologyBuilderTest {
- private static final String LINKSTATE_ROUTE_KEY = Unpooled.wrappedBuffer(
- StandardCharsets.UTF_8.encode("linkstate-route")).array().toString();
private static final String ROUTER_1_ID = "127.0.0.1";
private static final String ROUTER_2_ID = "127.0.0.2";
private static final String NODE_1_PREFIX = "127.0.1.1/32";
private static final Identifier IDENTIFIER = new Identifier(Uint64.ONE);
private static final long LISTENER_RESTART_TIME = 20000;
private static final int LISTENER_ENFORCE_COUNTER = 2;
+ private static final int SRGB_START = 90000;
+ private static final int SRGB_RANGE = 16;
+ private static final int NODE_SID_INDEX = 4;
+ private static final int ADJ_SID = 24001;
private LinkstateTopologyBuilder linkstateTopoBuilder;
- private InstanceIdentifier<LinkstateRoute> linkstateRouteIID;
+ private InstanceIdentifier<Tables> tablePathIID;
+ private String linkstateNodeRouteKey;
+ private String linkstatePrefixRouteKey;
+ private String linkstateLinkRouteKey;
+ private InstanceIdentifier<LinkstateRoute> linkstateNodeRouteIID;
+ private InstanceIdentifier<LinkstateRoute> linkstatePrefixRouteIID;
+ private InstanceIdentifier<LinkstateRoute> linkstateLinkRouteIID;
@Before
@Override
this.linkstateTopoBuilder = new LinkstateTopologyBuilder(getDataBroker(), LOC_RIB_REF, TEST_TOPOLOGY_ID,
LISTENER_RESTART_TIME, LISTENER_ENFORCE_COUNTER);
this.linkstateTopoBuilder.start();
- final InstanceIdentifier<Tables> path = LOC_RIB_REF.getInstanceIdentifier().builder().child(LocRib.class)
- .child(Tables.class, new TablesKey(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class))
- .build();
- this.linkstateRouteIID = path.builder().child(LinkstateRoutesCase.class, LinkstateRoutes.class)
- .child(LinkstateRoute.class, new LinkstateRouteKey(new PathId(Uint32.ZERO), LINKSTATE_ROUTE_KEY))
- .build();
-
+ this.tablePathIID =
+ LOC_RIB_REF.getInstanceIdentifier().builder().child(LocRib.class)
+ .child(Tables.class,
+ new TablesKey(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class))
+ .build();
+ this.linkstateNodeRouteKey = getLinkstateRouteKey("node-route");
+ this.linkstatePrefixRouteKey = getLinkstateRouteKey("prefix-route");
+ this.linkstateLinkRouteKey = getLinkstateRouteKey("link-route");
+ this.linkstateNodeRouteIID = createLinkstateRouteIID(this.linkstateNodeRouteKey);
+ this.linkstatePrefixRouteIID = createLinkstateRouteIID(this.linkstatePrefixRouteKey);
+ this.linkstateLinkRouteIID = createLinkstateRouteIID(this.linkstateLinkRouteKey);
}
@After
@Test
public void testLinkstateTopologyBuilderTopologyTypes() throws InterruptedException, ExecutionException {
readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
- assertNotNull(topology.getTopologyTypes().augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight
- .params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1.class));
- assertNotNull(topology.getTopologyTypes().augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight
- .params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1.class)
- .getBgpLinkstateTopology());
+ assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
return topology;
});
}
@Test
+ @SuppressWarnings("checkstyle:LineLength")
public void testIsisLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
// create node
- updateLinkstateRoute(createLinkstateNodeRoute(ProtocolId.IsisLevel2, "node1", NODE_1_AS, ROUTER_1_ID));
+ updateLinkstateRoute(this.linkstateNodeRouteIID,
+ createLinkstateNodeRoute(ProtocolId.IsisLevel2, "node1", NODE_1_AS, ROUTER_1_ID));
readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
assertEquals(1, topology.getNode().size());
final Node node1 = topology.getNode().get(0);
.getNet().get(0).getValue());
assertNull(igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
.topology.rev131021.IgpNodeAttributes1.class));
+ assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
+ assertNull(node1.augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class));
return topology;
});
-
// create link
- updateLinkstateRoute(createLinkstateLinkRoute(ProtocolId.IsisLevel2, NODE_1_AS, NODE_2_AS, "link1"));
+ updateLinkstateRoute(this.linkstateLinkRouteIID,
+ createLinkstateLinkRoute(ProtocolId.IsisLevel2, NODE_1_AS, NODE_2_AS, "link1"));
readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
assertEquals(1, topology.getLink().size());
final Link link1 = topology.getLink().get(0);
.getMultiTopologyId().shortValue());
assertNull(igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
.topology.rev131021.IgpLinkAttributes1.class));
+ assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
+ assertEquals(2, topology.getNode().size());
+ final Node srcNode;
+ if (topology.getNode().get(0).getNodeId().getValue().contains("0000.0102.0304")) {
+ srcNode = topology.getNode().get(0);
+ } else {
+ srcNode = topology.getNode().get(1);
+ }
+ assertEquals(1, srcNode.augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
+ .getSegments().size());
+ assertEquals(ADJ_SID, link1.augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Link1.class)
+ .getSegment().getValue().intValue());
return topology;
});
-
+ removeLinkstateRoute(this.linkstateLinkRouteIID);
// update node
- updateLinkstateRoute(createLinkstateNodeRoute(ProtocolId.IsisLevel2, "updated-node",
- NODE_1_AS, ROUTER_2_ID));
+ updateLinkstateRoute(this.linkstateNodeRouteIID,
+ createLinkstateNodeRoute(ProtocolId.IsisLevel2, "updated-node", NODE_1_AS, ROUTER_2_ID));
readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
assertEquals(1, topology.getNode().size());
final IgpNodeAttributes igpNode2 = topology.getNode().get(0).augmentation(Node1.class)
});
// remove
- final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
- wTx.delete(LogicalDatastoreType.OPERATIONAL, this.linkstateRouteIID);
- wTx.commit();
+ removeLinkstateRoute(this.linkstateNodeRouteIID);
readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
+ assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
assertNull(topology.getNode());
assertNull(topology.getLink());
return topology;
}
@Test
+ @SuppressWarnings("checkstyle:LineLength")
public void testOspfLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
// create node
- updateLinkstateRoute(createLinkstateNodeRoute(ProtocolId.Ospf, "node1", NODE_1_AS, ROUTER_1_ID));
+ updateLinkstateRoute(this.linkstateNodeRouteIID,
+ createLinkstateNodeRoute(ProtocolId.Ospf, "node1", NODE_1_AS, ROUTER_1_ID));
readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
assertEquals(1, topology.getNode().size());
final Node node1 = topology.getNode().get(0);
assertEquals(ROUTER_1_ID, igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
.yang.ospf.topology.rev131021.IgpNodeAttributes1.class).getOspfNodeAttributes().getTed()
.getTeRouterIdIpv4().getValue());
+ assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
+ assertNull(node1.augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class));
return topology;
});
// update node with prefix
- updateLinkstateRoute(createLinkstatePrefixRoute(ProtocolId.Ospf, NODE_1_AS, NODE_1_PREFIX,
- 500L, ROUTER_1_ID));
+ updateLinkstateRoute(this.linkstatePrefixRouteIID,
+ createLinkstatePrefixRoute(ProtocolId.Ospf, NODE_1_AS, NODE_1_PREFIX, 500L, ROUTER_1_ID));
readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
- final IgpNodeAttributes igpNode2 = topology.getNode().get(0).augmentation(Node1.class)
- .getIgpNodeAttributes();
- assertEquals(1, igpNode2.getPrefix().size());
- final Prefix prefix = igpNode2.getPrefix().get(0);
+ final Node node1 = topology.getNode().get(0);
+ final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
+ assertEquals(1, igpNode1.getPrefix().size());
+ final Prefix prefix = igpNode1.getPrefix().get(0);
assertEquals(NODE_1_PREFIX, prefix.getPrefix().getIpv4Prefix().getValue());
assertEquals(500L, prefix.getMetric().longValue());
+ assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
+ assertEquals(1, node1.augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
+ .getSegments().size());
+ assertEquals(SRGB_START + NODE_SID_INDEX, node1.augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
+ .getSegments().get(0).getSegmentId().getValue().intValue());
return topology;
});
-
// create link
- updateLinkstateRoute(createLinkstateLinkRoute(ProtocolId.Ospf, NODE_1_AS, NODE_2_AS, "link1"));
+ updateLinkstateRoute(this.linkstateLinkRouteIID,
+ createLinkstateLinkRoute(ProtocolId.Ospf, NODE_1_AS, NODE_2_AS, "link1"));
readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
assertEquals(1, topology.getLink().size());
final Link link1 = topology.getLink().get(0);
assertEquals(2, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
.yang.ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getTed().getSrlg()
.getSrlgValues().size());
+ assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
+ assertEquals(2, topology.getNode().size());
+ final Node srcNode;
+ if (topology.getNode().get(0).getNodeId().getValue().contains("0000.0102.0304")) {
+ srcNode = topology.getNode().get(0);
+ } else {
+ srcNode = topology.getNode().get(1);
+ }
+ assertEquals(2, srcNode.augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
+ .getSegments().size());
+ assertEquals(ADJ_SID, link1.augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Link1.class)
+ .getSegment().getValue().intValue());
return topology;
});
-
-
}
/**
verify(spiedLinkstateTopologyBuilder, times(1)).resetListener();
}
- private void updateLinkstateRoute(final LinkstateRoute data) {
+ private static String getLinkstateRouteKey(final String routeKey) {
+ return Unpooled.wrappedBuffer(StandardCharsets.UTF_8.encode(routeKey)).array().toString();
+ }
+
+ private InstanceIdentifier<LinkstateRoute> createLinkstateRouteIID(final String linkstateRouteKey) {
+ return this.tablePathIID.builder().child(LinkstateRoutesCase.class, LinkstateRoutes.class)
+ .child(LinkstateRoute.class, new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey)).build();
+ }
+
+ private void updateLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID,
+ final LinkstateRoute data) {
final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
- wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, this.linkstateRouteIID, data);
+ wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID, data);
wTx.commit();
}
- private static LinkstateRoute createLinkstateNodeRoute(final ProtocolId protocolId, final String nodeName,
+ private void removeLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID) {
+ final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
+ wTx.delete(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID);
+ wTx.commit();
+ }
+
+ private LinkstateRoute createLinkstateNodeRoute(final ProtocolId protocolId, final String nodeName,
final AsNumber asNumber, final String ipv4RouterId) {
- return createBaseBuilder(protocolId)
- .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
- .bgp.linkstate.rev200120.linkstate.object.type.NodeCaseBuilder()
+ return createBaseBuilder(this.linkstateNodeRouteKey, protocolId)
+ .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
+ .rev200120.linkstate.object.type.NodeCaseBuilder()
.setNodeDescriptors(new NodeDescriptorsBuilder()
.setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
.setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
.setIpv4RouterId(new Ipv4RouterIdentifier(ipv4RouterId))
.setIsisAreaId(Collections.singletonList(
new IsisAreaIdentifier(new byte[]{0x47})))
+ .setSrCapabilities(new SrCapabilitiesBuilder()
+ .setRangeSize(new Uint24(Uint32.valueOf(SRGB_RANGE)))
+ .setSidLabelIndex(new LocalLabelCaseBuilder()
+ .setLocalLabel(
+ new MplsLabel(Uint32.valueOf(SRGB_START)))
+ .build())
+ .build())
.build()).build()).build()).build()).build();
}
- private static LinkstateRoute createLinkstatePrefixRoute(final ProtocolId protocolId, final AsNumber asNumber,
+ private LinkstateRoute createLinkstatePrefixRoute(final ProtocolId protocolId, final AsNumber asNumber,
final String ipv4Prefix, final long igpMetric, final String ospfFwdAddress) {
- return createBaseBuilder(protocolId)
+ return createBaseBuilder(this.linkstatePrefixRouteKey, protocolId)
.setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120
.linkstate.object.type.PrefixCaseBuilder()
- .setAdvertisingNodeDescriptors(new AdvertisingNodeDescriptorsBuilder().setAsNumber(asNumber).build())
+ .setAdvertisingNodeDescriptors(new AdvertisingNodeDescriptorsBuilder()
+ .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
+ .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
+ .build()).setAsNumber(asNumber).build())
.setPrefixDescriptors(new PrefixDescriptorsBuilder()
.setIpReachabilityInformation(new IpPrefix(new Ipv4Prefix(ipv4Prefix))).build()).build())
.setAttributes(new AttributesBuilder()
.setPrefixAttributes(new PrefixAttributesBuilder()
.setOspfForwardingAddress(new IpAddressNoZone(new Ipv4AddressNoZone(ospfFwdAddress)))
.setPrefixMetric(new IgpMetric(Uint32.valueOf(igpMetric)))
+ .setSrPrefix(new SrPrefixBuilder()
+ .setAlgorithm(Algorithm.ShortestPathFirst)
+ .setSidLabelIndex(new SidCaseBuilder()
+ .setSid(Uint32.valueOf(NODE_SID_INDEX)).build())
+ .build())
.build())
.build())
.build())
.build();
}
- private static LinkstateRoute createLinkstateLinkRoute(final ProtocolId protocolId, final AsNumber localAs,
+ private LinkstateRoute createLinkstateLinkRoute(final ProtocolId protocolId, final AsNumber localAs,
final AsNumber remoteAs, final String linkName) {
- return createBaseBuilder(protocolId)
- .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
- .bgp.linkstate.rev200120.linkstate.object.type.LinkCaseBuilder()
+ return createBaseBuilder(this.linkstateLinkRouteKey, protocolId)
+ .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
+ .rev200120.linkstate.object.type.LinkCaseBuilder()
.setLocalNodeDescriptors(new LocalNodeDescriptorsBuilder().setAsNumber(localAs)
.setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
.setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4}))
.build()))
.setTeMetric(new TeMetric(Uint32.valueOf(100)))
.setLinkName(linkName)
+ .setSrAdjIds(Collections.singletonList(new SrAdjIdsBuilder()
+ .setSidLabelIndex(new LocalLabelCaseBuilder()
+ .setLocalLabel(new MplsLabel(Uint32.valueOf(ADJ_SID)))
+ .build())
+ .build()))
.build())
.build())
.build())
.build();
}
- private static LinkstateRouteBuilder createBaseBuilder(final ProtocolId protocolId) {
+ private static LinkstateRouteBuilder createBaseBuilder(final String linkstateRouteKey,
+ final ProtocolId protocolId) {
return new LinkstateRouteBuilder()
.setIdentifier(IDENTIFIER)
- .withKey(new LinkstateRouteKey(new PathId(Uint32.ZERO), LINKSTATE_ROUTE_KEY))
- .setRouteKey(LINKSTATE_ROUTE_KEY)
+ .withKey(new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey))
+ .setRouteKey(linkstateRouteKey)
.setProtocolId(protocolId);
}
}
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>concepts</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991-ietf-inet-types</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.mdsal.model</groupId>
<artifactId>ietf-topology</artifactId>
namespace "urn:opendaylight:params:xml:ns:yang:topology:sr";
prefix "sr";
+ import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
import network-topology { prefix nt; revision-date 2013-10-21; }
organization "Cisco Systems, Inc.";
}
}
}
- case node-case {
- container node {
- leaf node {
- type nt:node-ref;
+ case prefix-case {
+ container prefix {
+ leaf prefix {
+ type inet:ip-prefix;
mandatory true;
}
+ leaf node-sid {
+ type boolean;
+ default false;
+ }
}
}
}