This is the initial code drop, as passed through ICR on 07/10/2013.
Change-Id: Ia729cfc590629174fcd03a1a55dc667982f34d18
Signed-off-by: Robert Varga <rovarga@cisco.com>
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>bgp-subsystem</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.m2e.core.maven2Builder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-concepts</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-concepts</artifactId>
+ <description>Basic BGP concepts</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.concepts
+ </Export-Package>
+ <Import-Package>
+ com.google.common.base,
+ org.opendaylight.protocol.concepts,
+ com.google.guava,
+ org.opendaylight.protocol.util
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.version}</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-CONCEPTS Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Conceptual representation of an AS path. This class distills the concept behind the encoding rules specified in RFC
+ * 4271.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-5.1.2">AS Path</a>
+ */
+public final class ASPath implements Serializable {
+ /**
+ * An empty AS Path (attribute in all UPDATE messages sent to internal peers).
+ */
+ public static final ASPath EMPTY = new ASPath();
+ private static final long serialVersionUID = 7951172606939897308L;
+ private final Set<ASNumber> aggregatedAsPath;
+ private final List<ASNumber> visibleAsPath;
+
+ private ASPath() {
+ this.visibleAsPath = Collections.emptyList();
+ this.aggregatedAsPath = Collections.emptySet();
+ }
+
+ /**
+ * Construct an AS path object representing a fully-visible path.
+ *
+ * @param visibleAsPath Ordered list of AS numbers in the path, corresponding to the concatenation of all
+ * AS_SEQUENCE components.
+ */
+ public ASPath(final List<ASNumber> visibleAsPath) {
+ this.aggregatedAsPath = Collections.emptySet();
+ this.visibleAsPath = Collections.unmodifiableList(Preconditions.checkNotNull(visibleAsPath));
+ }
+
+ /**
+ * Construct an AS path object representing a partially aggregated path.
+ *
+ * @param visibleAsPath Ordered list of AS numbers in the path, corresponding to the concatenation of all
+ * AS_SEQUENCE components.
+ * @param aggregatedAsPath Unordered set of AS numbers in the path, corresponding to the concatenation of all AS_SET
+ * components.
+ */
+ public ASPath(final List<ASNumber> visibleAsPath, final Set<ASNumber> aggregatedAsPath) {
+ Preconditions.checkNotNull(aggregatedAsPath);
+ Preconditions.checkNotNull(visibleAsPath);
+ this.aggregatedAsPath = Collections.unmodifiableSet(aggregatedAsPath);
+ this.visibleAsPath = Collections.unmodifiableList(visibleAsPath);
+ }
+
+ /**
+ * Return the visible part of an AS path. Note that an AS number may be present multiple times in a row due to
+ * "AS number prepend" feature used by many routers to affect route decisions by extending the length on the list
+ * while keeping the loop information intact.
+ *
+ * @return Ordered list of AS numbers.
+ */
+ public List<ASNumber> getVisibleAsPath() {
+ return this.visibleAsPath;
+ }
+
+ /**
+ * Return the aggregated part of an AS path.
+ *
+ * @return Unordered set of AS numbers.
+ */
+ public Set<ASNumber> getAggregatedAsPath() {
+ return this.aggregatedAsPath;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.aggregatedAsPath == null) ? 0 : this.aggregatedAsPath.hashCode());
+ result = prime * result + ((this.visibleAsPath == null) ? 0 : this.visibleAsPath.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final ASPath other = (ASPath) obj;
+ if (this.aggregatedAsPath == null) {
+ if (other.aggregatedAsPath != null)
+ return false;
+ } else if (!this.aggregatedAsPath.equals(other.aggregatedAsPath))
+ return false;
+ if (this.visibleAsPath == null) {
+ if (other.visibleAsPath != null)
+ return false;
+ } else if (!this.visibleAsPath.equals(other.visibleAsPath))
+ return false;
+ return true;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("aggregatedAsPath", this.aggregatedAsPath);
+ toStringHelper.add("visibleAsPath", this.visibleAsPath);
+ return toStringHelper;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing an <a href="http://tools.ietf.org/html/rfc4360#section-3.1">Two-Octet AS Specific Extended
+ * Community</a>.
+ */
+public class ASSpecificExtendedCommunity extends ExtendedCommunity implements Serializable {
+ private static final long serialVersionUID = 6490173838144366385L;
+ private final ASNumber globalAdmin;
+ private final byte[] localAdmin;
+ private final int subType;
+
+ /**
+ * Construct a new Two-Octet AS Specific Extended Community.
+ *
+ * @param transitive True if this community is transitive
+ * @param subType Community subtype, has to be in range 0-255
+ * @param globalAdmin Globally-assigned namespace (AS number)
+ * @param localAdmin Locally-assigned value, has to be 4 bytes long
+ */
+ public ASSpecificExtendedCommunity(final boolean transitive, final int subType, final ASNumber globalAdmin, final byte[] localAdmin) {
+ super(false, transitive);
+ Preconditions.checkArgument(subType > 0 && subType < 255, "Invalid Sub-Type");
+ Preconditions.checkArgument(localAdmin.length == 4, "Invalid Local Administrator");
+ this.subType = subType;
+ this.globalAdmin = Preconditions.checkNotNull(globalAdmin);
+ this.localAdmin = localAdmin;
+ }
+
+ /**
+ * @return Community subtype
+ */
+ public final int getSubType() {
+ return this.subType;
+ }
+
+ /**
+ * @return Globally-assigned namespace
+ */
+ public final ASNumber getGlobalAdmin() {
+ return this.globalAdmin;
+ }
+
+ /**
+ * @return Locally-assigned value
+ */
+ public final byte[] getLocalAdmin() {
+ return this.localAdmin;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("subType", this.subType);
+ toStringHelper.add("globalAdmin", this.globalAdmin);
+ toStringHelper.add("localAdmin", this.localAdmin);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Abstract implementation of a NextHop class. This is a useful base class
+ * implementing all the required semantics for a NextHop. Subclasses only
+ * need to supply an appropriate public constructor.
+ *
+ * @param <T> template reference to subclass
+ */
+public abstract class AbstractNextHop<T extends NetworkAddress<T>> implements NextHop<T> {
+ private static final long serialVersionUID = 2462286640242941943L;
+ private final T global;
+ private final T linkLocal;
+
+ protected AbstractNextHop(final T global, final T linkLocal) {
+ this.global = Preconditions.checkNotNull(global);
+ this.linkLocal = linkLocal;
+ }
+
+ @Override
+ public T getGlobal() {
+ return global;
+ }
+
+ @Override
+ public T getLinkLocal() {
+ return linkLocal;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((global == null) ? 0 : global.hashCode());
+ result = prime * result
+ + ((linkLocal == null) ? 0 : linkLocal.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final AbstractNextHop<?> other = (AbstractNextHop<?>) obj;
+ if (global == null) {
+ if (other.global != null)
+ return false;
+ } else if (!global.equals(other.global))
+ return false;
+ if (linkLocal == null) {
+ if (other.linkLocal != null)
+ return false;
+ } else if (!linkLocal.equals(other.linkLocal))
+ return false;
+ return true;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("global", global);
+ toStringHelper.add("linkLocal", linkLocal);
+ return toStringHelper;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.AddressFamily;
+
+/**
+ * Enumeration of all supported address families.
+ */
+public enum BGPAddressFamily {
+ /**
+ * IP (IP version 4)
+ */
+ IPv4(org.opendaylight.protocol.concepts.IPv4.FAMILY),
+ /**
+ * IP6 (IP version 6)
+ */
+ IPv6(org.opendaylight.protocol.concepts.IPv6.FAMILY),
+ /**
+ * Link State Information
+ */
+ LinkState(null);
+
+ private final AddressFamily<?> family;
+
+ private BGPAddressFamily(final AddressFamily<?> family) {
+ this.family = family;
+ }
+
+ /**
+ * Return the associated address family class.
+ *
+ * @return associated address family class
+ */
+ public AddressFamily<?> getAddressFamily() {
+ return family;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ *
+ * BGP Path Attribute AGGREGATOR.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-5.1.7">BGP Aggregator</a>
+ *
+ */
+public interface BGPAggregator {
+
+ /**
+ * The BGP Speaker returns its own AS Number.
+ *
+ * @return own AS Number
+ */
+ public ASNumber getASNumber();
+
+ /**
+ * The BGP Speaker returns its own IP Address.
+ *
+ * @return own IP Address
+ */
+ public NetworkAddress<?> getNetworkAddress();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.Stateful;
+
+/**
+ *
+ * A common interface for objects that can be added to a topology. It can be either BGPRoute, BGPLink, BGPNode or
+ * BGPPrefix.
+ *
+ */
+public interface BGPObject extends Serializable, Stateful<BaseBGPObjectState> {
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+/**
+ *
+ * Values of BGP Origin Path Attribute.
+ *
+ */
+public enum BGPOrigin {
+ IGP, EGP, INCOMPLETE
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+/**
+ * Enumeration of all supported subsequent address family identifiers.
+ */
+public enum BGPSubsequentAddressFamily {
+ /**
+ * RFC4760: Network Layer Reachability Information used
+ * for unicast forwarding.
+ */
+ Unicast,
+ /**
+ * RFC4364: MPLS-labeled VPN address
+ */
+ MPLSLabeledVPN,
+ /**
+ * draft-ietf-idr-ls-distribution-03 : Linkstate SAFI
+ */
+ Linkstate
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import com.google.common.base.Preconditions;
+
+/**
+ * Utility class identifying a BGP table type. A table type is formed by two identifiers: AFI and SAFI.
+ */
+public final class BGPTableType implements Comparable<BGPTableType>, Identifier {
+
+ private static final long serialVersionUID = -5502662876916458740L;
+
+ private final BGPSubsequentAddressFamily safi;
+
+ private final BGPAddressFamily afi;
+
+ /**
+ * Creates BGP Table type.
+ *
+ * @param afi Address Family Identifier
+ * @param safi Subsequent Address Family Identifier
+ */
+ public BGPTableType(final BGPAddressFamily afi, final BGPSubsequentAddressFamily safi) {
+ this.afi = Preconditions.checkNotNull(afi, "Address family may not be null");
+ this.safi = Preconditions.checkNotNull(safi, "Subsequent address family may not be null");
+ }
+
+ /**
+ * Returns Address Family Identifier.
+ *
+ * @return afi AFI
+ */
+ public BGPAddressFamily getAddressFamily() {
+ return this.afi;
+ }
+
+ /**
+ * Returns Subsequent Address Family Identifier.
+ *
+ * @return safi SAFI
+ */
+ public BGPSubsequentAddressFamily getSubsequentAddressFamily() {
+ return this.safi;
+ }
+
+ @Override
+ public int hashCode() {
+ int ret = 3 * this.afi.hashCode();
+ ret += this.safi.hashCode();
+ return ret;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj != null && obj instanceof BGPTableType) {
+ final BGPTableType o = (BGPTableType) obj;
+ return this.afi.equals(o.afi) && this.safi.equals(o.safi);
+ }
+ return false;
+ }
+
+ @Override
+ public int compareTo(final BGPTableType other) {
+ if (other == null)
+ return 1;
+
+ final int c = this.afi.compareTo(other.afi);
+ if (c != 0)
+ return c;
+ return this.safi.compareTo(other.safi);
+ }
+
+ @Override
+ public String toString() {
+ return this.afi.toString() + "." + this.safi.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.State;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ *
+ * A common interface for objects that can be added to a topology. It can be either BGPRoute, BGPLink, BGPNode or
+ * BGPPrefix.
+ *
+ */
+public class BaseBGPObjectState implements State {
+
+ private static final long serialVersionUID = 2371691093534458869L;
+
+ private final BGPOrigin origin;
+ private final BGPAggregator aggregator;
+
+ /**
+ * Creates BaswBGPObjectState.
+ *
+ * @param origin {@link BGPOrigin}
+ * @param aggregator {@link BGPAggregator}
+ */
+ public BaseBGPObjectState(final BGPOrigin origin, final BGPAggregator aggregator) {
+ super();
+ this.origin = origin;
+ this.aggregator = aggregator;
+ }
+
+ protected BaseBGPObjectState(final BaseBGPObjectState orig) {
+ super();
+ this.origin = orig.origin;
+ this.aggregator = orig.aggregator;
+ }
+
+ /**
+ *
+ * @return the value of the ORIGIN attribute
+ */
+ public final BGPOrigin getOrigin() {
+ return this.origin;
+ }
+
+ /**
+ *
+ * @return BGPAggregator attribute of this object
+ */
+ public final BGPAggregator getAggregator() {
+ return this.aggregator;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("aggregator", this.aggregator);
+ toStringHelper.add("origin", this.origin);
+ return toStringHelper;
+ }
+
+ protected BaseBGPObjectState newInstance() {
+ return new BaseBGPObjectState(this);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.aggregator == null) ? 0 : this.aggregator.hashCode());
+ result = prime * result + ((this.origin == null) ? 0 : this.origin.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final BaseBGPObjectState other = (BaseBGPObjectState) obj;
+ if (this.aggregator == null) {
+ if (other.aggregator != null)
+ return false;
+ } else if (!this.aggregator.equals(other.aggregator))
+ return false;
+ if (this.origin != other.origin)
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing a BGP route-reflector cluster identifier.
+ */
+public final class ClusterIdentifier extends AbstractIdentifier<ClusterIdentifier> {
+ private static final long serialVersionUID = 7119651900750614105L;
+ /**
+ * Size of cluster identifier in bytes.
+ */
+ public static final int SIZE = 4;
+ private final byte[] clusterId;
+
+ /**
+ * Initialize a new Cluster Identifier.
+ *
+ * @param clusterId 4-byte identifier
+ * @throws IllegalArgumentException if the length of supplied clusterId is not 6 bytes
+ */
+ public ClusterIdentifier(final byte[] clusterId) {
+ Preconditions.checkArgument(clusterId.length == 4, "Invalid Cluster ID");
+ this.clusterId = clusterId;
+ }
+
+ @Override
+ public byte[] getBytes() {
+ return this.clusterId;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("clusterId", ByteArray.toHexString(clusterId, "."));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Preconditions;
+
+/**
+ * Object representation of a RFC1997 Community tag. Communities are a way for the advertising entitiy to attach
+ * semantic meaning/policy to advertised objects.
+ */
+public final class Community implements Serializable {
+ /**
+ * NO_EXPORT community. All routes received carrying a communities attribute containing this value MUST NOT be
+ * advertised outside a BGP confederation boundary (a stand-alone autonomous system that is not part of a
+ * confederation should be considered a confederation itself).
+ */
+ public static final Community NO_EXPORT = new Community(new ASNumber(0xFFFF), 0xFF01);
+ /**
+ * NO_ADVERTISE community. All routes received carrying a communities attribute containing this value MUST NOT be
+ * advertised to other BGP peers.
+ */
+ public static final Community NO_ADVERTISE = new Community(new ASNumber(0xFFFF), 0xFF02);
+ /**
+ * NO_EXPORT_SUBCONFED community. All routes received carrying a communities attribute containing this value MUST
+ * NOT be advertised to external BGP peers (this includes peers in other members autonomous systems inside a BGP
+ * confederation).
+ */
+ public static final Community NO_EXPORT_SUBCONFED = new Community(new ASNumber(0xFFFF), 0xFF03);
+
+ private static final long serialVersionUID = -944853598551415685L;
+
+ private final int semantics;
+
+ private final ASNumber as;
+
+ /**
+ * Create a new community tag for a particular AS number and semantics.
+ *
+ * @param as Global semantics namespace identifier (usually the tagging Autonomous System)
+ * @param semantics Sematics identifier (specific meaning defined externally by the namespace)
+ */
+ public Community(final ASNumber as, final int semantics) {
+ Preconditions.checkArgument(as.getHighValue() == 0, "Invalid AS number specified");
+ Preconditions.checkArgument(semantics > 0 && semantics < 65535, "Invalid semantics specified");
+ this.semantics = semantics;
+ this.as = as;
+ }
+
+ /**
+ * Return semantics attribute of community.
+ *
+ * @return Semantics attribute
+ */
+ public int getSemantics() {
+ return this.semantics;
+ }
+
+ /**
+ * Return ASNumber of community.
+ *
+ * @return {@link ASNumber}
+ */
+ public ASNumber getAs() {
+ return this.as;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof Community))
+ return false;
+
+ final Community c = (Community) o;
+ return this.as.equals(c.as) && this.semantics == c.semantics;
+ }
+
+ @Override
+ public int hashCode() {
+ return 7 * this.as.hashCode() + 13 * this.semantics;
+ }
+
+ @Override
+ public final String toString() {
+ final StringBuilder sb = new StringBuilder(this.as.toString());
+ sb.append(':');
+ sb.append(this.semantics);
+ return sb.toString();
+ }
+
+ /**
+ * Creates a Community from its String representation.
+ *
+ * @param string String representation of a community
+ * @return new Community
+ */
+ public static Community valueOf(final String string) {
+ final String[] parts = string.split(":", 2);
+
+ final int asn = Integer.valueOf(parts[0]);
+ final int sem = Integer.valueOf(parts[1]);
+ return new Community(new ASNumber(0, asn), sem);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Object representation of basic Extended Community, as defined by RFC4360. Extended communities are semantic tags,
+ * pretty much same way communities defined in RFC1997, with the notable exceptions of supporting four-byte AS numbers
+ * and having a more complicated structure.
+ */
+public abstract class ExtendedCommunity implements Serializable {
+
+ private static final long serialVersionUID = -6279624143516991855L;
+ private final boolean ianaAuthority;
+ private final boolean transitive;
+
+ /**
+ * Initialize the base class with specified authority/transitive bits.
+ *
+ * @param ianaAuthority Value of the 'IANA Authority' bit
+ * @param transitive Value of the 'Transitive' bit
+ */
+ protected ExtendedCommunity(final boolean ianaAuthority, final boolean transitive) {
+ this.ianaAuthority = ianaAuthority;
+ this.transitive = transitive;
+ }
+
+ /**
+ * Check what authority IANA holds over this extended community.
+ *
+ * @return <li>false IANA-assignable type using the "First Come First Serve" policy
+ *
+ * <li>true Part of this Type Field space is for IANA assignable types using either the Standard Action or
+ * the Early IANA Allocation policy. The rest of this Type Field space is for Experimental use.
+ */
+ public final boolean getIanaAuthority() {
+ return this.ianaAuthority;
+ }
+
+ /**
+ * Check if a community is transitive.
+ *
+ * @return <li>true: the community is transitive <li>false: the community is not transitive
+ */
+ public final boolean isTransitive() {
+ return this.transitive;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.ianaAuthority ? 1231 : 1237);
+ result = prime * result + (this.transitive ? 1231 : 1237);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof ExtendedCommunity))
+ return false;
+ final ExtendedCommunity other = (ExtendedCommunity) obj;
+ if (this.ianaAuthority != other.ianaAuthority)
+ return false;
+ if (this.transitive != other.transitive)
+ return false;
+ return true;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("ianaAuthority", ianaAuthority);
+ toStringHelper.add("transitive", transitive);
+ return toStringHelper;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * DTO for a subtype of Next Hop, containing type IPv4 addresses.
+ */
+public final class IPv4NextHop extends AbstractNextHop<IPv4Address> {
+ private static final long serialVersionUID = -7013857868462257974L;
+
+ /**
+ * Construct a new IPv4-based next hop.
+ *
+ * @param global {@link IPv4Address}
+ */
+ public IPv4NextHop(final IPv4Address global) {
+ super(global, null);
+ }
+
+ /**
+ * Creates a new IPv4NextHop using string IPv4Address.
+ *
+ * @param string String representation of IPv4Address.
+ * @return new IPv4NextHop
+ */
+ public static IPv4NextHop forString(final String string) {
+ return new IPv4NextHop(IPv4.FAMILY.addressForString(string));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+/**
+ * DTO for a subtype of NextHop, containing type IPv6 addresses.
+ */
+public final class IPv6NextHop extends AbstractNextHop<IPv6Address> {
+ private static final long serialVersionUID = -6656906151774744248L;
+
+ /**
+ * Construct a new IPv6 nexhop with only a global address.
+ *
+ * @param global Globally-visible address
+ */
+ public IPv6NextHop(final IPv6Address global) {
+ this(global, null);
+ }
+
+ /**
+ * Construct a new IPv6 nexhop with both global and link-local address.
+ *
+ * @param global Globally-visible address
+ * @param linkLocal Link-local address
+ */
+ public IPv6NextHop(final IPv6Address global, final IPv6Address linkLocal) {
+ super(global, linkLocal);
+ }
+
+ /**
+ * Creates a new IPv6NextHop using string IPv6Address.
+ *
+ * @param global String representation of global IPv6Address.
+ * @return new IPv6NextHop
+ */
+ public static IPv6NextHop forString(final String global) {
+ return new IPv6NextHop(IPv6.FAMILY.addressForString(global));
+ }
+
+ /**
+ * Creates a new IPv6NextHop using global and linkLocal string IPv6Addresses.
+ *
+ * @param global String representation of global IPv6Address
+ * @param linklocal String representation of linkLocal IPv6Address
+ * @return new IPv6NextHop
+ */
+ public static IPv6NextHop forString(final String global, final String linkLocal) {
+ return new IPv6NextHop(IPv6.FAMILY.addressForString(global), IPv6.FAMILY.addressForString(linkLocal));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing a <a href="http://tools.ietf.org/html/rfc4360#section-3.2">IPv4 Address Specific Extended
+ * Community</a>.
+ */
+public class Inet4SpecificExtendedCommunity extends ExtendedCommunity implements Serializable {
+
+ private static final long serialVersionUID = 1355924956883963072L;
+ private final IPv4Address globalAdmin;
+ private final byte[] localAdmin;
+ private final int subType;
+
+ /**
+ * Create a new IPv4 address-specific extended community.
+ *
+ * @param transitive True if the community is transitive
+ * @param subType Community subtype, has to be in range 0-255
+ * @param globalAdmin Globally-assigned namespace (IPv4 address)
+ * @param localAdmin byte[] Locally-assigned value, has to be 2 bytes long
+ * @throws IllegalArgumentException when either subtype or localAdmin is invalid
+ */
+ public Inet4SpecificExtendedCommunity(final boolean transitive, final int subType, final IPv4Address globalAdmin,
+ final byte[] localAdmin) {
+ super(false, transitive);
+ Preconditions.checkArgument(subType > 0 && subType < 255, "Invalid Sub-Type " + subType);
+ Preconditions.checkArgument(localAdmin.length == 2, "Invalid Local Administrator");
+ this.subType = subType;
+ this.globalAdmin = Preconditions.checkNotNull(globalAdmin);
+ this.localAdmin = localAdmin;
+ }
+
+ /**
+ * Returns the community subtype.
+ *
+ * @return Community subtype
+ */
+ public final int getSubType() {
+ return this.subType;
+ }
+
+ /**
+ * Returns the globally-assigned namespace.
+ *
+ * @return Globally-assigned namespace
+ */
+ public final IPv4Address getGlobalAdmin() {
+ return this.globalAdmin;
+ }
+
+ /**
+ * Returns the locally-assigned community value.
+ *
+ * @return Locally-assigned community value
+ */
+ public final byte[] getLocalAdmin() {
+ return this.localAdmin;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("subType", this.subType);
+ toStringHelper.add("globalAdmin", this.globalAdmin);
+ toStringHelper.add("localAdmin", this.localAdmin);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.globalAdmin == null) ? 0 : this.globalAdmin.hashCode());
+ result = prime * result + Arrays.hashCode(this.localAdmin);
+ result = prime * result + this.subType;
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Inet4SpecificExtendedCommunity other = (Inet4SpecificExtendedCommunity) obj;
+ if (this.globalAdmin == null) {
+ if (other.globalAdmin != null)
+ return false;
+ } else if (!this.globalAdmin.equals(other.globalAdmin))
+ return false;
+ if (!Arrays.equals(this.localAdmin, other.localAdmin))
+ return false;
+ if (this.subType != other.subType)
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Interface for BGP Next Hop Attribute.
+ * @see <a href="http://tools.ietf.org/html/rfc2545#section-3">Next Hop</a>
+ *
+ * @param <T> subtype of Network Address
+ */
+public interface NextHop<T extends NetworkAddress<?>> extends Serializable {
+ /**
+ * Return the global address of the next hop. This operation is
+ * always applicable.
+ *
+ * @return T global address
+ */
+ public T getGlobal();
+
+ /**
+ * Return the link-local address of the next hop. This operation is
+ * applicable only to some address types. For address types where
+ * it not applicable, null is returned.
+ *
+ * @return T link-local address, null if unsupported
+ */
+ public T getLinkLocal();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing a <a href="http://tools.ietf.org/html/rfc4360#section-3.3">Opaque Extended Community</a>.
+ */
+public class OpaqueExtendedCommunity extends ExtendedCommunity implements Serializable {
+
+ private static final long serialVersionUID = 2675224758578219774L;
+ private final byte[] value;
+ private final int subType;
+
+ /**
+ * Create a new opaque extended community.
+ *
+ * @param transitive True if the community is transitive
+ * @param subType Community subtype, has to be in range 0-255
+ * @param value Community value, has to be 6 bytes long
+ * @throws IllegalArgumentException when either subtype or value are invalid
+ */
+ public OpaqueExtendedCommunity(final boolean transitive, final int subType, final byte[] value) {
+ super(false, transitive);
+ Preconditions.checkArgument(subType > 0 && subType < 255, "Invalid Sub-Type");
+ Preconditions.checkArgument(value.length == 6, "Invalid value");
+ this.subType = subType;
+ this.value = value;
+ }
+
+ /**
+ * Returns community subtype.
+ *
+ * @return Community subtype
+ */
+ public final int getSubType() {
+ return this.subType;
+ }
+
+ /**
+ * Returns community value
+ *
+ * @return Community value
+ */
+ public final byte[] getValue() {
+ return this.value;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("subType", this.subType);
+ toStringHelper.add("value", this.value);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * @see <a href="http://tools.ietf.org/html/rfc4360#section-5">Route Origin Community</a>
+ */
+public class RouteOriginCommunity extends ASSpecificExtendedCommunity {
+
+ private static final long serialVersionUID = 540725495203637583L;
+
+ /**
+ * Construct a RouteOriginCommunity based on global and local
+ * administrator values.
+ *
+ * @param globalAdmin Global administrator (AS number)
+ * @param localAdmin Local administrator (AS-specific, opaque value)
+ */
+ public RouteOriginCommunity(final ASNumber globalAdmin, final byte[] localAdmin) {
+ super(false, 3, globalAdmin, localAdmin);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * @see <a href="http://tools.ietf.org/html/rfc4360#section-4">Route Target Community</a>
+ */
+public class RouteTargetCommunity extends ASSpecificExtendedCommunity {
+
+ private static final long serialVersionUID = 855252238770644603L;
+
+ /**
+ *
+ * @param globalAdmin Globally-administered identifier, i.e. an {@link ASNumber}
+ * @param localAdmin Locally-administered identifier
+ */
+ public RouteTargetCommunity(final ASNumber globalAdmin, final byte[] localAdmin) {
+ super(false, 2, globalAdmin, localAdmin);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class ASPathTest {
+
+ private ASNumber asn1, asn2, asn3, asn4, asn5, asn6, asn7, asn8;
+
+ private List<ASNumber> visibleAsPath;
+ private Set<ASNumber> aggregatedAsPath;
+
+ @Before
+ public void init() {
+ asn1 = new ASNumber(100, 200);
+ asn2 = new ASNumber(65534);
+ asn3 = new ASNumber(0, 200);
+ asn4 = new ASNumber(100, 199);
+ asn5 = new ASNumber(99, 199);
+ asn6 = new ASNumber(64538);
+ asn7 = new ASNumber(0, 200);
+ asn8 = new ASNumber(100, 0);
+
+ visibleAsPath = new ArrayList<ASNumber>();
+ aggregatedAsPath = new HashSet<ASNumber>();
+
+ visibleAsPath.add(asn1);
+ visibleAsPath.add(asn2);
+ visibleAsPath.add(asn3);
+ visibleAsPath.add(asn4);
+
+ aggregatedAsPath.add(asn5);
+ aggregatedAsPath.add(asn6);
+ aggregatedAsPath.add(asn7);
+ aggregatedAsPath.add(asn8);
+ }
+
+ @Test
+ public void testGetXXXPath() {
+ ASPath asp1 = ASPath.EMPTY;
+ assertEquals(0, asp1.getVisibleAsPath().size());
+ assertEquals(0, asp1.getAggregatedAsPath().size());
+
+ ASPath asp2 = new ASPath(visibleAsPath);
+ assertEquals(4, asp2.getVisibleAsPath().size());
+ assertEquals(0, asp2.getAggregatedAsPath().size());
+
+ ASPath asp3 = new ASPath(visibleAsPath, aggregatedAsPath);
+ assertEquals(4, asp3.getVisibleAsPath().size());
+ assertEquals(4, asp3.getAggregatedAsPath().size());
+ }
+
+ @Test
+ public void testEqualsHashCode() {
+ ASPath asp1 = ASPath.EMPTY;
+ ASPath asp2 = asp1;
+ assertEquals(asp1, asp2);
+ assertEquals(asp1.hashCode(), asp2.hashCode());
+ assertNotNull(asp1);
+ assertThat(asp1, not(new Object()));
+
+ ASPath asp3 = new ASPath(visibleAsPath, aggregatedAsPath);
+ assertThat(asp1, not(equalTo(asp3)));
+ assertThat(asp1.hashCode(), not(equalTo(asp3.hashCode())));
+
+ ASPath asp4 = new ASPath(new ArrayList<ASNumber>(), aggregatedAsPath);
+ assertThat(asp3, not(equalTo(asp4)));
+ }
+
+ @Test
+ public void testToString() {
+ ASPath asp = new ASPath(visibleAsPath, aggregatedAsPath);
+ assertNotNull(asp.toString());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASSpecificExtendedCommunity;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class ASSpecificExtendedCommunityTest {
+
+ private final boolean transitive = true;
+ private final int subType = 123;
+ private final ASNumber globalAdmin = new ASNumber(100, 200);
+ private final byte[] localAdmin = new byte[] { 10, 0, 0, 1 };
+
+ @Test
+ public void testOverflows() {
+ try {
+ new ASSpecificExtendedCommunity(this.transitive, -2, this.globalAdmin, this.localAdmin);
+ fail("Sub-type is negative!");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid Sub-Type", e.getMessage());
+ }
+ try {
+ new ASSpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, new byte[] {});
+ fail("Local Administrator has illegal length!");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid Local Administrator", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testGetSubType() {
+ final ASSpecificExtendedCommunity asSpecExCom = new ASSpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, this.localAdmin);
+ assertEquals(123, asSpecExCom.getSubType());
+ assertEquals(new ASNumber(100, 200), asSpecExCom.getGlobalAdmin());
+ assertArrayEquals(new byte[] { 10, 0, 0, 1 }, asSpecExCom.getLocalAdmin());
+
+ final ASSpecificExtendedCommunity a1 = new ASSpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, this.localAdmin);
+ assertEquals(a1.toString(), asSpecExCom.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ClusterIdentifier;
+
+public class ClusterIdentifierTest {
+
+ @Test
+ public void testClusterIdentifier() {
+ final ClusterIdentifier id = new ClusterIdentifier(new byte[] { 13, 14, 15, 16 });
+ try {
+ new ClusterIdentifier(new byte[] { 5, 6 });
+ fail("Cluster ID is invalid!");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid Cluster ID", e.getMessage());
+ }
+
+ final ClusterIdentifier id1 = new ClusterIdentifier(new byte[] { 13, 14, 15, 16 });
+
+ assertEquals(id1.toString(), id.toString());
+
+ assertArrayEquals(id1.getBytes(), new byte[] { 13, 14, 15, 16 });
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.OpaqueExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteOriginCommunity;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class CommunityTest {
+
+ @Test
+ public void testCommunity() {
+ new Community(new ASNumber(0, 10), 222);
+ final ASNumber as = new ASNumber(12);
+ final Community c = new Community(as, 12);
+ assertEquals(as, c.getAs());
+ assertEquals(12, c.getSemantics());
+ }
+
+ @Test
+ public void testOverflows() {
+ try {
+ new Community(new ASNumber(0, 10), -2);
+ fail("Semantics under range.");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid semantics specified", e.getMessage());
+ }
+ try {
+ new Community(new ASNumber(5, 10), 5);
+ fail("AS high number cannot be null");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid AS number specified", e.getMessage());
+ }
+ try {
+ new Community(new ASNumber(0, 10), 65536);
+ fail("Semantics above range.");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid semantics specified", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testEquals() {
+ final Community c1 = new Community(new ASNumber(0, 10), 222);
+ final Community c2 = new Community(new ASNumber(0, 10), 222);
+ assertEquals(c1, c2);
+ assertThat(c1, not(new Object()));
+ }
+
+ @Test
+ public void testHashCode() {
+ final Community c1 = new Community(new ASNumber(0, 10), 222);
+ final Community c2 = new Community(new ASNumber(0, 10), 222);
+ assertEquals(c1.hashCode(), c2.hashCode());
+ }
+
+ @Test
+ public void testToString() {
+ final Community c = new Community(new ASNumber(0, 10), 222);
+ assertNotNull(c.toString());
+ }
+
+ @Test
+ public void testValueOf() {
+ final Community comm = Community.valueOf("12:50");
+ assertEquals(comm, new Community(new ASNumber(0, 12), 50));
+ }
+
+ @Test
+ public void testExtendedCommunity() {
+ final ExtendedCommunity ec = new OpaqueExtendedCommunity(false, 5, new byte[] { 1, 2, 3, 4, 5, 6 });
+ final Object ec2 = new RouteOriginCommunity(new ASNumber(84), new byte[] { 1, 2, 3, 4 });
+ assertNotSame(ec, ec2);
+ assertEquals(ec, new OpaqueExtendedCommunity(false, 5, new byte[] { 1, 2, 3, 4, 5, 6 }));
+ assertEquals(ec.hashCode(), (new OpaqueExtendedCommunity(false, 5, new byte[] { 1, 2, 3, 4, 5, 6 })).hashCode());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+public class IPv4NextHopTest {
+
+ private IPv4NextHop nextHop;
+
+ @Before
+ public void init() {
+ final IPv4Address address = IPv4.FAMILY.addressForString("10.0.0.1");
+ this.nextHop = new IPv4NextHop(address);
+ }
+
+ @Test
+ public void testGetGlobal() {
+ final IPv4Address address = IPv4.FAMILY.addressForString("10.0.0.1");
+ assertEquals(address, this.nextHop.getGlobal());
+ }
+
+ @Test
+ public void testGetLinkLocal() {
+ assertNull(this.nextHop.getLinkLocal());
+ }
+
+ @Test
+ public void testHashCode() {
+ final IPv4NextHop nextHop2 = IPv4NextHop.forString("10.0.0.1");
+ assertEquals(this.nextHop.hashCode(), nextHop2.hashCode());
+ }
+
+ @Test
+ public void testEquals() {
+ assertNotNull(this.nextHop);
+ assertThat(this.nextHop, not(new Object()));
+
+ final IPv4NextHop nextHop1 = this.nextHop;
+ assertEquals(this.nextHop, nextHop1);
+
+ final IPv4NextHop nextHop2 = IPv4NextHop.forString("10.0.0.1");
+ assertEquals(this.nextHop, nextHop2);
+ }
+
+ @Test
+ public void testToString() {
+ assertNotNull(this.nextHop.toString());
+ }
+
+ @Test
+ public void testForString() {
+ assertEquals(this.nextHop, IPv4NextHop.forString("10.0.0.1"));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+public class IPv6NextHopTest {
+
+ private IPv6NextHop nextHopA;
+ private IPv6NextHop nextHopB;
+
+ @Before
+ public void init() {
+ final IPv6Address global = IPv6.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:7331");
+ final IPv6Address local = IPv6.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:0000");
+ this.nextHopA = new IPv6NextHop(global);
+ this.nextHopB = new IPv6NextHop(global, local);
+ }
+
+ @Test
+ public void testGetGlobal() {
+ final IPv6Address globalTestAddress = IPv6.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:7331");
+
+ assertEquals(this.nextHopA.getGlobal(), globalTestAddress);
+ assertEquals(this.nextHopB.getGlobal(), globalTestAddress);
+ }
+
+ @Test
+ public void testGetLinkLocal() {
+ final IPv6Address localTestAddress = IPv6.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:0000");
+
+ assertNull(this.nextHopA.getLinkLocal());
+ assertEquals(this.nextHopB.getLinkLocal(), localTestAddress);
+ }
+
+ @Test
+ public void testHashCode() {
+ final IPv6NextHop nextHop1 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331");
+ final IPv6NextHop nextHop2 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331", "2001:db8:85a3:0:0:8a2e:370:0000");
+ assertEquals(this.nextHopA.hashCode(), nextHop1.hashCode());
+ assertEquals(this.nextHopB.hashCode(), nextHop2.hashCode());
+ }
+
+ @Test
+ public void testEquals() {
+ assertNotNull(this.nextHopA);
+ assertNotNull(this.nextHopB);
+ assertThat(this.nextHopA, not(new Object()));
+ assertThat(this.nextHopB, not(new Object()));
+
+ final IPv6NextHop nextHop1 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331");
+ final IPv6NextHop nextHop2 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331", "2001:db8:85a3:0:0:8a2e:370:0000");
+ assertEquals(this.nextHopA, nextHop1);
+ assertEquals(this.nextHopB, nextHop2);
+
+ final IPv6NextHop x = this.nextHopA;
+ assertEquals(this.nextHopA, x);
+
+ final IPv6NextHop y = this.nextHopB;
+ assertEquals(this.nextHopB, y);
+
+ final IPv6NextHop nextHop3 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7332");
+ final IPv6NextHop nextHop4 = IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7332", "2001:db8:85a3:0:0:8a2e:370:0000");
+ assertThat(this.nextHopA, not(nextHop3));
+ assertThat(this.nextHopA, not(nextHop4));
+ assertThat(this.nextHopB, not(nextHop3));
+ assertThat(this.nextHopB, not(nextHop4));
+ }
+
+ @Test
+ public void testToString() {
+ assertNotNull(this.nextHopA.toString());
+ assertNotNull(this.nextHopB.toString());
+ }
+
+ @Test
+ public void testForString() {
+ assertEquals(this.nextHopA, IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331"));
+ assertEquals(this.nextHopB, IPv6NextHop.forString("2001:db8:85a3:0:0:8a2e:370:7331", "2001:db8:85a3:0:0:8a2e:370:0000"));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.Inet4SpecificExtendedCommunity;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+public class Inet4SpecificExtendedCommunityTest {
+
+ private boolean transitive;
+ private int subType;
+ private IPv4Address globalAdmin;
+ private byte[] localAdmin;
+
+ private Inet4SpecificExtendedCommunity community;
+
+ @Before
+ public void init() {
+ this.transitive = true;
+ this.subType = 123;
+ this.globalAdmin = IPv4.FAMILY.addressForString("10.0.0.1");
+ this.localAdmin = new byte[] { 10, 1 };
+ this.community = new Inet4SpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, this.localAdmin);
+ }
+
+ @Test
+ public void testOverflows() {
+ try {
+ new Inet4SpecificExtendedCommunity(this.transitive, -2, this.globalAdmin, this.localAdmin);
+ fail("Sub-type is negative!");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid Sub-Type -2", e.getMessage());
+ }
+ try {
+ new Inet4SpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, new byte[] { 10, 0, 1 });
+ fail("Invalid length of local administrator!");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid Local Administrator", e.getMessage());
+ }
+ try {
+ new Inet4SpecificExtendedCommunity(this.transitive, 256, this.globalAdmin, this.localAdmin);
+ fail("Sub-type is above range!");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid Sub-Type 256", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testGetSubType() {
+ final int subType = 123;
+ assertEquals(subType, this.community.getSubType());
+ }
+
+ @Test
+ public void testGetGlobalAdmin() {
+ final IPv4Address globalAdmin = IPv4.FAMILY.addressForString("10.0.0.1");
+ assertEquals(globalAdmin, this.community.getGlobalAdmin());
+ }
+
+ @Test
+ public void testGetLocalAdmin() {
+ final byte[] localAdmin = new byte[] { 10, 1 };
+ assertArrayEquals(localAdmin, this.community.getLocalAdmin());
+ }
+
+ @Test
+ public void testGetIanaAuthority() {
+ // Should be always false for Inet4SpecificExtendedCommunity instances
+ assertFalse(this.community.getIanaAuthority());
+ }
+
+ @Test
+ public void testIsTransitive() {
+ assertTrue(this.community.isTransitive());
+ }
+
+ @Test
+ public void testToString() {
+ final Inet4SpecificExtendedCommunity comm = new Inet4SpecificExtendedCommunity(this.transitive, this.subType, this.globalAdmin, this.localAdmin);
+ assertEquals(this.community.toString(), comm.toString());
+ assertEquals(this.community, comm);
+ assertEquals(this.community.hashCode(), comm.hashCode());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.OpaqueExtendedCommunity;
+
+public class OpaqueExtendedCommunityTest {
+
+ private boolean transitive;
+ private int subType;
+ private byte[] value;
+
+ private OpaqueExtendedCommunity community;
+
+ @Before
+ public void init() {
+ this.transitive = true;
+ this.subType = 222;
+ this.value = new byte[] { 1, 5, 9, 3, 5, 7 };
+ this.community = new OpaqueExtendedCommunity(this.transitive, this.subType, this.value);
+ }
+
+ @Test
+ public void testOverflows() {
+ try {
+ new OpaqueExtendedCommunity(this.transitive, -2, this.value);
+ fail("Sub-type is negative!");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid Sub-Type", e.getMessage());
+ }
+ try {
+ new OpaqueExtendedCommunity(this.transitive, 256, this.value);
+ fail("Sub-type is above range!");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid Sub-Type", e.getMessage());
+ }
+ try {
+ new OpaqueExtendedCommunity(this.transitive, this.subType, new byte[] { 0, 1, 2, 3, 4, 5, 6, });
+ fail("Constructor successful unexpectedly");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Invalid value", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testGetSubType() {
+ assertEquals(222, this.community.getSubType());
+ }
+
+ @Test
+ public void testGetValue() {
+ assertArrayEquals(new byte[] { 1, 5, 9, 3, 5, 7 }, this.community.getValue());
+ }
+
+ @Test
+ public void testGetIanaAuthority() {
+ assertFalse(this.community.getIanaAuthority());
+ }
+
+ @Test
+ public void testIsTransitive() {
+ assertTrue(this.community.isTransitive());
+ }
+
+ @Test
+ public void testToString() {
+ final OpaqueExtendedCommunity c = new OpaqueExtendedCommunity(false, this.subType, this.value);
+ assertNotSame(c.toString(), this.community.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.RouteOriginCommunity;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class RouteOriginCommunityTest {
+
+ private RouteOriginCommunity community;
+
+ @Before
+ public void init() {
+ final ASNumber globalAdmin = new ASNumber(100, 200);
+ final byte[] localAdmin = new byte[] { 10, 0, 0, 1 };
+ this.community = new RouteOriginCommunity(globalAdmin, localAdmin);
+ }
+
+ @Test
+ public void testGetSubType() {
+ assertEquals(3, this.community.getSubType());
+ }
+
+ @Test
+ public void testGetGlobalAdmin() {
+ final ASNumber testAsn = new ASNumber(100, 200);
+ assertEquals(this.community.getGlobalAdmin(), testAsn);
+ }
+
+ @Test
+ public void testGetLocalAdmin() {
+ assertArrayEquals(new byte[] { 10, 0, 0, 1 }, this.community.getLocalAdmin());
+ }
+
+ @Test
+ public void testGetIanaAuthority() {
+ assertFalse(this.community.getIanaAuthority());
+ }
+
+ @Test
+ public void testIsTransitive() {
+ assertFalse(this.community.isTransitive());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.RouteTargetCommunity;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public class RouteTargetCommunityTest {
+
+ private RouteTargetCommunity community;
+
+ @Before
+ public void init() {
+ final ASNumber globalAdmin = new ASNumber(100, 200);
+ final byte[] localAdmin = new byte[] { 10, 0, 0, 1 };
+ this.community = new RouteTargetCommunity(globalAdmin, localAdmin);
+ }
+
+ @Test
+ public void testGetSubType() {
+ assertEquals(2, this.community.getSubType());
+ }
+
+ @Test
+ public void testGetGlobalAdmin() {
+ final ASNumber testAsn = new ASNumber(100, 200);
+ assertEquals(this.community.getGlobalAdmin(), testAsn);
+ }
+
+ @Test
+ public void testGetLocalAdmin() {
+ assertArrayEquals(new byte[] { 10, 0, 0, 1 }, this.community.getLocalAdmin());
+ }
+
+ @Test
+ public void testGetIanaAuthority() {
+ assertFalse(this.community.getIanaAuthority());
+ }
+
+ @Test
+ public void testIsTransitive() {
+ assertFalse(this.community.isTransitive());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv6;
+
+public class TableTypeTest {
+
+ @Test
+ public void testTableTypes() {
+ final BGPTableType tt1 = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.MPLSLabeledVPN);
+ final BGPTableType tt2 = new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.valueOf("MPLSLabeledVPN"));
+ final BGPTableType tt3 = new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast);
+
+ assertEquals(IPv6.FAMILY, BGPAddressFamily.IPv6.getAddressFamily());
+ assertNull(BGPAddressFamily.LinkState.getAddressFamily());
+
+ try {
+ new BGPTableType(null, BGPSubsequentAddressFamily.MPLSLabeledVPN);
+ fail("Null AFI!");
+ } catch (final NullPointerException e) {
+ assertEquals("Address family may not be null", e.getMessage());
+ }
+
+ try {
+ new BGPTableType(BGPAddressFamily.valueOf("IPv6"), null);
+ fail("Null SAFI!");
+ } catch (final NullPointerException e) {
+ assertEquals("Subsequent address family may not be null", e.getMessage());
+ }
+
+ assertFalse(tt1.equals(tt2));
+ assertNotSame(tt1.hashCode(), tt2.hashCode());
+ assertEquals(1, tt2.compareTo(tt1));
+ assertEquals(1, tt2.compareTo(tt3));
+ assertEquals(tt1.toString(), tt1.toString());
+ assertNotSame(tt1.getAddressFamily(), tt2.getAddressFamily());
+ assertEquals(tt1.getSubsequentAddressFamily(), tt2.getSubsequentAddressFamily());
+ }
+
+ @Test
+ public void testOrigin() {
+ final BGPOrigin or = BGPOrigin.EGP;
+ assertEquals(or.name(), "EGP");
+ }
+
+ @Test
+ public void testBaseBGPObjectState() {
+ final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.INCOMPLETE, null);
+ final BaseBGPObjectState state1 = new BaseBGPObjectState(BGPOrigin.INCOMPLETE, null);
+ assertNull(state.getAggregator());
+ assertEquals(BGPOrigin.INCOMPLETE, state.getOrigin());
+ assertEquals(state.toString(), state1.toString());
+
+ final BaseBGPObjectState s = new BaseBGPObjectState(state);
+ assertEquals(state, s);
+ assertEquals(state.hashCode(), s.hashCode());
+
+ assertEquals(s, s.newInstance());
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-linkstate</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-linkstate</artifactId>
+ <description>BGP linkstate concepts</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.linkstate
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.version}</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-CONCEPTS Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractLANIdentifier<T extends RouterIdentifier> implements LANIdentifier<T> {
+ private static final long serialVersionUID = 1L;
+ private final T designatedRouter;
+
+ protected AbstractLANIdentifier(final T designatedRouter) {
+ this.designatedRouter = Preconditions.checkNotNull(designatedRouter);
+ }
+
+ @Override
+ final public T getDesignatedRouter() {
+ return this.designatedRouter;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("designatedRouter", this.designatedRouter);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((designatedRouter == null) ? 0 : designatedRouter.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ AbstractLANIdentifier<?> other = (AbstractLANIdentifier<?>) obj;
+ if (designatedRouter == null) {
+ if (other.designatedRouter != null)
+ return false;
+ } else if (!designatedRouter.equals(other.designatedRouter))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractNetworkAddressRouterIdentifier<T extends NetworkAddress<?>> implements NetworkAddressRouterIdentifier<T> {
+ private static final long serialVersionUID = 1L;
+ private final T address;
+
+ protected AbstractNetworkAddressRouterIdentifier(final T address) {
+ Preconditions.checkNotNull(address, "Address may not be null");
+ this.address = address;
+ }
+
+ @Override
+ public T getAddress() {
+ return this.address;
+ }
+
+ @Override
+ public final String toString() {
+ return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("address", this.address);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.address == null) ? 0 : this.address.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final AbstractNetworkAddressRouterIdentifier<?> other = (AbstractNetworkAddressRouterIdentifier<?>) obj;
+ if (this.address == null) {
+ if (other.address != null)
+ return false;
+ } else if (!this.address.equals(other.address))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An abstract OSPF LAN "pseudonode" identifier. This class is specialized for OSPFv2 and OSPFv3 as the two differ only
+ * slightly in semantics.
+ */
+public abstract class AbstractOSPFLANIdentifier<T extends InterfaceIdentifier> extends AbstractLANIdentifier<OSPFRouterIdentifier> {
+ private static final long serialVersionUID = 1L;
+ private final T lanInterface;
+
+ protected AbstractOSPFLANIdentifier(final OSPFRouterIdentifier dr, final T lanInterface) {
+ super(dr);
+ this.lanInterface = Preconditions.checkNotNull(lanInterface);
+ }
+
+ public final T getLANInterface() {
+ return this.lanInterface;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("lanInterface", this.lanInterface);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((lanInterface == null) ? 0 : lanInterface.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ AbstractOSPFLANIdentifier<?> other = (AbstractOSPFLANIdentifier<?>) obj;
+ if (lanInterface == null) {
+ if (other.lanInterface != null)
+ return false;
+ } else if (!lanInterface.equals(other.lanInterface))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * Identifier class for Administrative Groups. Administrative groups, also
+ * known as Colors, are a way for administrative authority to assign objects
+ * to groups. This allows separation of policy, which defines what actions
+ * should be applied to a particular group from actual assignment of objects.
+ */
+public class AdministrativeGroup implements Comparable<AdministrativeGroup>, Identifier {
+ public static final AdministrativeGroup NONE = new AdministrativeGroup(0);
+ private static final long serialVersionUID = 6127162286553485280L;
+ private final long value;
+
+ /**
+ * Create a new administrative group. Each group has a numeric
+ * identifier in range 0-4294967295. Two groups with the same
+ * identifier are considered equal.
+ *
+ * @param value Group identifier value
+ */
+ public AdministrativeGroup(final long value) {
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid Administrative Group value");
+ this.value = value;
+ }
+
+ /**
+ * Standard getter for value attribute of {@link AdministrativeGroup}.
+ *
+ * @return Group identifier value
+ */
+ public final long getValue() {
+ return value;
+ }
+
+ @Override
+ public final int compareTo(final AdministrativeGroup other) {
+ if (value < other.value)
+ return -1;
+ if (value > other.value)
+ return 1;
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (value ^ (value >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof AdministrativeGroup))
+ return false;
+ final AdministrativeGroup other = (AdministrativeGroup) obj;
+ if (value != other.value)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Area Identifier SubTLV from Identifier TLV.
+ *
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2.1.3">Area Identifier
+ * SubTLV</a>
+ */
+public final class AreaIdentifier extends AbstractIdentifier<AreaIdentifier> {
+ private static final long serialVersionUID = 1L;
+ private final byte[] id;
+
+ /**
+ * Construct a new Node Area identifier. This constructor expects a non-empty byte array which is the are
+ * distinguisher. Maximum length of the array is capped at 20 bytes.
+ *
+ * @param id Area identifier, expressed as a byte array
+ * @throws IllegalArgumentException if the identifier is not valid
+ */
+ public AreaIdentifier(final byte[] id) {
+ Preconditions.checkArgument(id.length == 4);
+ this.id = id;
+ }
+
+ /**
+ * Access the underlying identifier.
+ *
+ * @return Identifier bytearray of AreaIdentifier.
+ */
+ @Override
+ public final byte[] getBytes() {
+ return this.id;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("id", ByteArray.toHexString(id, "."));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Domain Identifier SubTLV from Identifier TLV.
+ *
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2.1.2">Domain Identifier
+ * SubTLV</a>
+ */
+public final class DomainIdentifier extends AbstractIdentifier<DomainIdentifier> {
+
+ private static final long serialVersionUID = -5033319198070873474L;
+
+ private final byte[] id;
+
+ /**
+ * Create a new domain identifier using its raw identifier. There is not length constraint.
+ *
+ * @param id Raw identifier, has to be four bytes long.
+ */
+ public DomainIdentifier(final byte[] id) {
+ Preconditions.checkNotNull(id);
+ Preconditions.checkArgument(id.length == 4);
+ this.id = id;
+ }
+
+ /**
+ * Returns the raw identifier
+ *
+ * @return Raw identifier
+ */
+ @Override
+ public byte[] getBytes() {
+ return this.id;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("id", ByteArray.toHexString(id, "."));
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + Arrays.hashCode(this.id);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final DomainIdentifier other = (DomainIdentifier) obj;
+ if (!Arrays.equals(this.id, other.id))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.SignedBytes;
+
+public final class ExtendedRouteTag implements Serializable, Comparable<ExtendedRouteTag> {
+ private static final long serialVersionUID = 1L;
+ private final byte[] value;
+
+ public ExtendedRouteTag(final byte[] value) {
+ Preconditions.checkNotNull(value);
+ Preconditions.checkArgument(value.length == 8);
+ this.value = value;
+ }
+
+ @Override
+ public String toString(){
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("value", Arrays.toString(value));
+ return toStringHelper;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(value);
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ExtendedRouteTag other = (ExtendedRouteTag) obj;
+ if (!Arrays.equals(value, other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(final ExtendedRouteTag o) {
+ if (o == null)
+ return 1;
+ if (o == this)
+ return 0;
+ return SignedBytes.lexicographicalComparator().compare(value, o.value);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.base.Preconditions;
+
+public final class IPv4InterfaceIdentifier implements Comparable<IPv4InterfaceIdentifier>, InterfaceIdentifier {
+ private static final long serialVersionUID = 1L;
+ private final IPv4Address value;
+
+ /**
+ * Create a new unnumbered link identifier.
+ *
+ * @param value Raw link identifier, has to be in range 1-4294967295
+ * @throws IllegalArgumentException when value is outside of allowed range
+ */
+ public IPv4InterfaceIdentifier(final IPv4Address value) {
+ Preconditions.checkNotNull(value, "Unsupported identifier value");
+ this.value = value;
+ }
+
+ /**
+ * Returns raw link identifier value.
+ *
+ * @return value Raw link identifier value
+ */
+ public IPv4Address getValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.value.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final IPv4InterfaceIdentifier other = (IPv4InterfaceIdentifier) obj;
+ if (!this.value.equals(other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(final IPv4InterfaceIdentifier other) {
+ if (this == other)
+ return 0;
+ if (other == null)
+ return 1;
+ return this.value.compareTo(other.value);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("IPv4InterfaceIdentifier [value=");
+ builder.append(this.value);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ public static IPv4InterfaceIdentifier forString(final String string) {
+ Preconditions.checkNotNull(string);
+ return new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString(string));
+ }
+
+ public static IPv4InterfaceIdentifier forBytes(final byte[] bytes) {
+ Preconditions.checkNotNull(bytes);
+ return new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForBytes(bytes));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+
+public final class IPv4PrefixIdentifier extends PrefixIdentifier<IPv4Address> {
+ private static final long serialVersionUID = 1L;
+
+ public IPv4PrefixIdentifier(final NodeIdentifier owner, final IPv4Prefix prefix) {
+ super(owner, prefix);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * Interface representing an IPv4 network route. This interface exists
+ * purely as a specialized extension on NetworkRoute to work around the
+ * loss of run-time information caused by type erasure.
+ */
+public interface IPv4Route extends NetworkRoute<IPv4Address> {
+
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.base.Preconditions;
+
+public final class IPv4RouterIdentifier extends AbstractNetworkAddressRouterIdentifier<IPv4Address> {
+ private static final long serialVersionUID = 1L;
+
+ public IPv4RouterIdentifier(final IPv4Address address) {
+ super(address);
+ }
+
+ public static IPv4RouterIdentifier forString(final String string) {
+ Preconditions.checkNotNull(string);
+ return new IPv4RouterIdentifier(IPv4.FAMILY.addressForString(string));
+ }
+
+ public static IPv4RouterIdentifier forBytes(final byte[] bytes) {
+ Preconditions.checkNotNull(bytes);
+ return new IPv4RouterIdentifier(IPv4.FAMILY.addressForBytes(bytes));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import com.google.common.base.Preconditions;
+
+public final class IPv6InterfaceIdentifier implements Comparable<IPv6InterfaceIdentifier>, InterfaceIdentifier {
+ private static final long serialVersionUID = 1L;
+ private final IPv6Address value;
+
+ /**
+ * Create a new unnumbered link identifier.
+ *
+ * @param value Raw link identifier, has to be in range 1-4294967295
+ * @throws IllegalArgumentException when value is outside of allowed range
+ */
+ public IPv6InterfaceIdentifier(final IPv6Address value) {
+ this.value = Preconditions.checkNotNull(value, "Unsupported identifier value");
+ }
+
+ /**
+ * Returns raw link identifier value.
+ *
+ * @return value Raw link identifier value
+ */
+ public IPv6Address getValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.value.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final IPv6InterfaceIdentifier other = (IPv6InterfaceIdentifier) obj;
+ if (!this.value.equals(other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(final IPv6InterfaceIdentifier other) {
+ if (this == other)
+ return 0;
+ if (other == null)
+ return 1;
+ return this.value.compareTo(other.value);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("IPv6InterfaceIdentifier [value=");
+ builder.append(this.value);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ public static IPv6InterfaceIdentifier forString(final String string) {
+ Preconditions.checkNotNull(string);
+ return new IPv6InterfaceIdentifier(IPv6.FAMILY.addressForString(string));
+ }
+
+ public static IPv6InterfaceIdentifier forBytes(final byte[] bytes) {
+ Preconditions.checkNotNull(bytes);
+ return new IPv6InterfaceIdentifier(IPv6.FAMILY.addressForBytes(bytes));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+
+public final class IPv6PrefixIdentifier extends PrefixIdentifier<IPv6Address> {
+ private static final long serialVersionUID = 1L;
+
+ public IPv6PrefixIdentifier(final NodeIdentifier owner, final IPv6Prefix prefix) {
+ super(owner, prefix);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+/**
+ * Interface representing an IPv6 network route. This interface exists
+ * purely as a specialized extension on NetworkRoute to work around the
+ * loss of run-time information caused by type erasure.
+ */
+public interface IPv6Route extends NetworkRoute<IPv6Address> {
+
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import com.google.common.base.Preconditions;
+
+public final class IPv6RouterIdentifier extends AbstractNetworkAddressRouterIdentifier<IPv6Address> {
+ private static final long serialVersionUID = 1L;
+
+ public IPv6RouterIdentifier(final IPv6Address address) {
+ super(address);
+ }
+
+ public static IPv6RouterIdentifier forString(final String string) {
+ Preconditions.checkNotNull(string);
+ return new IPv6RouterIdentifier(IPv6.FAMILY.addressForString(string));
+ }
+
+ public static IPv6RouterIdentifier forBytes(final byte[] bytes) {
+ Preconditions.checkNotNull(bytes);
+ return new IPv6RouterIdentifier(IPv6.FAMILY.addressForBytes(bytes));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.3.1.2
+ */
+public final class ISISAreaIdentifier extends AbstractIdentifier<ISISAreaIdentifier> {
+ private static final long serialVersionUID = 1L;
+ private final byte[] id;
+
+ /**
+ * Construct a new Node Area identifier. This constructor expects
+ * a non-empty byte array which is the are distinguisher. Maximum
+ * length of the array is capped at 20 bytes.
+ *
+ * @param id Area identifier, expressed as a byte array
+ * @throws IllegalArgumentException if the identifier is not valid
+ */
+ public ISISAreaIdentifier(final byte[] id) {
+ this.id = Preconditions.checkNotNull(id);
+ Preconditions.checkArgument(id.length > 0 && id.length <= 20);
+ }
+
+ /**
+ * Access the underlying identifier.
+ *
+ * @return Identifier bytearray of AreaIdentifier.
+ */
+ @Override
+ public final byte[] getBytes() {
+ return this.id;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("id", ByteArray.toHexString(id, "."));
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An IS-IS node identifier.
+ */
+public final class ISISLANIdentifier extends AbstractLANIdentifier<ISISRouterIdentifier> {
+ private static final long serialVersionUID = 1L;
+ private final short psn;
+
+ /**
+ * Construct a new node identifier. Formed as the unification of component identifiers.
+ *
+ * @param systemId ISO System ID, may not be null
+ */
+ public ISISLANIdentifier(final ISOSystemIdentifier systemId, final short psn) {
+ this(new ISISRouterIdentifier(systemId), psn);
+ }
+
+ public ISISLANIdentifier(final ISISRouterIdentifier dis, final short psn) {
+ super(dis);
+ Preconditions.checkArgument(psn > 0 && psn < 255);
+ this.psn = psn;
+ }
+
+ public short getPSN() {
+ return psn;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("psn", psn);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + psn;
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ISISLANIdentifier other = (ISISLANIdentifier) obj;
+ if (psn != other.psn)
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * ISIS-specific prefix prefix advertisement.
+ * @param <T> Network Address type of the prefix being advertised
+ */
+public interface ISISNetworkPrefix<T extends NetworkAddress<?>> extends NetworkPrefix<T> {
+ @Override
+ public ISISNetworkPrefixState currentState();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.SortedSet;
+
+import org.opendaylight.protocol.bgp.linkstate.ExtendedRouteTag;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * ISIS-specific prefix prefix advertisement state.
+ */
+public class ISISNetworkPrefixState extends NetworkPrefixState {
+ private static final long serialVersionUID = 1L;
+ private final SortedSet<ExtendedRouteTag> extendedRouteTags;
+ private final boolean upDownBit;
+
+ public ISISNetworkPrefixState(NetworkPrefixState orig, SortedSet<ExtendedRouteTag> extendedRouteTags, boolean upDownBit) {
+ super(orig);
+ this.extendedRouteTags = extendedRouteTags;
+ this.upDownBit = upDownBit;
+ }
+
+ protected ISISNetworkPrefixState(ISISNetworkPrefixState orig) {
+ super(orig);
+ this.extendedRouteTags = orig.extendedRouteTags;
+ this.upDownBit = orig.upDownBit;
+ }
+
+ /**
+ * Returns the IS-IS extended route tags associated with this
+ * advertisement.
+ *
+ * @return IS-IS extended route tags, may be empty
+ */
+ public final SortedSet<ExtendedRouteTag> getExtendedRouteTags() {
+ return extendedRouteTags;
+ }
+
+ /**
+ * Returns the IS-IS Up/Down bit associated with this advertisement.
+ *
+ * @return Status of the IS-IS Up/Down bit
+ */
+ public final boolean getUpDownBit() {
+ return upDownBit;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("extendedRouteTags", this.extendedRouteTags);
+ toStringHelper.add("upDownBit", this.upDownBit);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An IS-IS node identifier.
+ */
+public final class ISISRouterIdentifier implements RouterIdentifier {
+ private static final long serialVersionUID = 1L;
+ private final ISOSystemIdentifier systemId;
+
+ /**
+ * Construct a new node identifier. Formed as the unification of component identifiers.
+ *
+ * @param systemId ISO System ID, may not be null
+ */
+ public ISISRouterIdentifier(final ISOSystemIdentifier systemId) {
+ this.systemId = Preconditions.checkNotNull(systemId, "ISO System Identifier is mandatory.");
+ }
+
+ public final ISOSystemIdentifier getSystemId() {
+ return this.systemId;
+ }
+
+ @Override
+ public final String toString() {
+ return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("systemId", this.systemId);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.systemId == null) ? 0 : this.systemId.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final ISISRouterIdentifier other = (ISISRouterIdentifier) obj;
+ if (this.systemId == null) {
+ if (other.systemId != null)
+ return false;
+ } else if (!this.systemId.equals(other.systemId))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+public interface InterfaceIdentifier extends Identifier {
+
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+public interface LANIdentifier<T extends RouterIdentifier> extends RouterIdentifier {
+ public T getDesignatedRouter();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Identifier specifying a Link Anchor. A link is anchored by two nodes.
+ * In case there are multiple links between two nodes with the same
+ * directionality, each of them carries a different Interface Identifier.
+ */
+public final class LinkAnchor implements Identifier {
+
+ private static final long serialVersionUID = 4768211569568229262L;
+
+ private final NodeIdentifier nodeIdentifier;
+
+ private final InterfaceIdentifier interfaceIdentifier;
+
+ /**
+ * Construct a new link anchor.
+ *
+ * @param nodeIdentifier Node Identifier part, may not be null
+ * @param interfaceIdentifier Interface Identifier part, possibly null
+ */
+ public LinkAnchor(final NodeIdentifier nodeIdentifier, final InterfaceIdentifier interfaceIdentifier) {
+ if(nodeIdentifier == null)
+ throw new NullPointerException("Can not create link anchor with null node identifier.");
+ this.nodeIdentifier = nodeIdentifier;
+ this.interfaceIdentifier = interfaceIdentifier;
+ }
+
+ /**
+ * Returns the Node Identifier part of this anchor.
+ *
+ * @return Node Identifier part
+ */
+ public NodeIdentifier getNodeIdentifier() {
+ return this.nodeIdentifier;
+ }
+
+ /**
+ * Returns the Interface Identifier part of this anchor.
+ *
+ * @return Interface Identifier part, may be null
+ */
+ public InterfaceIdentifier getInterfaceIdentifier() {
+ return this.interfaceIdentifier;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("node", nodeIdentifier);
+ toStringHelper.add("interface", interfaceIdentifier);
+ return toStringHelper;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime
+ * result
+ + (this.interfaceIdentifier == null ? 0 : this.interfaceIdentifier
+ .hashCode());
+ result = prime * result
+ + (this.nodeIdentifier == null ? 0 : this.nodeIdentifier.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final LinkAnchor other = (LinkAnchor) obj;
+ if (this.interfaceIdentifier == null) {
+ if (other.interfaceIdentifier != null)
+ return false;
+ } else if (!this.interfaceIdentifier.equals(other.interfaceIdentifier))
+ return false;
+ if (this.nodeIdentifier == null) {
+ if (other.nodeIdentifier != null)
+ return false;
+ } else if (!this.nodeIdentifier.equals(other.nodeIdentifier))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * A network link identifier. An instance of this object uniquely identifies
+ * a link between two nodes.
+ */
+public final class LinkIdentifier implements Identifier {
+ private static final long serialVersionUID = 1L;
+ private final TopologyIdentifier topology;
+ private final LinkAnchor localAnchor, remoteAnchor;
+
+ /**
+ * Construct a new Link identifier based on its partial identifiers.
+ *
+ * @param topology Link topology identifier, may be null
+ * @param localAnchor Link local anchor
+ * @param remoteAnchor Link remote anchor
+ * @throws IllegalArgumentException when anchors do not have equal
+ * source protocol
+ */
+ public LinkIdentifier(final TopologyIdentifier topology, final LinkAnchor localAnchor, final LinkAnchor remoteAnchor) {
+ this.topology = topology;
+ this.localAnchor = localAnchor;
+ this.remoteAnchor = remoteAnchor;
+ }
+
+ /**
+ * Returns the local anchor identifier.
+ *
+ * @return Local anchor identifier
+ */
+ public LinkAnchor getLocalAnchor() {
+ return localAnchor;
+ }
+
+ /**
+ * Returns the remote anchor identifier.
+ *
+ * @return Remove anchor identifier
+ */
+ public LinkAnchor getRemoteAnchor() {
+ return remoteAnchor;
+ }
+
+ /**
+ * Returns identifier of topology to which this link belongs.
+ *
+ * @return Link's topology identifier
+ */
+ public TopologyIdentifier getTopology() {
+ return topology;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("topology", topology);
+ toStringHelper.add("localAnchor", localAnchor);
+ toStringHelper.add("remoteAnchor", remoteAnchor);
+ return toStringHelper;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (topology == null ? 0 : topology.hashCode());
+ result = prime * result + (localAnchor == null ? 0 : localAnchor.hashCode());
+ result = prime * result + (remoteAnchor == null ? 0 : remoteAnchor.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final LinkIdentifier other = (LinkIdentifier) obj;
+ if (localAnchor == null) {
+ if (other.localAnchor != null)
+ return false;
+ } else if (!localAnchor.equals(other.localAnchor))
+ return false;
+ if (remoteAnchor == null) {
+ if (other.remoteAnchor != null)
+ return false;
+ } else if (!remoteAnchor.equals(other.remoteAnchor))
+ return false;
+ if (topology == null) {
+ if (other.topology != null)
+ return false;
+ } else if (!topology.equals(other.topology))
+ return false;
+ return true;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+/**
+ * Enumeration of possibilities how a link can be protected.
+ * @see <a href="http://tools.ietf.org/html/rfc4202#section-2.2">RFC 4202</a>
+ */
+public enum LinkProtectionType {
+ /**
+ * If the link is of type Extra Traffic, it means that the link is
+ * protecting another link or links. The LSPs on a link of this type
+ * will be lost if any of the links it is protecting fail.
+ */
+ EXTRA_TRAFFIC,
+ /**
+ * If the link is of type Unprotected, it means that there is no
+ * other link protecting this link. The LSPs on a link of this type
+ * will be lost if the link fails.
+ */
+ UNPROTECTED,
+ /**
+ * If the link is of type Shared, it means that there are one or more
+ * disjoint links of type Extra Traffic that are protecting this
+ * link. These Extra Traffic links are shared between one or more
+ * links of type Shared.
+ */
+ SHARED,
+ /**
+ * If the link is of type Dedicated 1:1, it means that there is one
+ * dedicated disjoint link of type Extra Traffic that is protecting
+ * this link.
+ */
+ DEDICATED_ONE_TO_ONE,
+ /**
+ * If the link is of type Dedicated 1+1, it means that a dedicated
+ * disjoint link is protecting this link. However, the protecting
+ * link is not advertised in the link state database and is therefore
+ * not available for the routing of LSPs.
+ */
+ DEDICATED_ONE_PLUS_ONE,
+ /**
+ * If the link is of type Enhanced, it means that a protection scheme
+ * that is more reliable than Dedicated 1+1, e.g., 4 fiber
+ * BLSR/MS-SPRING, is being used to protect this link.
+ */
+ ENHANCED
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+/**
+ * Enumeration of all supported signalling protocols which support tunnel
+ * establishment in a MPLS network.
+ */
+public enum MPLSProtocol {
+ /**
+ * Label Distribution Protocol. Specified by <a href="http://tools.ietf.org/html/rfc3036">RFC 3036</a>.
+ */
+ LDP,
+ /**
+ * Resource Reservation Protocol - Traffic Engineering. Specified by
+ * <a href="http://tools.ietf.org/html/rfc3209">RFC 3209</a>.
+ */
+ RSVPTE
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+public interface NetworkAddressRouterIdentifier<T extends NetworkAddress<?>> extends RouterIdentifier {
+ public T getAddress();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+
+/**
+ *
+ * A single link in network topology. Network link is a connecting line between
+ * two network nodes with bunch of attributes.
+ */
+public interface NetworkLink extends NetworkObject<LinkIdentifier> {
+ @Override
+ public NetworkLinkState currentState();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.bgp.linkstate.AdministrativeGroup;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.MPLSProtocol;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLink;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+
+/**
+ * Implementation of {@link NetworkLink}
+ */
+public final class NetworkLinkImpl extends NetworkObjectImpl<LinkIdentifier> implements NetworkLink {
+ private static final long serialVersionUID = 5203163596015262211L;
+
+ /**
+ *
+ * @param name
+ * {@link LinkIdentifier}
+ */
+ public NetworkLinkImpl(final LinkIdentifier name) {
+ this(name, NetworkLinkState.EMPTY);
+ }
+
+ /**
+ *
+ * @param name {@link LinkIdentifier}
+ * @param template {@link NetworkLink}
+ */
+ public NetworkLinkImpl(final LinkIdentifier name, final NetworkLinkState state) {
+ super(name, state);
+ }
+
+ @Override
+ public NetworkLinkState currentState() {
+ return (NetworkLinkState) super.currentState();
+ }
+
+ /**
+ *
+ * @param administrativeGroup
+ * {@link AdministrativeGroup}
+ */
+ @Deprecated
+ public synchronized void setAdministrativeGroup(final AdministrativeGroup administrativeGroup) {
+ this.state = currentState().withAdministrativeGroup(administrativeGroup);
+ }
+
+ /**
+ *
+ * @param maximumBandwidth
+ * {@link Bandwidth}
+ */
+ @Deprecated
+ public synchronized void setMaximumBandwidth(final Bandwidth maximumBandwidth) {
+ this.state = currentState().withMaximumBandwidth(maximumBandwidth);
+ }
+
+ /**
+ *
+ * @param reservableBandwidth
+ * {@link Bandwidth}
+ */
+ @Deprecated
+ public synchronized void setMaximumReservableBandwidth(final Bandwidth reservableBandwidth) {
+ this.state = currentState().withReservableBandwidth(reservableBandwidth);
+ }
+
+ /**
+ *
+ * @param unreservedBandwidth
+ * array of {@link Bandwidth}
+ */
+ @Deprecated
+ public synchronized void setUnreservedBandwidth(final Bandwidth[] unreservedBandwidth) {
+ this.state = currentState().withUnreservedBandwidth(unreservedBandwidth);
+ }
+
+ /**
+ *
+ * @param protectionType
+ * {@link LinkProtectionType}
+ */
+ @Deprecated
+ public synchronized void setProtectionType(final LinkProtectionType protectionType) {
+ this.state = currentState().withProtectionType(protectionType);
+ }
+
+ /**
+ *
+ * @param enabledMPLSProtocols
+ * set of {@link MPLSProtocol}
+ */
+ @Deprecated
+ public synchronized void setEnabledMPLSProtocols(final Set<MPLSProtocol> enabledMPLSProtocols) {
+ this.state = currentState().withEnabledMPLSProtocols(enabledMPLSProtocols);
+ }
+
+ /**
+ *
+ * @param sharedRiskLinkGroups
+ * set of {@link SharedRiskLinkGroup}
+ */
+ @Deprecated
+ public synchronized void setSharedRiskLinkGroups(final Set<SharedRiskLinkGroup> sharedRiskLinkGroups) {
+ this.state = currentState().withSharedRiskLinkGroups(sharedRiskLinkGroups);
+ }
+
+ /**
+ *
+ * @param <T>
+ * metric
+ * @param metric
+ * T
+ */
+ @Deprecated
+ public synchronized <T extends Metric<?>> void setDefaultMetric(final T metric) {
+ this.state = currentState().withDefaultMetric(metric);
+ }
+
+ /**
+ *
+ * @param <T> metric
+ * @param metricType class
+ * @param metric T
+ */
+ @Deprecated
+ public synchronized <T extends Metric<T>> void setMetric(final Class<T> metricType, final T metric) {
+ this.state = currentState().withMetric(metricType, metric);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.bgp.linkstate.AdministrativeGroup;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.MPLSProtocol;
+import org.opendaylight.protocol.util.DefaultingTypesafeContainer;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ *
+ * A single link in network topology. Network link is a connecting line between two network nodes with bunch of
+ * attributes.
+ */
+public final class NetworkLinkState extends NetworkObjectState {
+ public static final NetworkLinkState EMPTY = new NetworkLinkState();
+ private static final long serialVersionUID = 1L;
+ private final DefaultingTypesafeContainer<Metric<?>> metrics;
+ private Set<SharedRiskLinkGroup> sharedRiskLinkGroups;
+ private AdministrativeGroup administrativeGroup;
+ private Set<MPLSProtocol> enabledMPLSProtocols;
+ private LinkProtectionType protectionType;
+ private Bandwidth[] unreservedBandwidth;
+ private Bandwidth reservableBandwidth;
+ private Bandwidth maximumBandwidth;
+ private String symbolicName;
+
+ private NetworkLinkState() {
+ this(NetworkObjectState.EMPTY, new DefaultingTypesafeContainer<Metric<?>>(), null, LinkProtectionType.UNPROTECTED, null, null, null);
+ }
+
+ public NetworkLinkState(final NetworkObjectState orig, final DefaultingTypesafeContainer<Metric<?>> metrics,
+ final Set<SharedRiskLinkGroup> sharedRiskLinkGroups, final AdministrativeGroup administrativeGroup,
+ final Set<MPLSProtocol> enabledMPLSProtocols, final LinkProtectionType protectionType, final String symbolicName,
+ final Bandwidth[] unreservedBandwidth, final Bandwidth reservableBandwidth, final Bandwidth maximumBandwidth) {
+ super(orig);
+ this.metrics = Preconditions.checkNotNull(metrics, "Metric is mandatory.");
+ this.sharedRiskLinkGroups = sharedRiskLinkGroups;
+ this.administrativeGroup = administrativeGroup;
+ this.enabledMPLSProtocols = enabledMPLSProtocols;
+ this.protectionType = Preconditions.checkNotNull(protectionType);
+ this.symbolicName = symbolicName;
+ this.unreservedBandwidth = unreservedBandwidth;
+ this.reservableBandwidth = reservableBandwidth;
+ this.maximumBandwidth = maximumBandwidth;
+ }
+
+ public NetworkLinkState(final NetworkObjectState orig, final DefaultingTypesafeContainer<Metric<?>> metrics,
+ final AdministrativeGroup administrativeGroup, final LinkProtectionType protectionType, final Bandwidth[] unreservedBandwidth,
+ final Bandwidth reservableBandwidth, final Bandwidth maximumBandwidth) {
+ this(orig, metrics, Collections.<SharedRiskLinkGroup> emptySet(), administrativeGroup, Collections.<MPLSProtocol> emptySet(), protectionType,
+ null, unreservedBandwidth, reservableBandwidth, maximumBandwidth);
+ }
+
+ protected NetworkLinkState(final NetworkLinkState orig) {
+ super(orig);
+ this.metrics = orig.metrics;
+ this.sharedRiskLinkGroups = orig.sharedRiskLinkGroups;
+ this.administrativeGroup = orig.administrativeGroup;
+ this.enabledMPLSProtocols = orig.enabledMPLSProtocols;
+ this.protectionType = orig.protectionType;
+ this.symbolicName = orig.symbolicName;
+ this.unreservedBandwidth = orig.unreservedBandwidth;
+ this.reservableBandwidth = orig.reservableBandwidth;
+ this.maximumBandwidth = orig.maximumBandwidth;
+ }
+
+ @Override
+ protected NetworkLinkState newInstance() {
+ return new NetworkLinkState(this);
+ }
+
+ /**
+ * Get AdministrativeGroup attribute of network link {@link AdministrativeGroup}.
+ *
+ * @return AdministrativeGroup of network link.
+ */
+ public final AdministrativeGroup getAdministrativeGroup() {
+ return this.administrativeGroup;
+ }
+
+ public final NetworkLinkState withAdministrativeGroup(final AdministrativeGroup administrativeGroup) {
+ final NetworkLinkState ret = newInstance();
+ ret.administrativeGroup = administrativeGroup;
+ return ret;
+ }
+
+ /**
+ * Get maximum bandwidth attribute of network link {@link Bandwidth}.
+ *
+ * @return Bandwidth maximum bandwidth of network link.
+ */
+ public final Bandwidth getMaximumBandwidth() {
+ return this.maximumBandwidth;
+ }
+
+ public final NetworkLinkState withMaximumBandwidth(final Bandwidth maximumBandwidth) {
+ final NetworkLinkState ret = newInstance();
+ ret.maximumBandwidth = maximumBandwidth;
+ return ret;
+ }
+
+ /**
+ * Get maximum reservable bandwidth attribute of network link {@link Bandwidth}.
+ *
+ * @return Bandwidth maximum reservable bandwidth of network link.
+ */
+ public final Bandwidth getMaximumReservableBandwidth() {
+ return this.reservableBandwidth;
+ }
+
+ public final NetworkLinkState withReservableBandwidth(final Bandwidth reservableBandwidth) {
+ final NetworkLinkState ret = newInstance();
+ ret.reservableBandwidth = reservableBandwidth;
+ return ret;
+ }
+
+ /**
+ * Get unreserved bandwidth attribute of network link {@link Bandwidth}.
+ *
+ * @return Bandwidth[] unreserved bandwidth of network link.
+ */
+ public final Bandwidth[] getUnreservedBandwidth() {
+ return this.unreservedBandwidth;
+ }
+
+ public final NetworkLinkState withUnreservedBandwidth(final Bandwidth[] unreservedBandwidth) {
+ Preconditions.checkNotNull(unreservedBandwidth);
+ Preconditions.checkArgument(unreservedBandwidth.length == 8);
+
+ final NetworkLinkState ret = newInstance();
+ ret.unreservedBandwidth = unreservedBandwidth;
+ return ret;
+ }
+
+ /**
+ * Get link protection type attribute of network link {@link LinkProtectionType}.
+ *
+ * @return LinkProtectionType of network link.
+ */
+ public final LinkProtectionType getProtectionType() {
+ return this.protectionType;
+ }
+
+ public final NetworkObjectState withProtectionType(final LinkProtectionType protectionType) {
+ final NetworkLinkState ret = newInstance();
+ ret.protectionType = protectionType;
+ return ret;
+ }
+
+ /**
+ * Get set of enabled MPLSProtocols of network link {@link MPLSProtocol}.
+ *
+ * @return Set<MPLSProtocol> enabled MPLSProtocols of network link.
+ */
+ public final Set<MPLSProtocol> getEnabledMPLSProtocols() {
+ return this.enabledMPLSProtocols;
+ }
+
+ public final NetworkLinkState withEnabledMPLSProtocols(final Set<MPLSProtocol> enabledMPLSProtocols) {
+ final NetworkLinkState ret = newInstance();
+ ret.enabledMPLSProtocols = enabledMPLSProtocols;
+ return ret;
+ }
+
+ /**
+ * Get set of SharedRiskLinkGroups of network link {@link SharedRiskLinkGroup}.
+ *
+ * @return Set<SharedRiskLinkGroup> shared risk link groups of network link.
+ */
+ public final Set<SharedRiskLinkGroup> getSharedRiskLinkGroups() {
+ return this.sharedRiskLinkGroups;
+ }
+
+ public final NetworkLinkState withSharedRiskLinkGroups(final Set<SharedRiskLinkGroup> sharedRiskLinkGroups) {
+ Preconditions.checkNotNull(sharedRiskLinkGroups);
+ final NetworkLinkState ret = newInstance();
+ ret.sharedRiskLinkGroups = sharedRiskLinkGroups;
+ return ret;
+ }
+
+ /**
+ * Get default Metric attribute of network link {@link Metric}.
+ *
+ * @return default Metric of network link.
+ */
+ public final Metric<?> getDefaultMetric() {
+ return this.metrics.getDefaultEntry();
+ }
+
+ public final <T extends Metric<?>> NetworkLinkState withDefaultMetric(final T metric) {
+ // FIXME: this violates API contract of State!
+ this.metrics.setDefaultEntry(metric);
+ return this;
+ }
+
+ /**
+ * Get metric attribute of submitted metric type of network link {@link Metric}.
+ *
+ * @param <T> sub-type of metric.
+ * @param metricType which value should be returned.
+ * @return metric of submitted type of network link.
+ */
+ public final <T extends Metric<?>> T getMetric(final Class<? extends T> metricType) {
+ return this.metrics.getEntry(metricType);
+ }
+
+ public final <T extends Metric<T>> NetworkLinkState withMetric(final Class<T> metricType, final T metric) {
+ // FIXME: this violates API contract of State!
+ this.metrics.setEntry(metricType, metric);
+ return this;
+ }
+
+ public final String getSymbolicName() {
+ return this.symbolicName;
+ }
+
+ public final NetworkLinkState withSymbolicName(final String symbolicName) {
+ final NetworkLinkState ret = newInstance();
+ ret.symbolicName = symbolicName;
+ return ret;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("metrics", this.metrics);
+ toStringHelper.add("SRLGs", this.sharedRiskLinkGroups);
+ toStringHelper.add("administrativeGroup", this.administrativeGroup);
+ toStringHelper.add("enabledMPLSProtocols", this.enabledMPLSProtocols);
+ toStringHelper.add("protectionType", this.protectionType);
+ toStringHelper.add("unreservedBandwidth", this.unreservedBandwidth);
+ toStringHelper.add("reservableBandwidth", this.reservableBandwidth);
+ toStringHelper.add("maximumBandwidth", this.maximumBandwidth);
+ toStringHelper.add("symbolicName", this.symbolicName);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.administrativeGroup == null) ? 0 : this.administrativeGroup.hashCode());
+ result = prime * result + ((this.enabledMPLSProtocols == null) ? 0 : this.enabledMPLSProtocols.hashCode());
+ result = prime * result + ((this.maximumBandwidth == null) ? 0 : this.maximumBandwidth.hashCode());
+ result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+ result = prime * result + ((this.protectionType == null) ? 0 : this.protectionType.hashCode());
+ result = prime * result + ((this.symbolicName == null) ? 0 : this.symbolicName.hashCode());
+ result = prime * result + ((this.reservableBandwidth == null) ? 0 : this.reservableBandwidth.hashCode());
+ result = prime * result + ((this.sharedRiskLinkGroups == null) ? 0 : this.sharedRiskLinkGroups.hashCode());
+ result = prime * result + Arrays.hashCode(this.unreservedBandwidth);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final NetworkLinkState other = (NetworkLinkState) obj;
+ if (this.administrativeGroup == null) {
+ if (other.administrativeGroup != null)
+ return false;
+ } else if (!this.administrativeGroup.equals(other.administrativeGroup))
+ return false;
+ if (this.enabledMPLSProtocols == null) {
+ if (other.enabledMPLSProtocols != null)
+ return false;
+ } else if (!this.enabledMPLSProtocols.equals(other.enabledMPLSProtocols))
+ return false;
+ if (this.maximumBandwidth == null) {
+ if (other.maximumBandwidth != null)
+ return false;
+ } else if (!this.maximumBandwidth.equals(other.maximumBandwidth))
+ return false;
+ if (this.metrics == null) {
+ if (other.metrics != null)
+ return false;
+ } else if (!this.metrics.equals(other.metrics))
+ return false;
+ if (this.symbolicName == null) {
+ if (other.symbolicName != null)
+ return false;
+ } else if (!this.symbolicName.equals(other.symbolicName))
+ return false;
+ if (this.protectionType != other.protectionType)
+ return false;
+ if (this.reservableBandwidth == null) {
+ if (other.reservableBandwidth != null)
+ return false;
+ } else if (!this.reservableBandwidth.equals(other.reservableBandwidth))
+ return false;
+ if (this.sharedRiskLinkGroups == null) {
+ if (other.sharedRiskLinkGroups != null)
+ return false;
+ } else if (!this.sharedRiskLinkGroups.equals(other.sharedRiskLinkGroups))
+ return false;
+ if (!Arrays.equals(this.unreservedBandwidth, other.unreservedBandwidth))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+
+/**
+ * A single (router) node in the network topology. Nodes are interconnected by links and have a bunch of attributes. One
+ * of the key attributes is the set of prefixes for which this node acts as a network edge router.
+ */
+public interface NetworkNode extends NetworkObject<NodeIdentifier> {
+ @Override
+ public NetworkNodeState currentState();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNode;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+
+/**
+ * Implementation of {@link NetworkNode}
+ */
+public class NetworkNodeImpl extends NetworkObjectImpl<NodeIdentifier> implements NetworkNode {
+ private static final long serialVersionUID = -7999816386632869087L;
+
+ /**
+ *
+ * @param name {@link NodeIdentifier}
+ */
+ public NetworkNodeImpl(final NodeIdentifier name) {
+ this(name, NetworkNodeState.EMPTY);
+ }
+
+ /**
+ *
+ * @param name {@link NodeIdentifier}
+ * @param template {@link NetworkNode}
+ */
+ public NetworkNodeImpl(final NodeIdentifier name, final NetworkNodeState state) {
+ super(name, state);
+ }
+
+ /**
+ * Standard setter for NetworkNode identifierAlterinatives attribute.
+ *
+ * @param identifierAlternatives a set of all alternatives, has to include the primary identifier.
+ */
+ @Deprecated
+ public synchronized void setAlternativeIdentifiers(final Set<RouterIdentifier> identifierAlternatives) {
+ this.state = currentState().withIdentifierAlternatives(identifierAlternatives);
+ }
+
+ /**
+ * Standard setter for NetworkNode topologyMembership attribute.
+ *
+ * @param topologyMembership map of {@link TopologyIdentifier} and {@link TopologyNodeInformation}
+ */
+ @Deprecated
+ public synchronized void setTopologyMembership(final Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership) {
+ this.state = currentState().withTopologyMembership(topologyMembership);
+ }
+
+ /**
+ * Standard setter for NetworkNode areaMembership attribute.
+ *
+ * @param areaMembership set of {@link NodeAreaIdentifier}
+ */
+ @Deprecated
+ public synchronized void setAreaMembership(final Set<ISISAreaIdentifier> areaMembership) {
+ this.state = currentState().withAreaMembership(areaMembership);
+ }
+
+ /**
+ * Standard setter for NetworkNode isAreaBorderRouter attribute.
+ *
+ * @param isAreaBorderRouter boolean
+ */
+ @Deprecated
+ public synchronized void setAreaBorderRouter(final boolean isAreaBorderRouter) {
+ this.state = currentState().withAreaBorderRouter(isAreaBorderRouter);
+ }
+
+ /**
+ * Standard setter for NetworkNode isExternal attribute.
+ *
+ * @param isExternal boolean
+ */
+ @Deprecated
+ public synchronized void setExternal(final boolean isExternal) {
+ this.state = currentState().withExternal(isExternal);
+ }
+
+ /**
+ *
+ * @param value hostName
+ */
+ @Deprecated
+ public synchronized void setDynamicHostname(final String value) {
+ this.state = currentState().withDynamicHostname(value);
+ }
+
+ @Override
+ public synchronized NetworkNodeState currentState() {
+ return (NetworkNodeState) super.currentState();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * A single (router) node in the network topology. Nodes are interconnected by links and have a bunch of attributes. One
+ * of the key attributes is the set of prefixes for which this node acts as a network edge router.
+ */
+public class NetworkNodeState extends NetworkObjectState {
+ public static final NetworkNodeState EMPTY = new NetworkNodeState();
+ private static final long serialVersionUID = 1L;
+ private Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership;
+ private Set<ISISAreaIdentifier> areaMembership;
+ private boolean areaBorderRouter;
+ private boolean external;
+ private Set<RouterIdentifier> identifierAlternatives;
+ private String dynamicHostName;
+
+ private NetworkNodeState() {
+ this(NetworkObjectState.EMPTY, Collections.<TopologyIdentifier, TopologyNodeInformation> emptyMap(), Collections.<ISISAreaIdentifier> emptySet(), false, false, Collections.<RouterIdentifier> emptySet(), null);
+ }
+
+ public NetworkNodeState(final NetworkObjectState orig, final Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership,
+ final Set<ISISAreaIdentifier> areaMembership, final boolean areaBorderRouter, final boolean external,
+ final Set<RouterIdentifier> identifierAlternatives, final String dynamicHostName) {
+ super(orig);
+ Preconditions.checkNotNull(areaMembership);
+ Preconditions.checkNotNull(identifierAlternatives);
+ Preconditions.checkNotNull(topologyMembership);
+ this.topologyMembership = topologyMembership;
+ this.areaMembership = areaMembership;
+ this.areaBorderRouter = areaBorderRouter;
+ this.external = external;
+ this.identifierAlternatives = identifierAlternatives;
+ this.dynamicHostName = dynamicHostName;
+ }
+
+ protected NetworkNodeState(final NetworkNodeState orig) {
+ super(orig);
+ this.topologyMembership = orig.topologyMembership;
+ this.areaMembership = orig.areaMembership;
+ this.areaBorderRouter = orig.areaBorderRouter;
+ this.external = orig.external;
+ this.identifierAlternatives = orig.identifierAlternatives;
+ this.dynamicHostName = orig.dynamicHostName;
+ }
+
+ /**
+ * Get the per-topology information about this node.
+ *
+ * @return An immutable map of per-topology state information
+ */
+ public final Map<TopologyIdentifier, TopologyNodeInformation> getTopologyMembership() {
+ return this.topologyMembership;
+ }
+
+ public final NetworkNodeState withTopologyMembership(final Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership) {
+ final NetworkNodeState ret = newInstance();
+ ret.topologyMembership = Collections.unmodifiableMap(topologyMembership);
+ return ret;
+ }
+
+ /**
+ * Get area membership information.
+ *
+ * @return An immutable set containing identifiers of all node area this node is member of.
+ */
+ public final Set<ISISAreaIdentifier> getAreaMembership() {
+ return this.areaMembership;
+ }
+
+ public final NetworkNodeState withAreaMembership(final Set<ISISAreaIdentifier> areaMembership) {
+ final NetworkNodeState ret = newInstance();
+ ret.areaMembership = Collections.unmodifiableSet(areaMembership);
+ return ret;
+ }
+
+ /**
+ * Get ABR flag value. Area Border Routers (e.g. routers connected to multiple areas) advertise this flag.
+ *
+ * @return True if this router is an ABR.
+ */
+ public final boolean isAreaBorderRouter() {
+ return this.areaBorderRouter;
+ }
+
+ public final NetworkNodeState withAreaBorderRouter(final boolean value) {
+ final NetworkNodeState ret = newInstance();
+ ret.areaBorderRouter = value;
+ return ret;
+ }
+
+ /**
+ * Get external flag value. This corresponds to <a href="http://tools.ietf.org/html/rfc2328">RFC 2328</a> definition
+ * of ExternalRoutingCapability. It is advertized by all routers connected to external ASes.
+ *
+ * @return True if the router is an AS-border router
+ */
+ public final boolean isExternal() {
+ return this.external;
+ }
+
+ public final NetworkNodeState withExternal(final boolean value) {
+ final NetworkNodeState ret = newInstance();
+ ret.external = value;
+ return ret;
+ }
+
+ /**
+ * http://tools.ietf.org/html/rfc5301#section-3, encoded as a String. The string is guaranteed to contain US-ASCII
+ * characters.
+ *
+ * @return dynamic hostname of the router that is connected
+ */
+ public final String getDynamicHostname() {
+ return this.dynamicHostName;
+ }
+
+ public final NetworkNodeState withDynamicHostname(final String value) {
+ Preconditions.checkNotNull(value);
+ Preconditions.checkArgument(value.length() >= 1);
+ Preconditions.checkArgument(value.length() <= 255);
+ Preconditions.checkArgument(CharMatcher.ASCII.matchesAllOf(value));
+
+ final NetworkNodeState ret = newInstance();
+ ret.dynamicHostName = value;
+ return ret;
+ }
+
+ /**
+ * Return the set of alternative identifiers to which this node responds. This set must contain the primary
+ * identifier.
+ *
+ * @return set of identifier alternatives.
+ */
+ public final Set<RouterIdentifier> getIdentifierAlternatives() {
+ return this.identifierAlternatives;
+ }
+
+ public final NetworkNodeState withIdentifierAlternatives(final Set<RouterIdentifier> identifierAlternatives) {
+ final NetworkNodeState ret = newInstance();
+ ret.identifierAlternatives = identifierAlternatives;
+ return ret;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("topologyMembership", this.topologyMembership);
+ toStringHelper.add("areaMembership", this.areaMembership);
+ toStringHelper.add("external", this.external);
+ toStringHelper.add("ABR", this.areaBorderRouter);
+ toStringHelper.add("dynamicHostname", this.dynamicHostName);
+ toStringHelper.add("routerIdentifiers", this.identifierAlternatives);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ protected NetworkNodeState newInstance() {
+ return new NetworkNodeState(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.io.Serializable;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.NamedObject;
+import org.opendaylight.protocol.concepts.Stateful;
+
+/**
+ * Class representing an generic object living in a network. Each such object
+ * has a name which uniquely identifies it in a particular network. Further
+ * generic attributes provide view into how a particular object has been tagged
+ * in BGP world.
+ *
+ * @param <T>
+ */
+public interface NetworkObject<T extends Identifier> extends NamedObject<T>, Serializable, Stateful<NetworkObjectState> {
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObject;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Implementation of {@link NetworkObject}
+ *
+ * @param <T> {@link Identifier} type
+ */
+public class NetworkObjectImpl<T extends Identifier> implements NetworkObject<T> {
+ private static final long serialVersionUID = 1L;
+ private final T name;
+ protected NetworkObjectState state;
+
+ /**
+ *
+ * @param name
+ */
+ public NetworkObjectImpl(final T name) {
+ this(name, NetworkObjectState.EMPTY);
+ }
+
+ /**
+ *
+ * @param name T
+ * @param template T
+ */
+ public NetworkObjectImpl(final T name, final NetworkObjectState state) {
+ Preconditions.checkNotNull(name);
+ Preconditions.checkNotNull(state);
+ this.name = name;
+ this.state = state;
+ }
+
+ @Override
+ public final T getName() {
+ return this.name;
+ }
+
+ /**
+ * Standard setter for NetworkObject asPath attribute.
+ *
+ * @param asPath
+ * {@link ASPath}
+ */
+ public final synchronized void setASPath(final ASPath asPath) {
+ this.state = state.withASPath(asPath);
+ }
+
+ /**
+ * Standard setter for NetworkObject communities attribute.
+ *
+ * @param communities
+ * {@link Community}
+ */
+ public final synchronized void setCommunities(final Set<Community> communities) {
+ this.state = state.withCommunities(Collections.unmodifiableSet(communities));
+ }
+
+ /**
+ * Standard setter for NetworkObject extendedCommunities attribute.
+ *
+ * @param extendedCommunities
+ * {@link ExtendedCommunity}
+ */
+ public final synchronized void setExtendedCommunities(
+ final Set<ExtendedCommunity> extendedCommunities) {
+ this.state = state.withExtendedCommunities(Collections.unmodifiableSet(extendedCommunities));
+ }
+
+ @Override
+ public synchronized final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("name", name);
+ toStringHelper.add("state", state);
+ return toStringHelper;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof NetworkObjectImpl))
+ return false;
+ final NetworkObjectImpl<?> other = (NetworkObjectImpl<?>) obj;
+ if (this.name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!this.name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public synchronized NetworkObjectState currentState() {
+ return state;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+
+import org.opendaylight.protocol.concepts.State;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Class representing state of a generic object living somewhere in the network. Each such object has potentially
+ * arrived through BGP-like inter-domain distribution channel and thus contains equivalent tags -- which may be empty.
+ */
+public class NetworkObjectState implements State {
+ public static final NetworkObjectState EMPTY = new NetworkObjectState();
+ private static final long serialVersionUID = 1L;
+ private Set<ExtendedCommunity> extendedCommunities;
+ private Set<Community> communities;
+ private ASPath asPath;
+
+ protected NetworkObjectState() {
+ this(ASPath.EMPTY, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+ }
+
+ public NetworkObjectState(final ASPath asPath, final Set<Community> communities, final Set<ExtendedCommunity> extendedCommunities) {
+ this.asPath = asPath;
+ this.communities = communities;
+ this.extendedCommunities = extendedCommunities;
+ }
+
+ protected NetworkObjectState(final NetworkObjectState orig) {
+ this.asPath = orig.asPath;
+ this.communities = orig.communities;
+ this.extendedCommunities = orig.extendedCommunities;
+ }
+
+ /**
+ * Get the AS path from the local network to the object. This may be null if the installing source has no idea about
+ * ASes, as would be the case of network nodes learned from an IGP.
+ *
+ * @return Path to the advertising Autonomous System.
+ */
+ public final ASPath getASPath() {
+ return this.asPath;
+ }
+
+ public final NetworkObjectState withASPath(final ASPath asPath) {
+ final NetworkObjectState ret = newInstance();
+ ret.asPath = asPath;
+ return ret;
+ }
+
+ /**
+ * Get BGP communities associated with this object. If this object has no RFC1997 extended communities attached, the
+ * returned set will be empty.
+ *
+ * @return A set of RFC1997 communities.
+ */
+ public final Set<Community> getCommunities() {
+ return this.communities;
+ }
+
+ public final NetworkObjectState withCommunities(final Set<Community> communities) {
+ final NetworkObjectState ret = newInstance();
+ ret.communities = communities;
+ return ret;
+ }
+
+ /**
+ * Get BGP communities associated with this object. If this object has no RFC4360 extended communities attached, the
+ * returned set will be empty.
+ *
+ * @return A set of RFC4360 extended communities.
+ */
+ public final Set<ExtendedCommunity> getExtendedCommunities() {
+ return this.extendedCommunities;
+ }
+
+ public final NetworkObjectState withExtendedCommunities(final Set<ExtendedCommunity> extendedCommunities) {
+ final NetworkObjectState ret = newInstance();
+ ret.extendedCommunities = extendedCommunities;
+ return ret;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("ASPath", this.asPath);
+ toStringHelper.add("communities", this.communities);
+ toStringHelper.add("extendedCommunities", this.extendedCommunities);
+ return toStringHelper;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.asPath == null) ? 0 : this.asPath.hashCode());
+ result = prime * result + ((this.communities == null) ? 0 : this.communities.hashCode());
+ result = prime * result + ((this.extendedCommunities == null) ? 0 : this.extendedCommunities.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final NetworkObjectState other = (NetworkObjectState) obj;
+ if (this.asPath == null) {
+ if (other.asPath != null)
+ return false;
+ } else if (!this.asPath.equals(other.asPath))
+ return false;
+ if (this.communities == null) {
+ if (other.communities != null)
+ return false;
+ } else if (!this.communities.equals(other.communities))
+ return false;
+ if (this.extendedCommunities == null) {
+ if (other.extendedCommunities != null)
+ return false;
+ } else if (!this.extendedCommunities.equals(other.extendedCommunities))
+ return false;
+ return true;
+ }
+
+ protected NetworkObjectState newInstance() {
+ return new NetworkObjectState(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+
+/**
+ * Generic, IGP-independent prefix advertisement.
+ * @param <T> Network Address type of the prefix
+ */
+public interface NetworkPrefix<T extends NetworkAddress<?>> extends NetworkObject<PrefixIdentifier<T>> {
+ @Override
+ public NetworkPrefixState currentState();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.bgp.linkstate.RouteTag;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Generic, IGP-independent prefix advertisement.
+ * @param <T> Network Address type of the prefix
+ */
+public class NetworkPrefixState extends NetworkObjectState {
+ public static final NetworkPrefixState EMPTY = new NetworkPrefixState();
+ private static final long serialVersionUID = 1L;
+ private SortedSet<RouteTag> routeTags;
+ private Metric<?> metric;
+
+ private NetworkPrefixState() {
+ this(NetworkObjectState.EMPTY, new TreeSet<RouteTag>(), null);
+ }
+
+ protected NetworkPrefixState(NetworkPrefixState orig) {
+ super(orig);
+ this.metric = orig.metric;
+ this.routeTags = orig.routeTags;
+ }
+
+ public NetworkPrefixState(NetworkObjectState orig, SortedSet<RouteTag> routeTags, Metric<?> metric) {
+ super(orig);
+ Preconditions.checkNotNull(routeTags);
+ this.metric = metric;
+ this.routeTags = routeTags;
+ }
+
+ /**
+ * Return the prefix metric attached to this advertisement.
+ *
+ * @return Prefix metric, possibly null
+ */
+ public final Metric<?> getPrefixMetric() {
+ return metric;
+ }
+
+ public final NetworkPrefixState withPrefixMetric(Metric<?> metric) {
+ final NetworkPrefixState ret = newInstance();
+ ret.metric = metric;
+ return ret;
+ }
+
+ /**
+ * Return the route tag attached to this advertisement.
+ *
+ * @return Route tag, possibly null
+ */
+ public final SortedSet<RouteTag> getRouteTags() {
+ return routeTags;
+ }
+
+ public final NetworkPrefixState withRouteTags(SortedSet<RouteTag> routeTags) {
+ final NetworkPrefixState ret = newInstance();
+ ret.routeTags = routeTags;
+ return ret;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("metric", metric);
+ toStringHelper.add("routeTags", routeTags);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ protected NetworkPrefixState newInstance() {
+ return new NetworkPrefixState(this);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ * A single route existing within the network. A route is a way how to get from
+ * the local node to a set of network addresses. The set of addresses is
+ * represented as a Prefix of a particular address type and is the unique
+ * identifier for the route. The routing part is represented as the
+ * directly-connected neighbor, which should be used used as a relay for traffic
+ * going to the set of addresses.
+ *
+ * @param <T>
+ */
+public interface NetworkRoute<T extends NetworkAddress<?>> extends NetworkObject<Prefix<T>> {
+ @Override
+ public NetworkRouteState<T> currentState();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Preconditions;
+
+/**
+ * A single route existing within the network. A route is a way how to get from the local node to a set of network
+ * addresses. The set of addresses is represented as a Prefix of a particular address type and is the unique identifier
+ * for the route. The routing part is represented as the directly-connected neighbor, which should be used used as a
+ * relay for traffic going to the set of addresses.
+ *
+ * @param <T>
+ */
+public final class NetworkRouteState<T extends NetworkAddress<?>> extends NetworkObjectState {
+ private static final long serialVersionUID = 1L;
+ private final NextHop<T> nextHop;
+
+ public NetworkRouteState(final NextHop<T> nextHop) {
+ this(NetworkObjectState.EMPTY, nextHop);
+ }
+
+ public NetworkRouteState(final NetworkObjectState orig, final NextHop<T> nextHop) {
+ super(orig);
+ this.nextHop = Preconditions.checkNotNull(nextHop);
+ }
+
+ protected NetworkRouteState(final NetworkRouteState<T> orig) {
+ super(orig);
+ this.nextHop = orig.nextHop;
+ }
+
+ @Override
+ protected NetworkRouteState<T> newInstance() {
+ return new NetworkRouteState<T>(this);
+ }
+
+ /**
+ * Get the relay for the set of addresses covered by this route.
+ *
+ * @return NextHop<T> next hop.
+ */
+ public NextHop<T> getNextHop() {
+ return this.nextHop;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.nextHop == null) ? 0 : this.nextHop.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final NetworkRouteState<?> other = (NetworkRouteState<?>) obj;
+ if (this.nextHop == null) {
+ if (other.nextHop != null)
+ return false;
+ } else if (!this.nextHop.equals(other.nextHop))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * A network node identifier. A network node is typically a router, a switch, or similar entity.
+ */
+public final class NodeIdentifier implements Identifier {
+ private static final long serialVersionUID = 1L;
+
+ private final ASNumber asNumber;
+ private final DomainIdentifier domainIdentifier;
+ private final AreaIdentifier areaIdentifier;
+ private final RouterIdentifier routerIdentifier;
+
+ public NodeIdentifier(final ASNumber as, final DomainIdentifier domain, final AreaIdentifier area, final RouterIdentifier router) {
+ this.routerIdentifier = Preconditions.checkNotNull(router, "Router Identifier is mandatory.");
+ this.asNumber = as;
+ this.domainIdentifier = domain;
+ this.areaIdentifier = area;
+ }
+
+ /**
+ * Return the AS number where this node resides.
+ *
+ * @return AS of residence
+ */
+ public ASNumber getAsNumber() {
+ return this.asNumber;
+ }
+
+ public DomainIdentifier getDomainIdentifier() {
+ return this.domainIdentifier;
+ }
+
+ public AreaIdentifier getAreaIdentifier() {
+ return this.areaIdentifier;
+ }
+
+ public RouterIdentifier getRouterIdentifier() {
+ return this.routerIdentifier;
+ }
+
+ @Override
+ public String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("as", this.asNumber);
+ toStringHelper.add("domain", this.domainIdentifier);
+ toStringHelper.add("area", this.areaIdentifier);
+ toStringHelper.add("router", this.routerIdentifier);
+ return toStringHelper;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.areaIdentifier == null) ? 0 : this.areaIdentifier.hashCode());
+ result = prime * result + ((this.asNumber == null) ? 0 : this.asNumber.hashCode());
+ result = prime * result + ((this.domainIdentifier == null) ? 0 : this.domainIdentifier.hashCode());
+ result = prime * result + ((this.routerIdentifier == null) ? 0 : this.routerIdentifier.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final NodeIdentifier other = (NodeIdentifier) obj;
+ if (this.areaIdentifier == null) {
+ if (other.areaIdentifier != null)
+ return false;
+ } else if (!this.areaIdentifier.equals(other.areaIdentifier))
+ return false;
+ if (this.asNumber == null) {
+ if (other.asNumber != null)
+ return false;
+ } else if (!this.asNumber.equals(other.asNumber))
+ return false;
+ if (this.domainIdentifier == null) {
+ if (other.domainIdentifier != null)
+ return false;
+ } else if (!this.domainIdentifier.equals(other.domainIdentifier))
+ return false;
+ if (this.routerIdentifier == null) {
+ if (other.routerIdentifier != null)
+ return false;
+ } else if (!this.routerIdentifier.equals(other.routerIdentifier))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+public final class NodeIdentifierFactory {
+ private final ASNumber as;
+ private final DomainIdentifier domain;
+ private final AreaIdentifier area;
+
+ public NodeIdentifierFactory(final ASNumber as, final DomainIdentifier domain, final AreaIdentifier area) {
+ this.as = as;
+ this.area = area;
+ this.domain = domain;
+ }
+
+ public NodeIdentifier identifierForRouter(final RouterIdentifier router) {
+ return new NodeIdentifier(as, domain, area, router);
+ }
+
+ public static NodeIdentifier localIdentifier(final RouterIdentifier router) {
+ return new NodeIdentifier(null, null, null, router);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An OSPFv3 interface identifier.
+ *
+ * @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.2.1.4
+ */
+public final class OSPFInterfaceIdentifier implements InterfaceIdentifier {
+ private static final long serialVersionUID = 1L;
+ private final byte[] value;
+
+ public OSPFInterfaceIdentifier(final byte[] value) {
+ Preconditions.checkNotNull(value);
+ Preconditions.checkArgument(value.length == 4);
+ this.value = value;
+ }
+
+ public byte[] getValue() {
+ return this.value;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("value", Arrays.toString(this.value));
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(this.value);
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final OSPFInterfaceIdentifier other = (OSPFInterfaceIdentifier) obj;
+ if (!Arrays.equals(this.value, other.value))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * OSPF-specific prefix prefix advertisement.
+ * @param <T> Network Address type of the prefix being advertised
+ */
+public interface OSPFNetworkPrefix<T extends NetworkAddress<?>> extends NetworkPrefix<T> {
+ @Override
+ public OSPFNetworkPrefixState<T> currentState();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * OSPF-specific prefix prefix advertisement.
+ * @param <T> Network Address type of the prefix being advertised
+ */
+public class OSPFNetworkPrefixState<T extends NetworkAddress<?>> extends NetworkPrefixState {
+ private static final long serialVersionUID = 1L;
+ private final T forwardingAddress;
+
+ protected OSPFNetworkPrefixState(OSPFNetworkPrefixState<T> orig) {
+ super(orig);
+ this.forwardingAddress = orig.forwardingAddress;
+ }
+
+ public OSPFNetworkPrefixState(NetworkPrefixState orig, T forwardingAddress) {
+ super(orig);
+ this.forwardingAddress = forwardingAddress;
+ }
+
+ /**
+ * Returns the OSPF forwarding address attached to this advertisement.
+ *
+ * @return OSPF forwarding address
+ */
+ public final T getForwardingAddress() {
+ return forwardingAddress;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("forwardingAddress", this.forwardingAddress);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * A network node identifier. A network node is typically a router, a switch, or similar entity.
+ */
+public final class OSPFPrefixIdentifier<T extends NetworkAddress<?>> extends PrefixIdentifier<T> {
+ private static final long serialVersionUID = 1L;
+ private final OSPFRouteType routeType;
+
+ public OSPFPrefixIdentifier(final NodeIdentifier owner, final Prefix<T> prefix, final OSPFRouteType routeType) {
+ super(owner, prefix);
+ this.routeType = routeType;
+ }
+
+ /**
+ * Returns OSPF Route Type.
+ *
+ * @return {@link OSPFRouteType}
+ */
+ public OSPFRouteType getRouteType() {
+ return routeType;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("routeType", routeType);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((routeType == null) ? 0 : routeType.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ OSPFPrefixIdentifier<?> other = (OSPFPrefixIdentifier<?>) obj;
+ if (routeType != other.routeType)
+ return false;
+ return true;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+/**
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2.1.4">OSPF Route Type SubTLV</a>
+ */
+public enum OSPFRouteType {
+ Intra_Area, Inter_Area, External1, External2, NSSA1, NSSA2
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * An OSPF node identifier.
+ */
+public final class OSPFRouterIdentifier implements RouterIdentifier {
+ private static final long serialVersionUID = 1L;
+ private final byte[] routerId;
+
+ /**
+ * Construct a new node identifier. Formed as the unification of component identifiers.
+ *
+ * @param routerId OSPF Router ID
+ */
+ public OSPFRouterIdentifier(final byte[] routerId) {
+ Preconditions.checkNotNull(routerId, "Router identifier may not be null");
+ // @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.2.1.4
+ Preconditions.checkArgument(routerId.length == 4, "Router identifier must be 4 bytes long");
+ this.routerId = routerId;
+ }
+
+ public byte[] getRouterId() {
+ return this.routerId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(this.routerId);
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final OSPFRouterIdentifier other = (OSPFRouterIdentifier) obj;
+ if (!Arrays.equals(this.routerId, other.routerId))
+ return false;
+ return true;
+ }
+
+ @Override
+ public final String toString() {
+ return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("routerID", Arrays.toString(this.routerId));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+
+/**
+ * An OSPFv2 LAN "pseudonode" identifier
+ * @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.2.1.4
+ */
+public final class OSPFv2LANIdentifier extends AbstractOSPFLANIdentifier<IPv4InterfaceIdentifier> {
+ private static final long serialVersionUID = 1L;
+
+ public OSPFv2LANIdentifier(final OSPFRouterIdentifier dr, final IPv4InterfaceIdentifier lanInterface) {
+ super(dr, lanInterface);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+
+/**
+ * An OSPFv3 LAN "pseudonode" identifier
+ * @see https://tools.ietf.org/html/draft-ietf-idr-ls-distribution-03#section-3.2.1.4
+ */
+public final class OSPFv3LANIdentifier extends AbstractOSPFLANIdentifier<OSPFInterfaceIdentifier> {
+ private static final long serialVersionUID = 1L;
+
+ public OSPFv3LANIdentifier(final OSPFRouterIdentifier dr, final OSPFInterfaceIdentifier lanInterface) {
+ super(dr, lanInterface);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * A network node identifier. A network node is typically a router, a switch, or similar entity.
+ */
+public class PrefixIdentifier<T extends NetworkAddress<?>> implements Identifier {
+ private static final long serialVersionUID = 1L;
+ private final NodeIdentifier owner;
+ private final Prefix<T> prefix;
+
+ public PrefixIdentifier(final NodeIdentifier owner, final Prefix<T> prefix) {
+ this.owner = Preconditions.checkNotNull(owner);
+ this.prefix = Preconditions.checkNotNull(prefix);
+ }
+
+ public final NodeIdentifier getOwner() {
+ return owner;
+ }
+
+ /**
+ * Return the Prefix.
+ *
+ * @return prefix
+ */
+ public final Prefix<T> getPrefix() {
+ return prefix;
+ }
+
+ @Override
+ public final String toString(){
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("owner", owner);
+ toStringHelper.add("prefix", prefix);
+ return toStringHelper;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((owner == null) ? 0 : owner.hashCode());
+ result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ PrefixIdentifier<?> other = (PrefixIdentifier<?>) obj;
+ if (owner == null) {
+ if (other.owner != null)
+ return false;
+ } else if (!owner.equals(other.owner))
+ return false;
+ if (prefix == null) {
+ if (other.prefix != null)
+ return false;
+ } else if (!prefix.equals(other.prefix))
+ return false;
+ return true;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.SignedBytes;
+
+public final class RouteTag implements Serializable, Comparable<RouteTag> {
+ private static final long serialVersionUID = 1L;
+ private final byte[] value;
+
+ public RouteTag(final byte[] value) {
+ Preconditions.checkNotNull(value);
+ Preconditions.checkArgument(value.length == 4);
+ this.value = value;
+ }
+
+ @Override
+ public String toString(){
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("value", value);
+ return toStringHelper;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(value);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ RouteTag other = (RouteTag) obj;
+ if (!Arrays.equals(value, other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(RouteTag o) {
+ if (o == null)
+ return 1;
+ if (o == this)
+ return 0;
+ return SignedBytes.lexicographicalComparator().compare(value, o.value);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+public interface RouterIdentifier extends Identifier {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+/**
+ * Enumeration of all protocols which may source link-state information.
+ */
+public enum SourceProtocol {
+ /**
+ * IS-IS Level 1 adjacency
+ */
+ ISISLevel1,
+ /**
+ * IS-IS Level 2 adjacency
+ */
+ ISISLevel2,
+ /**
+ * OSPF adjacency
+ */
+ OSPF,
+ /**
+ * Local run-time state. Learned by the advertising entity by
+ * seeing its directly-attached neighbors.
+ */
+ Direct,
+ /**
+ * Local configuration. Defined statically by an operator at the
+ * advertising entity.
+ */
+ Static,
+ /**
+ * Unknown source. Use this value if the others do not fit how we
+ * came by the information.
+ */
+ Unknown
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.nio.ByteBuffer;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Topology identifier. This identifier is used in multi-topology networks,
+ * e.g. when there are multiple logical network built on top of a set of
+ * physical components. Usually routing happens only within a single topology,
+ * but nodes resident in multiple topologies can act as inter-topology
+ * gateways.
+ */
+public final class TopologyIdentifier extends AbstractIdentifier<TopologyIdentifier> {
+ private static final long serialVersionUID = 8386493752725436667L;
+ private final short id;
+
+ /**
+ * Construct a new topology identifier for a numeric ID.
+ *
+ * @param id Topology identifier. Valid range is 0-4095.
+ */
+ public TopologyIdentifier(final long id) {
+ if (id < 0 || id > 4095)
+ throw new IllegalArgumentException("Invalid topology identifier");
+ this.id = (short) id;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + this.id;
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final TopologyIdentifier other = (TopologyIdentifier) obj;
+ if (this.id != other.id)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected byte[] getBytes() {
+ final ByteBuffer bb = ByteBuffer.allocate(Short.SIZE);
+ bb.putShort(this.id);
+ return bb.array();
+ }
+
+ /**
+ * Return ID attribute of Topology Identifier.
+ *
+ * @return Topology identifier
+ */
+ public short getId() {
+ return this.id;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("id", id);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import java.io.Serializable;
+
+/**
+ * Class representing per-Topology information about a Node. A node
+ * in this context is typically a router, which has a few properties
+ * which may be virtualized so as to have different values in topologies
+ * in which the node participates.
+ */
+public final class TopologyNodeInformation implements Serializable {
+ private static final long serialVersionUID = -3310738851831793539L;
+ private final boolean attached, overloaded;
+
+ /**
+ * Create a new per-topology object.
+ *
+ * @param isAttached Flag indicating the node is attached
+ * @param isOverloaded Flag indicating the node is overloaded
+ */
+ public TopologyNodeInformation(final boolean isAttached, final boolean isOverloaded) {
+ this.attached = isAttached;
+ this.overloaded = isOverloaded;
+ }
+
+ /**
+ * Check if node is attached.
+ *
+ * @return True if the node is attached
+ */
+ public boolean isAttached() {
+ return this.attached;
+ }
+
+ /**
+ * Check if the node is overloaded. An overloaded noded should
+ * not be assigned new traffic.
+ *
+ * @return True if the node experiences overload
+ */
+ public boolean isOverloaded() {
+ return this.overloaded;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.attached ? 1231 : 1237);
+ result = prime * result + (this.overloaded ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof TopologyNodeInformation))
+ return false;
+ final TopologyNodeInformation other = (TopologyNodeInformation) obj;
+ if (this.attached != other.attached)
+ return false;
+ if (this.overloaded != other.overloaded)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("TopologyNodeInformation [attached=");
+ sb.append(this.attached);
+ sb.append(", overloaded=");
+ sb.append(this.overloaded);
+ sb.append("]");
+ return sb.toString();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+public final class UniverseIdentifier extends AbstractIdentifier<UniverseIdentifier> {
+ public static final UniverseIdentifier L3_PACKET_TOPOLOGY = new UniverseIdentifier(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
+ public static final UniverseIdentifier L1_OPTICAL_TOPOLOGY = new UniverseIdentifier(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 });
+
+ private static final long serialVersionUID = 1L;
+ private final byte[] value;
+
+ public UniverseIdentifier(final byte[] value) {
+ this.value = value;
+ }
+
+ @Override
+ protected byte[] getBytes() {
+ return value;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("value", ByteArray.toHexString(value, "."));
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+/**
+ * Identifier class for Unnumbered Links, as defined by
+ * <a href="http://tools.ietf.org/html/rfc4202">RFC 4202</a>. Note that the
+ * class naming is a deliberate misnomer.
+ */
+public final class UnnumberedLinkIdentifier implements Comparable<UnnumberedLinkIdentifier>, InterfaceIdentifier {
+ private static final long serialVersionUID = -8301403294494612786L;
+ private final long value;
+
+ /**
+ * Create a new unnumbered link identifier.
+ *
+ * @param value Raw link identifier, has to be in range 1-4294967295
+ * @throws IllegalArgumentException when value is outside of allowed range
+ */
+ public UnnumberedLinkIdentifier(final long value) {
+ if (value < 1 || value > 4294967295L)
+ throw new IllegalArgumentException("Unsupported identifier value");
+ this.value = value;
+ }
+
+ /**
+ * Returns raw link identifier value.
+ *
+ * @return value Raw link identifier value
+ */
+ public long getValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (this.value ^ (this.value >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final UnnumberedLinkIdentifier other = (UnnumberedLinkIdentifier) obj;
+ if (this.value != other.value)
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(final UnnumberedLinkIdentifier other) {
+ if (this == other)
+ return 0;
+ if (other == null)
+ return 1;
+ if (this.value < other.value)
+ return -1;
+ if (this.value > other.value)
+ return 1;
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("UnnumberedLinkIdentifier [value=");
+ builder.append(this.value);
+ builder.append("]");
+ return builder.toString();
+ }
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.hamcrest.core.IsNot.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class AdministrativeGroupTest {
+
+ @Test
+ public void testOverflows() {
+ try {
+ new AdministrativeGroup(-2);
+ fail("Constructor successful unexpectedly");
+ } catch(IllegalArgumentException e) {}
+ try {
+ new AdministrativeGroup(4294967296L);
+ fail("Constructor successful unexpectedly");
+ } catch(IllegalArgumentException e) {}
+ }
+
+ @Test
+ public void testGetValue() {
+ AdministrativeGroup ag = new AdministrativeGroup(12345);
+ assertEquals(12345, ag.getValue());
+ }
+
+ @Test
+ public void testHashCode() {
+ AdministrativeGroup ag1 = new AdministrativeGroup(4321);
+ AdministrativeGroup ag2 = new AdministrativeGroup(4321);
+ assertEquals(ag1.hashCode(), ag2.hashCode());
+ }
+
+ @Test
+ public void testEquals() {
+ AdministrativeGroup ag1 = new AdministrativeGroup(4321);
+ AdministrativeGroup ag2 = ag1;
+ assertEquals(ag1, ag2);
+ assertEquals(ag1, new AdministrativeGroup(4321));
+ assertNotNull(ag1);
+ assertThat(ag1, not(new Object()));
+ assertThat(ag1, not(new AdministrativeGroup(5432)));
+ assertFalse(ag1.equals(null));
+ assertFalse(ag1.equals(new Object()));
+ }
+
+ @Test
+ public void testCompareTo(){
+ AdministrativeGroup a1 = new AdministrativeGroup(10);
+ AdministrativeGroup a2 = new AdministrativeGroup(5);
+ AdministrativeGroup a3 = new AdministrativeGroup(10);
+ assertTrue(a1.compareTo(a2) > 0);
+ assertTrue(a2.compareTo(a1) < 0);
+ assertTrue(a1.compareTo(a3) == 0);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class AreaIdentifierTest {
+
+ private AreaIdentifier identifier;
+
+ @Before
+ public void init() {
+ final byte[] id = new byte[] {10,0,0,1};
+ this.identifier = new AreaIdentifier(id);
+ }
+
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testLinkAreaIdentifier() {
+ final byte[] id = new byte[] {10, 90, 13, 9, 3};
+ new AreaIdentifier(id);
+ }
+
+ @Test
+ public void testGetBytes() {
+ final byte[] id = new byte[] {10,0,0,1};
+ assertArrayEquals(id, this.identifier.getBytes());
+ }
+
+ @Test
+ public void testHashCode() {
+ final byte[] id1 = new byte[] {10,0,0,1};
+ final AreaIdentifier testIdentifier1 = new AreaIdentifier(id1);
+ assertEquals(this.identifier.hashCode(), testIdentifier1.hashCode());
+
+ final byte[] id2 = new byte[] {10,0,0,2};
+ final AreaIdentifier testIdentifier2 = new AreaIdentifier(id2);
+ assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+ }
+
+ @Test
+ public void testEquals() {
+ assertThat(this.identifier, not(new Object()));
+
+ final byte[] id = new byte[] {10,0,0,1};
+ final AreaIdentifier testIdentifier = new AreaIdentifier(id);
+ assertEquals(this.identifier, testIdentifier);
+ }
+
+ @Test
+ public void testCompareTo() {
+ final byte[] id1 = new byte[] {10,0,0,1};
+ final AreaIdentifier testIdentifier1 = new AreaIdentifier(id1);
+ assertEquals(0, this.identifier.compareTo(testIdentifier1));
+
+ final byte[] id2 = new byte[] {10,0,0,2};
+ final AreaIdentifier testIdentifier2 = new AreaIdentifier(id2);
+ assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+ }
+
+ @Test
+ public void testToString(){
+ final byte[] id1 = new byte[] {10,0,0,1};
+ final AreaIdentifier l1 = new AreaIdentifier(id1);
+ final String s1 = "AreaIdentifier{id=0a.00.00.01}";
+ assertEquals(s1, l1.toString());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ISISAreaIdentifierTest {
+
+ private ISISAreaIdentifier identifier;
+
+ @Before
+ public void init() {
+ final byte[] id = new byte[] { 10, 0, 0, 1 };
+ this.identifier = new ISISAreaIdentifier(id);
+ }
+
+ @Test
+ public void testOverflows() {
+ try {
+ new ISISAreaIdentifier(new byte[] {});
+ fail("Constructor successful unexpectedly");
+ } catch (final IllegalArgumentException e) {
+ }
+ try {
+ new ISISAreaIdentifier(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2 });
+ fail("Constructor successful unexpectedly");
+ } catch (final IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testGetBytes() {
+ assertArrayEquals(new byte[] { 10, 0, 0, 1 }, this.identifier.getBytes());
+ }
+
+ @Test
+ public void testHashCode() {
+ final byte[] id1 = new byte[] { 10, 0, 0, 1 };
+ final ISISAreaIdentifier testIdentifier1 = new ISISAreaIdentifier(id1);
+ assertEquals(testIdentifier1.hashCode(), this.identifier.hashCode());
+
+ final byte[] id2 = new byte[] { 10, 0, 0, 2 };
+ final ISISAreaIdentifier testIdentifier2 = new ISISAreaIdentifier(id2);
+ assertThat(testIdentifier2.hashCode(), not(equalTo(this.identifier.hashCode())));
+ }
+
+ @Test
+ public void testEqualsObject() {
+ assertThat(this.identifier, not(new Object()));
+
+ final byte[] id = new byte[] { 10, 0, 0, 1 };
+ final ISISAreaIdentifier testIdentifier = new ISISAreaIdentifier(id);
+ assertEquals(this.identifier, testIdentifier);
+ }
+
+ @Test
+ public void testCompareTo() {
+ final byte[] id1 = new byte[] { 10, 0, 0, 1 };
+ final ISISAreaIdentifier testIdentifier1 = new ISISAreaIdentifier(id1);
+ assertEquals(0, this.identifier.compareTo(testIdentifier1));
+
+ final byte[] id2 = new byte[] { 10, 0, 0, 2 };
+ final ISISAreaIdentifier testIdentifier2 = new ISISAreaIdentifier(id2);
+ assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testIllegalArgument() {
+ new ISISAreaIdentifier(null);
+ }
+
+ @Test
+ public void testToString() {
+ assertEquals("ISISAreaIdentifier{id=0a.00.00.01}", this.identifier.toString());
+ final ISISAreaIdentifier id = new ISISAreaIdentifier(new byte[] { 1 });
+ assertEquals("ISISAreaIdentifier{id=01}", id.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+
+public class LinkAnchorTest {
+
+ @Test
+ public void test() {
+ try {
+ new LinkAnchor(null, null);
+ } catch (final NullPointerException e) {
+ assertEquals("Can not create link anchor with null node identifier.", e.getMessage());
+ }
+
+ final LinkAnchor la1 = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new OSPFRouterIdentifier(new byte[] { 1, 2, 3, 4 })), IPv6InterfaceIdentifier.forString("2001:db8:85a3::8a2e:370:7334"));
+
+ final LinkAnchor la2 = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] {
+ 1, 2, 3, 4, 5, 6 }))), null);
+
+ final LinkAnchor la3 = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new OSPFRouterIdentifier(new byte[] { 1, 2, 3, 4 })), IPv6InterfaceIdentifier.forString("2001:db8:85a3::8a2e:370:7334"));
+
+ assertNotSame(la1, la2);
+ assertNotSame(la1.hashCode(), la2.hashCode());
+
+ assertEquals(la1, la3);
+ assertEquals(la1.toString(), la3.toString());
+ assertEquals(la1.getNodeIdentifier(), la3.getNodeIdentifier());
+
+ assertNull(la2.getInterfaceIdentifier());
+ }
+
+ @Test
+ public void testEnums() throws UnknownHostException {
+ assertEquals(MPLSProtocol.LDP.toString(), "LDP");
+ assertEquals(LinkProtectionType.ENHANCED.toString(), "ENHANCED");
+
+ final InterfaceIdentifier ii1 = new IPv6InterfaceIdentifier(new IPv6Address(InetAddress.getByName("2001:db8:85a3::8a2e:370:7334")));
+ final InterfaceIdentifier ii2 = new IPv6InterfaceIdentifier(new IPv6Address(InetAddress.getByName("2001:db8:85a3::8a2e:370:7335")));
+
+ assertEquals(-1, ((IPv6InterfaceIdentifier) ii1).compareTo((IPv6InterfaceIdentifier) ii2));
+ assertEquals(0, ((IPv6InterfaceIdentifier) ii1).compareTo((IPv6InterfaceIdentifier) ii1));
+
+ assertNotSame(ii1, ii2);
+
+ assertNotNull(((IPv6InterfaceIdentifier) ii1).getValue());
+
+ try {
+ new IPv4InterfaceIdentifier(null);
+ } catch (final NullPointerException e) {
+ assertEquals("Unsupported identifier value", e.getMessage());
+ }
+
+ try {
+ new IPv6InterfaceIdentifier(null);
+ } catch (final NullPointerException e) {
+ assertEquals("Unsupported identifier value", e.getMessage());
+ }
+
+ final InterfaceIdentifier ip1 = new IPv4InterfaceIdentifier(new IPv4Address(InetAddress.getByName("127.0.0.1")));
+ final InterfaceIdentifier ip2 = new IPv4InterfaceIdentifier(new IPv4Address(InetAddress.getByName("127.0.0.2")));
+
+ assertEquals(-1, ((IPv4InterfaceIdentifier) ip1).compareTo((IPv4InterfaceIdentifier) ip2));
+ assertEquals(0, ((IPv4InterfaceIdentifier) ip1).compareTo((IPv4InterfaceIdentifier) ip1));
+
+ assertNotSame(ip1, ip2);
+
+ assertNotNull(((IPv4InterfaceIdentifier) ip1).getValue());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4;
+
+public class LinkIdentifierTest {
+
+ @Test
+ public void test() {
+
+ final LinkAnchor a = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("12.51.8.4"))),
+ IPv4InterfaceIdentifier.forString("12.51.8.4"));
+
+ final LinkAnchor b = new LinkAnchor(NodeIdentifierFactory.localIdentifier(new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("12.51.8.10"))),
+ IPv4InterfaceIdentifier.forString("12.51.8.10"));
+
+ final LinkIdentifier l1 = new LinkIdentifier(new TopologyIdentifier(5), a, b);
+
+ final LinkIdentifier l11 = new LinkIdentifier(new TopologyIdentifier(5), a, b);
+
+ final LinkIdentifier l2 = new LinkIdentifier(new TopologyIdentifier(5), b, a);
+
+ assertNotSame(l1, l2);
+
+ assertEquals(l1, l11);
+
+ assertNotSame(l1.getLocalAnchor(), l2.getLocalAnchor());
+
+ assertEquals(l1.getLocalAnchor(), l2.getRemoteAnchor());
+
+ assertNotNull(l1.getTopology());
+
+ assertEquals(l1.hashCode(), l11.hashCode());
+
+ assertEquals(l1.toString(), l11.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+
+public class NodeIdentifierTest {
+ private final NodeIdentifierFactory f = new NodeIdentifierFactory(new ASNumber(25600, 0), null, null);
+
+ @Test
+ public void testHashCodeEquals() {
+ final NodeIdentifier id1 = this.f.identifierForRouter(new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] { 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22 })));
+ final NodeIdentifier id2 = this.f.identifierForRouter(new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] { 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22 })));
+ final NodeIdentifier id3 = this.f.identifierForRouter(new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("192.168.1.5")));
+ final NodeIdentifier id4 = this.f.identifierForRouter(new IPv6RouterIdentifier(IPv6.FAMILY.addressForString("2001:db8:85a3::8a2e:370:7334")));
+
+ assertEquals("HashCodes should be equal", id1.hashCode(), id2.hashCode());
+ assertEquals("toString should be equal", id1.toString(), id2.toString());
+ assertEquals(id1, id2);
+
+ assertNotSame(id1, id3);
+ assertNotSame(id3, id4);
+ }
+
+ @Test
+ public void testIPv4RouterIdentifier() {
+ try {
+ new IPv4RouterIdentifier(null);
+ fail("Nullable IPv4RouterIdentifier");
+ } catch (final NullPointerException e) {
+ assertEquals("Address may not be null", e.getMessage());
+ }
+
+ final IPv4RouterIdentifier ip1 = new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("127.0.0.1"));
+ final IPv4RouterIdentifier ip2 = new IPv4RouterIdentifier(IPv4.FAMILY.addressForString("127.0.0.1"));
+
+ assertEquals(ip1, ip2);
+ }
+
+ @Test
+ public void testIPv6RouterIdentifier() {
+ try {
+ new IPv6RouterIdentifier(null);
+ fail("Nullable IPv6RouterIdentifier");
+ } catch (final NullPointerException e) {
+ assertEquals("Address may not be null", e.getMessage());
+ }
+
+ final IPv6RouterIdentifier ip1 = new IPv6RouterIdentifier(IPv6.FAMILY.addressForString("2001:db8:85a3::8a2e:370:7334"));
+ final IPv6RouterIdentifier ip2 = new IPv6RouterIdentifier(IPv6.FAMILY.addressForString("2001:db8:85a3::8a2e:370:7334"));
+
+ assertEquals(ip1, ip2);
+ }
+
+ @Test
+ public void testISISRouterIdentifier() {
+ final ISISRouterIdentifier is1 = new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }));
+ final ISISRouterIdentifier is2 = new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }));
+
+ assertEquals(is1, is2);
+ }
+
+ @Test
+ public void testOSPFNodeIdentifier() {
+ try {
+ new OSPFRouterIdentifier(null);
+ fail("Nullable Router Identifier!");
+ } catch (final NullPointerException e) {
+ assertEquals("Router identifier may not be null", e.getMessage());
+ }
+
+ try {
+ new OSPFRouterIdentifier(new byte[] { 5 });
+ fail("Wrong length of OSPF Router Identifier!");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Router identifier must be 4 bytes long", e.getMessage());
+ }
+
+ final OSPFRouterIdentifier os1 = new OSPFRouterIdentifier(new byte[] { 5, 5, 5, 5 });
+ final OSPFRouterIdentifier os2 = new OSPFRouterIdentifier(new byte[] { 5, 5, 5, 5 });
+
+ assertEquals(os1, os2);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+
+public class SharedRiskLinkGroupTest {
+
+ @Test
+ public void testOverflows() {
+ try {
+ new SharedRiskLinkGroup(-2);
+ fail("Constructor successful unexpectedly");
+ } catch(IllegalArgumentException e) {}
+ try {
+ new SharedRiskLinkGroup(4294967296L);
+ fail("Constructor successful unexpectedly");
+ } catch(IllegalArgumentException e) {}
+ }
+
+ @Test
+ public void testGetValue() {
+ SharedRiskLinkGroup group = new SharedRiskLinkGroup(252);
+ assertEquals(252, group.getValue());
+ }
+
+ @Test
+ public void testHashCodeEquals() {
+ SharedRiskLinkGroup group1 = new SharedRiskLinkGroup(252);
+ SharedRiskLinkGroup group2 = new SharedRiskLinkGroup(252);
+ SharedRiskLinkGroup group3 = new SharedRiskLinkGroup(987);
+ SharedRiskLinkGroup group4 = group3;
+
+ assertThat(group1.hashCode(), equalTo(group2.hashCode()));
+ assertThat(group1.hashCode(), not(equalTo(group3.hashCode())));
+
+ assertThat(group1, equalTo(group2));
+ assertThat(group1, not(equalTo((group3))));
+ assertThat(group3, equalTo(group4));
+ assertNotNull(group1);
+ assertThat(group1, not(new Object()));
+ }
+
+ @Test
+ public void testCompareTo(){
+ SharedRiskLinkGroup s1 = new SharedRiskLinkGroup(123);
+ SharedRiskLinkGroup s2 = s1;
+ SharedRiskLinkGroup s3 = new SharedRiskLinkGroup(158);
+ assertTrue(s1.compareTo(s2) == 0);
+ assertTrue(s1.compareTo(s3) < 0);
+ assertTrue(s3.compareTo(s1) > 0);
+ }
+
+ @Test
+ public void testEquals(){
+ SharedRiskLinkGroup s1 = new SharedRiskLinkGroup(123);
+ SharedRiskLinkGroup s2 = s1;
+ SharedRiskLinkGroup s3 = new SharedRiskLinkGroup(158);
+ assertFalse(s1.equals(null));
+ assertFalse(s1.equals(new Object()));
+ assertTrue(s1.equals(s2));
+ assertFalse(s1.equals(s3));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class TopologyIdentifierTest {
+
+ private TopologyIdentifier identifier;
+
+ @Before
+ public void init() {
+ this.identifier = new TopologyIdentifier(23);
+ }
+
+ @Test
+ public void testLinkAreaIdentifier() {
+ try {
+ new TopologyIdentifier(4096);
+ } catch (final Exception e) {
+ assertTrue(e instanceof IllegalArgumentException);
+ }
+ try {
+ new TopologyIdentifier(-2);
+ } catch (final Exception e) {
+ assertTrue(e instanceof IllegalArgumentException);
+ }
+
+ }
+
+ @Test
+ public void testGetId() {
+ assertEquals(23, this.identifier.getId());
+ }
+
+ @Test
+ public void testHashCode() {
+ final TopologyIdentifier testIdentifier1 = new TopologyIdentifier(23);
+ assertEquals(this.identifier.hashCode(), testIdentifier1.hashCode());
+
+ final TopologyIdentifier testIdentifier2 = new TopologyIdentifier(24);
+ assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+ }
+
+ @Test
+ public void testEquals() {
+ assertThat(this.identifier, not(new Object()));
+
+ final TopologyIdentifier testIdentifier = new TopologyIdentifier(23);
+ assertEquals(this.identifier, testIdentifier);
+ }
+
+ @Test
+ public void testCompareTo() {
+ final TopologyIdentifier testIdentifier1 = new TopologyIdentifier(23);
+ assertEquals(0, this.identifier.compareTo(testIdentifier1));
+
+ final TopologyIdentifier testIdentifier2 = new TopologyIdentifier(34);
+ assertThat(this.identifier.compareTo(testIdentifier2), not(equalTo(0)));
+ }
+
+ @Test
+ public void testToString() {
+ assertEquals("TopologyIdentifier{id=23}", this.identifier.toString());
+ final TopologyIdentifier id = new TopologyIdentifier(3);
+ assertEquals("TopologyIdentifier{id=3}", id.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class TopologyNodeInformationTest {
+
+ @Test
+ public void test() {
+ TopologyNodeInformation nodeInfo1 = new TopologyNodeInformation(true, true);
+ TopologyNodeInformation nodeInfo2 = new TopologyNodeInformation(false, false);
+ assertTrue(nodeInfo1.isAttached());
+ assertTrue(nodeInfo1.isOverloaded());
+ assertFalse(nodeInfo2.isAttached());
+ assertFalse(nodeInfo2.isOverloaded());
+ }
+
+ @Test
+ public void testEquals(){
+ TopologyNodeInformation t1 = new TopologyNodeInformation(true, true);
+ TopologyNodeInformation t2 = t1;
+ TopologyNodeInformation t3 = new TopologyNodeInformation(true, false);
+ assertEquals(t1, t2);
+ assertEquals(t1, new TopologyNodeInformation(true, true));
+ assertFalse(t1.equals(t3));
+ assertFalse(t1.equals(null));
+ assertFalse(t1.equals(new Object()));
+ }
+
+ @Test
+ public void testHashCode(){
+ TopologyNodeInformation t1 = new TopologyNodeInformation(true, false);
+ TopologyNodeInformation t2 = new TopologyNodeInformation(true, false);
+ assertEquals(t1.hashCode(), t2.hashCode());
+ }
+
+ @Test
+ public void testToString(){
+ TopologyNodeInformation t1 = new TopologyNodeInformation(true, false);
+ String s = "TopologyNodeInformation [attached=" + t1.isAttached() + ", overloaded=" + t1.isOverloaded() + "]";
+ assertEquals(s, t1.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.linkstate;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class UnnumberedLinkIdentifierTest {
+
+ private UnnumberedLinkIdentifier unnumberedId;
+
+ @Before
+ public void init() {
+ this.unnumberedId = new UnnumberedLinkIdentifier(256);
+ }
+
+ @Test
+ public void testOverflows() {
+ try {
+ new UnnumberedLinkIdentifier(-2);
+ fail("Constructor successful unexpectedly");
+ } catch(final IllegalArgumentException e) {}
+ try {
+ new UnnumberedLinkIdentifier(4294967296L);
+ fail("Constructor successful unexpectedly");
+ } catch(final IllegalArgumentException e) {}
+ }
+
+ @Test
+ public void testGetValue() {
+ assertEquals(256L, this.unnumberedId.getValue());
+ }
+
+ /**
+ * Test hashcode(), equals(), compareTo()
+ */
+ @Test
+ public void test() {
+ final UnnumberedLinkIdentifier testId1 = this.unnumberedId;
+ final UnnumberedLinkIdentifier testId2 = new UnnumberedLinkIdentifier(256);
+ final UnnumberedLinkIdentifier testId3 = new UnnumberedLinkIdentifier(951);
+
+ assertEquals(testId1.hashCode(), testId2.hashCode());
+ assertThat(testId2.hashCode(), not(equalTo(testId3.hashCode())));
+
+ assertEquals(testId1, testId2);
+ assertEquals(testId1.toString(), testId2.toString());
+ assertThat(testId1, not(equalTo(testId3)));
+ assertEquals(this.unnumberedId, testId1);
+ assertNotNull(this.unnumberedId);
+ assertThat(this.unnumberedId, not(equalTo(new Object())));
+
+ assertEquals(0, testId1.compareTo(testId2));
+ assertEquals(0, this.unnumberedId.compareTo(testId1));
+ assertEquals(1, this.unnumberedId.compareTo(null));
+ assertThat(testId2.compareTo(testId3), not(equalTo(0)));
+ assertThat(testId3.compareTo(testId1), not(equalTo(0)));
+ }
+
+}
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-parser-api</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-parser-api</artifactId>
+ <description>BGP Parser API</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>framework</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-linkstate</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Import-Package>
+ org.opendaylight.protocol.bgp.concepts,
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.framework,
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.util,
+ com.google.common.primitives,
+ com.google.common.collect,
+ org.opendaylight.protocol.bgp.linkstate,
+ com.google.common.base,
+ com.google.guava,
+ org.slf4j,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.parser,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.version}</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-PARSER-API Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import com.google.common.base.Objects.ToStringHelper;
+
+public abstract class AbstractBGPObjectState<T extends NetworkObjectState> extends BaseBGPObjectState {
+ private static final long serialVersionUID = 1L;
+ private final T objectState;
+
+ public AbstractBGPObjectState(final BaseBGPObjectState orig, final T objectState) {
+ super(orig);
+ this.objectState = objectState;
+ }
+
+ protected AbstractBGPObjectState(final AbstractBGPObjectState<T> orig) {
+ super(orig);
+ this.objectState = orig.objectState;
+ }
+
+ public final T getObjectState() {
+ return this.objectState;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("objectState", this.objectState);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.objectState == null) ? 0 : this.objectState.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final AbstractBGPObjectState<?> other = (AbstractBGPObjectState<?>) obj;
+ if (this.objectState == null) {
+ if (other.objectState != null)
+ return false;
+ } else if (!this.objectState.equals(other.objectState))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DocumentedException;
+
+/**
+ * There are several errors documented in RFC4271 or in draft, that have specific meaning for the BGP. This exception is
+ * used, when any of those errors occurs.
+ */
+public final class BGPDocumentedException extends DocumentedException {
+
+ private static final long serialVersionUID = -6212702584439430736L;
+
+ private static final Logger logger = LoggerFactory.getLogger(BGPDocumentedException.class);
+
+ private final BGPError error;
+
+ private final byte[] data;
+
+ /**
+ * Used when an error occurred that is described in rfc or draft.
+ *
+ * @param message message bound with this exception
+ * @param error specific documented error
+ */
+ public BGPDocumentedException(final String message, final BGPError error) {
+ this(message, error, null);
+ }
+
+ /**
+ * Used when an error occurred that is described in rfc or draft.
+ *
+ * @param message message bound with this exception
+ * @param error specific documented error
+ * @param data data associated with the error
+ */
+ public BGPDocumentedException(final String message, final BGPError error, final byte[] data) {
+ super(message);
+ this.error = error;
+ this.data = data;
+ logger.error("Error = " + error, this);
+ }
+
+ /**
+ * Returns specific documented error.
+ *
+ * @return documented error
+ */
+ public BGPError getError() {
+ return this.error;
+ }
+
+ /**
+ * Returns data associated with this error.
+ *
+ * @return byte array data
+ */
+ public byte[] getData() {
+ return this.data;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+/**
+ * Possible errors from implemented RFCs and drafts. Each error consists of error code and error subcode (code/subcode
+ * in comments).
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.5">BGP Notification Message</a>
+ */
+public enum BGPError {
+ /**
+ * Connection Not Synchronized. 1/1
+ */
+ CONNECTION_NOT_SYNC,
+ /**
+ * Bad Message Length. 1/2
+ */
+ BAD_MSG_LENGTH,
+ /**
+ * Bad Message Type. 1/3
+ */
+ BAD_MSG_TYPE,
+ /**
+ * Unspecific Open Message error.
+ */
+ UNSPECIFIC_OPEN_ERROR,
+ /**
+ * Unsupported Version Number. 2/1
+ */
+ VERSION_NOT_SUPPORTED,
+ /**
+ * Bad Peer AS. 2/2
+ */
+ BAD_PEER_AS,
+ /**
+ * Bad BGP Identifier. 2/3
+ */
+ BAD_BGP_ID,
+ /**
+ * Unsupported Optional Parameter. 2/4
+ */
+ OPT_PARAM_NOT_SUPPORTED,
+ /**
+ * Unacceptable Hold Time. 2/6
+ */
+ HOLD_TIME_NOT_ACC,
+ /**
+ * Malformed Attribute List. 3/1
+ */
+ MALFORMED_ATTR_LIST,
+ /**
+ * Unrecognized Well-known Attribute. 3/2
+ */
+ WELL_KNOWN_ATTR_NOT_RECOGNIZED,
+ /**
+ * Missing Well-known Attribute. 3/3
+ */
+ WELL_KNOWN_ATTR_MISSING,
+ /**
+ * Attribute Flags Error. 3/4
+ */
+ ATTR_FLAGS_MISSING,
+ /**
+ * Attribute Length Error. 3/5
+ */
+ ATTR_LENGTH_ERROR,
+ /**
+ * Invalid ORIGIN Attribute. 3/6
+ */
+ ORIGIN_ATTR_NOT_VALID,
+ /**
+ * Invalid NEXT_HOP Attribute. 3/8
+ */
+ NEXT_HOP_NOT_VALID,
+ /**
+ * Optional Attribute Error. 3/9
+ */
+ OPT_ATTR_ERROR,
+ /**
+ * Invalid Network Field. 3/10
+ */
+ NETWORK_NOT_VALID,
+ /**
+ * Malformed AS_PATH. 3/11
+ */
+ AS_PATH_MALFORMED,
+ /**
+ * Hold Timer Expired. 4/0
+ */
+ HOLD_TIMER_EXPIRED,
+ /**
+ * Finite State Machine Error. 5/0
+ */
+ FSM_ERROR,
+ /**
+ * Cease. 6/0
+ */
+ CEASE
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+
+/**
+ * Interface exposing the attributes of a BGPLink.
+ */
+public interface BGPLink extends BGPObject {
+ @Override
+ public BGPLinkState currentState();
+
+ /**
+ * Returns object Link Identifier describing this link.
+ *
+ * @return Link Identifier
+ */
+ public LinkIdentifier getLinkIdentifier();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+
+public final class BGPLinkState extends AbstractBGPObjectState<NetworkLinkState> {
+ private static final long serialVersionUID = 1L;
+
+ public BGPLinkState(BaseBGPObjectState orig, NetworkLinkState linkState) {
+ super(orig, linkState);
+ }
+
+ protected BGPLinkState(BGPLinkState orig) {
+ super(orig, orig.getObjectState());
+ }
+
+ @Override
+ protected BGPLinkState newInstance() {
+ return new BGPLinkState(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.framework.ProtocolMessage;
+
+/**
+ * Basic structure for BGP Message. There is not other common feature than the serialization.
+ */
+public interface BGPMessage extends ProtocolMessage {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Representation of BGP Message Header. Includes methods for parsing and serializing header.
+ * Length field represents the length of the message including the length of its header.
+ */
+public class BGPMessageHeader implements ProtocolMessageHeader {
+
+ public static final Logger logger = LoggerFactory.getLogger(BGPMessageHeader.class);
+
+ /**
+ * BGP message header fixed length (in bytes)
+ */
+ public static final int COMMON_HEADER_LENGTH = 19;
+
+ private static final int MARKER_SIZE = 16;
+ private static final int LENGTH_SIZE = 2;
+ private static final int TYPE_OFFSET = MARKER_SIZE + LENGTH_SIZE;
+
+ private int type;
+ private int length;
+ private boolean parsed = false;
+
+ /**
+ * Creates message header.
+ */
+ public BGPMessageHeader() {
+
+ }
+
+ /**
+ * Creates message header with given attributes.
+ * @param type int
+ * @param length int
+ */
+ public BGPMessageHeader(final int type, final int length) {
+ this.type = type;
+ this.length = length;
+ }
+
+ /**
+ * Creates a BGP Message Header from given byte array.
+ *
+ * @param bytes byte array to be parsed
+ * @return BGP Message Header
+ */
+ public BGPMessageHeader fromBytes(final byte[] bytes) {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory");
+ //FIXME: how to send Notification message from this point?
+ // final byte[] ones = new byte[MARKER_SIZE];
+ // Arrays.fill(ones, (byte)0xff);
+ //
+ // if (Arrays.equals(bytes, ones))
+ // throw new BGPDocumentedException("Marker not set to ones.", BGPError.CONNECTION_NOT_SYNC);
+
+ logger.trace("Attempt to parse message header: {}", ByteArray.bytesToHexString(bytes));
+
+ if (bytes.length < COMMON_HEADER_LENGTH)
+ throw new IllegalArgumentException("Too few bytes in passed array. Passed: " + bytes.length + ". Expected: >= " + COMMON_HEADER_LENGTH + ".");
+
+ this.length = ByteArray.bytesToInt(ByteArray.subByte(bytes, MARKER_SIZE, LENGTH_SIZE));
+
+ this.type = UnsignedBytes.toInt(bytes[TYPE_OFFSET]);
+
+ logger.trace("Message header was parsed. {}", this);
+ this.parsed = true;
+ return this;
+ }
+
+ /**
+ * Serializes this BGP Message header to byte array.
+ *
+ * @return byte array representation of this header
+ */
+ public byte[] toBytes() {
+ final byte[] retBytes = new byte[COMMON_HEADER_LENGTH];
+
+ Arrays.fill(retBytes, 0, MARKER_SIZE, (byte)0xff);
+
+ System.arraycopy(ByteArray.intToBytes(this.length), Integer.SIZE / Byte.SIZE - LENGTH_SIZE, retBytes, MARKER_SIZE, LENGTH_SIZE);
+
+ retBytes[TYPE_OFFSET] = (byte) this.type;
+
+ return retBytes;
+ }
+
+ /**
+ * Returns length presented in Length field of this header.
+ *
+ * @return length of the BGP message
+ */
+ public int getLength() {
+ return this.length;
+ }
+
+ /**
+ * Returns type presented in Type field of this header.
+ *
+ * @return type of the BGP message
+ */
+ public int getType() {
+ return this.type;
+ }
+
+ /**
+ * Return the state of the parsing of this header.
+ *
+ * @return the parsed true if the header was parsed false if the header was not parsed
+ */
+ public boolean isParsed() {
+ return this.parsed;
+ }
+
+ /**
+ * Marks parsing as not finished. There is no need for other classes to mark parsing as done, therefore calling this
+ * method will set parsing to unfinished.
+ */
+ public void setParsed() {
+ this.parsed = false;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import java.io.Closeable;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+
+/**
+ * Parser for BGP Messages.
+ */
+public interface BGPMessageParser extends ProtocolMessageFactory, Closeable {
+
+ @Override
+ public BGPMessage parse(byte[] bytes, ProtocolMessageHeader msgHeader) throws DeserializerException, DocumentedException;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+
+/**
+ * Interface exposing the attributes of a BGPNode.
+ */
+public interface BGPNode extends BGPObject {
+ @Override
+ public BGPNodeState currentState();
+
+ /**
+ * Returns object Node Identifier describing this node.
+ *
+ * @return {@link NodeIdentifier}
+ */
+ public NodeIdentifier getNodeIdentifier();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+
+public final class BGPNodeState extends AbstractBGPObjectState<NetworkNodeState> {
+ private static final long serialVersionUID = 1L;
+
+ public BGPNodeState(BaseBGPObjectState orig, NetworkNodeState nodeState) {
+ super(orig, nodeState);
+ }
+
+ protected BGPNodeState(BGPNodeState orig) {
+ super(orig, orig.getObjectState());
+ }
+
+ @Override
+ protected BGPNodeState newInstance() {
+ return new BGPNodeState(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+/**
+ * Marker interface of each BGP Parameter. Currently we have only Capabilities parameter.
+ */
+public interface BGPParameter {
+
+ /**
+ * Returns fixed type of the parameter.
+ *
+ * @return type of the parameter
+ */
+ public int getType();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+
+/**
+ *
+ * Used when something occurs during the parsing to get Update Message.
+ *
+ */
+public class BGPParsingException extends DeserializerException {
+
+ private static final long serialVersionUID = -6893285837086620580L;
+
+ private final String message;
+
+ /**
+ *
+ * @param err error message string.
+ */
+ public BGPParsingException(final String err) {
+ super(err);
+ this.message = err;
+ }
+
+ /**
+ *
+ * @param message exception message
+ * @param cause primary exception
+ */
+ public BGPParsingException(final String message, final Exception cause){
+ super(message, cause);
+ this.message = message;
+ }
+
+ /**
+ *
+ * @return error message.
+ */
+ public String getError() {
+ return this.message;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+
+/**
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2">Figure 9: The IPv4/IPv6
+ * Topology Prefix NLRI format</a>
+ *
+ * @param <T> Network Address type of the prefix
+ */
+public interface BGPPrefix<T extends NetworkAddress<T>> extends BGPObject {
+ @Override
+ public BGPPrefixState currentState();
+
+ /**
+ * Return the Prefix Identifier.
+ *
+ * @return Prefix Identifier
+ */
+ public PrefixIdentifier<T> getPrefixIdentifier();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+
+public final class BGPPrefixState extends AbstractBGPObjectState<NetworkPrefixState> {
+ private static final long serialVersionUID = 1L;
+
+ public BGPPrefixState(BaseBGPObjectState base, NetworkPrefixState prefixState) {
+ super(base, prefixState);
+ }
+
+ protected BGPPrefixState(BGPPrefixState orig) {
+ super(orig, orig.getObjectState());
+ }
+
+ @Override
+ protected BGPPrefixState newInstance() {
+ return new BGPPrefixState(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+import org.opendaylight.protocol.concepts.NamedObject;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ * A route is a unit of information that pairs a set of destinations with the attributes of a path to those
+ * destinations. The set of destinations are systems whose IP addresses are contained in one IP address prefix carried
+ * in the Network Layer Reachability Information (NLRI) field of an UPDATE message. The path is the information reported
+ * in the path attributes field of the same UPDATE message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-1.1">Definition of Commonly Used Terms</a>
+ * @param <T> subtype of Network Address
+ */
+public interface BGPRoute<T extends NetworkAddress<T>> extends BGPObject, NamedObject<Prefix<T>> {
+
+ @Override
+ public BGPRouteState<T> currentState();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+public final class BGPRouteState<T extends NetworkAddress<?>> extends AbstractBGPObjectState<NetworkRouteState<T>> {
+ private static final long serialVersionUID = 1L;
+
+ public BGPRouteState(BaseBGPObjectState orig, NetworkRouteState<T> routeState) {
+ super(orig, routeState);
+ }
+
+ protected BGPRouteState(BGPRouteState<T> orig) {
+ super(orig, orig.getObjectState());
+ }
+
+ @Override
+ protected BGPRouteState<T> newInstance() {
+ return new BGPRouteState<T>(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import java.io.Closeable;
+
+/**
+ * BGP Session represents the finite state machine in BGP, including timers and its purpose is to create a BGP
+ * connection between BGP speakers. Session is automatically started, when TCP connection is created, but can be stopped
+ * manually via close method of the Closeable interface.
+ *
+ * If the session is up, it has to redirect messages to/from user. Handles also malformed messages and unknown requests.
+ */
+public interface BGPSession extends Closeable {
+ @Override
+ public void close();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+import org.opendaylight.protocol.framework.SessionListener;
+
+/**
+ * Listener that receives session informations from the session.
+ */
+public abstract class BGPSessionListener implements SessionListener {
+
+ /**
+ * Fired when an Update or a non-fatal Notification message is received.
+ *
+ * @param message BGPMessage
+ */
+ public abstract void onMessage(BGPMessage message);
+
+ /**
+ * Fired when the session was established successfully.
+ *
+ * @param remoteParams Peer address families which we accepted
+ */
+ public abstract void onSessionUp(Set<BGPTableType> remoteParams);
+
+ /**
+ * Fired when the session went down because of an IO error. Implementation should take care of closing underlying
+ * session.
+ *
+ * @param session that went down
+ * @param e Exception that was thrown as the cause of session being down
+ */
+ public abstract void onSessionDown(BGPSession session, Exception e);
+
+ /**
+ * Fired when the session is terminated locally. The session has already been closed and transitioned to IDLE state.
+ * Any outstanding queued messages were not sent. The user should not attempt to make any use of the session.
+ *
+ * @param cause the cause why the session went down
+ */
+ public abstract void onSessionTerminated(BGPError cause);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+/**
+ * Marker interface for events resulting from parsing of an BGP UPDATE message. An unfortunate twist in BGP spec makes
+ * use of a specially-crafted message to indicate that a per-AFI RIB has been completely synchronized.
+ *
+ * Extends ProtocolMessage to allow parsing of BGP Update Messages in BGP listener.
+ */
+public interface BGPUpdateEvent extends BGPMessage {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+
+
+/**
+ *
+ * BGP Update Message contains two sets of Objects, ones that have to be removed from the topology and ones that need to
+ * be added. Although it is restricted to have the same object in both sets, the implementation needs to handle this
+ * kind of situation. Therefore, first step is to remove objects, then add the other set.
+ *
+ */
+public interface BGPUpdateMessage extends BGPUpdateEvent, BGPMessage {
+ /**
+ * Objects that are identified with Identifiers in this set, need to be removed from topology.
+ *
+ * @return set of identifiers of objects to be removed
+ */
+ public Set<?> getRemovedObjects();
+
+ /**
+ * Set of objects that need to be added to the topology wrapped in BGPObject that includes the identifier and its
+ * attributes.
+ *
+ * @return set of BGPObjects to be added
+ */
+ public Set<BGPObject> getAddedObjects();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+/**
+ * Update event indicating that a RIB has reached initial synchronization. An instance of this interface is generated
+ * when the BGP UPDATE parser encounters such a marker message.
+ */
+public interface BGPUpdateSynchronized extends BGPUpdateEvent {
+ /**
+ * Identify which RIB has reached synchronization.
+ *
+ * @return BGP table type
+ */
+ public BGPTableType getTableType();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.message;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+
+/**
+ * BGP KeepAlive message. Always empty.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.4">BGP KeepAlive message</a>
+ */
+public final class BGPKeepAliveMessage implements BGPMessage {
+
+ private static final long serialVersionUID = 5469664138660829255L;
+
+ /**
+ * Creates a BGP KeepAlive message.
+ */
+ public BGPKeepAliveMessage() {
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.message;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+
+
+/**
+ * Representation of BGPNotification message.
+ *
+ * @see <a link="http://tools.ietf.org/html/rfc4271#section-4.5">BGP Notification Message</a>
+ */
+public final class BGPNotificationMessage implements BGPMessage {
+
+ private static final long serialVersionUID = -5860147919167775673L;
+
+ private final BGPError error;
+
+ private final byte[] data;
+
+ /**
+ * Creates a BGPNotification message with no data.
+ *
+ * @param error cause
+ */
+ public BGPNotificationMessage(final BGPError error) {
+ this(error, null);
+ }
+
+ /**
+ * Creates a BGPNotification message with error cause and data.
+ *
+ * @param error cause
+ * @param data associated with this message
+ */
+ public BGPNotificationMessage(final BGPError error, final byte[] data) {
+ super();
+ this.error = error;
+ this.data = data;
+ }
+
+ /**
+ * Returns BGPError contained in this message.
+ *
+ * @return the error
+ */
+ public BGPError getError() {
+ return this.error;
+ }
+
+ /**
+ * Returns possible data associated with this message.
+ *
+ * @return the data
+ */
+ public byte[] getData() {
+ return this.data;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("BGPNotificationMessage [error=");
+ builder.append(this.error);
+ builder.append(", data=");
+ builder.append(Arrays.toString(this.data));
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.message;
+
+import java.util.List;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * Representation of BGPOpen message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.2">BGP Open Message</a>
+ */
+public final class BGPOpenMessage implements BGPMessage {
+
+ private static final long serialVersionUID = -3507481736478860117L;
+
+ /**
+ * Current BGP version.
+ */
+ public static final int BGP_VERSION = 4;
+
+ private final ASNumber myAS;
+
+ private final short holdTime;
+
+ private final IPv4Address bgpId;
+
+ private final List<BGPParameter> optParams;
+
+ /**
+ * Creates BGPOpen message.
+ *
+ * @param myAS ASNumber of the BGP speaker
+ * @param holdTime proposed value of the Hold Timer
+ * @param bgpId IPv4 Address of the BGP speaker
+ * @param optParams List of optional parameters
+ */
+ public BGPOpenMessage(final ASNumber myAS, final short holdTime, final IPv4Address bgpId, final List<BGPParameter> optParams) {
+ super();
+ this.myAS = myAS;
+ this.holdTime = holdTime;
+ this.bgpId = bgpId;
+ this.optParams = optParams;
+ }
+
+ /**
+ * Returns the AS number of the BGP speaker.
+ *
+ * @return myAS
+ */
+ public ASNumber getMyAS() {
+ return this.myAS;
+ }
+
+ /**
+ * Returns the value of the Hold timer.
+ *
+ * @return the holdTime
+ */
+ public short getHoldTime() {
+ return this.holdTime;
+ }
+
+ /**
+ * Returns BGP identifier of the speaker (his IP address).
+ *
+ * @return the bgpId
+ */
+ public IPv4Address getBgpId() {
+ return this.bgpId;
+ }
+
+ /**
+ * Returns optional parameters in form of TLVs.
+ *
+ * @return the optParams
+ */
+ public List<BGPParameter> getOptParams() {
+ return this.optParams;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("BGPOpenMessage [myAS=");
+ builder.append(this.myAS);
+ builder.append(", holdTime=");
+ builder.append(this.holdTime);
+ builder.append(", bgpId=");
+ builder.append(this.bgpId);
+ builder.append(", optParams=");
+ builder.append(this.optParams);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.parameter;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * AS 4B Numbers capability.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc6793">BGP Support for 4-Octet AS Number Space</a>
+ */
+public final class AS4BytesCapability extends CapabilityParameter {
+
+ /**
+ * Capability code for 4B AS.
+ */
+ public static final int CODE = 65;
+
+ private final ASNumber as;
+
+ public AS4BytesCapability(final ASNumber as) {
+ super(CODE);
+ this.as = as;
+ }
+
+ /**
+ * Returns 4B AS Number.
+ *
+ * @return 4B AS Number
+ */
+ public ASNumber getASNumber() {
+ return this.as;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("AS4BytesCapability [as=");
+ builder.append(this.as);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.parameter;
+
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+
+/**
+ * Capability parameter superclass.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3392#section-4">Capabilities Optional Parameter</a>
+ */
+public abstract class CapabilityParameter implements BGPParameter {
+
+ private final int TYPE = 2;
+
+ private final int code;
+
+ CapabilityParameter(final int code) {
+ this.code = code;
+ }
+
+ /**
+ * Returns capability code specific capability parameter.
+ *
+ * @return capability code
+ */
+ public int getCode() {
+ return this.code;
+ }
+
+ @Override
+ public int getType() {
+ return this.TYPE;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.parameter;
+
+import java.util.Map;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+
+/**
+ * Graceful restart capability parameter as described in:
+ *
+ * <a href="http://tools.ietf.org/html/rfc4724#section-3">Graceful Restart Capability</a>
+ */
+public final class GracefulCapability extends CapabilityParameter {
+
+ /**
+ * Capability code for GR)
+ */
+ private static final int CODE = 64;
+
+ private final boolean restartFlag;
+
+ private final int restartTimerValue;
+
+ private final Map<BGPTableType, Boolean> tableTypes;
+
+ /**
+ * Creates new Graceful restart capability.
+ *
+ * @param restartFlag should be false
+ * @param restartTimerValue should be 0
+ * @param tableTypes supported AFI/SAFI along with Forwarding state flag (should be true)
+ */
+ public GracefulCapability(final boolean restartFlag, final int restartTimerValue, final Map<BGPTableType, Boolean> tableTypes) {
+ super(CODE);
+ this.restartFlag = restartFlag;
+ this.restartTimerValue = restartTimerValue;
+ this.tableTypes = tableTypes;
+ }
+
+ /**
+ * Was router restarted?
+ *
+ * @return the restartFlag
+ */
+ public boolean isRestartFlag() {
+ return this.restartFlag;
+ }
+
+ /**
+ * Currently should be always 0.
+ *
+ * @return the restartTimerValue
+ */
+ public int getRestartTimerValue() {
+ return this.restartTimerValue;
+ }
+
+ /**
+ * Return supported AFI/SAFI along with Forwarding state flag.
+ *
+ * @return the tableTypes
+ */
+ public Map<BGPTableType, Boolean> getTableTypes() {
+ return this.tableTypes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.parameter;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+/**
+ * Multiprotocol capability Parameter as described in:
+ *
+ * <a href="http://tools.ietf.org/html/rfc4760#section-8">Use of BGP Capability Advertisement/a>
+ */
+public final class MultiprotocolCapability extends CapabilityParameter {
+
+ /**
+ * Capability Code is set to 1, which indicates Multiprotocol Extensions capabilities.
+ */
+ public static final int CODE = 1;
+
+ private final BGPTableType tableType;
+
+ /**
+ * Creates Multiprotocol Capability.
+ *
+ *
+ * @param type bgp table type
+ */
+ public MultiprotocolCapability(final BGPTableType type) {
+ super(CODE);
+ this.tableType = type;
+ }
+
+ /**
+ * Returns numeric representation of AFI.
+ *
+ * @return AFI
+ */
+ public BGPAddressFamily getAfi() {
+ return this.tableType.getAddressFamily();
+ }
+
+ /**
+ * Returns numeric representation of SAFI.
+ *
+ * @return SAFI
+ */
+ public BGPSubsequentAddressFamily getSafi() {
+ return this.tableType.getSubsequentAddressFamily();
+ }
+
+ /**
+ * Returns BGP Table Type that is supported by the sender of this capability.
+ *
+ * @return BGP Table Type
+ */
+ public BGPTableType getTableType() {
+ return this.tableType;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("MultiprotocolCapability [tableType=");
+ builder.append(this.tableType);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+ <body>
+ <head>${project.artifactId}</head>
+ <links>
+ <item name="${project.artifactId}" href="index.html"/>
+ </links>
+
+ <menu ref="parent"/>
+
+ <menu ref="reports"/>
+
+
+ </body>
+</project>
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.UnknownHostException;
+import java.util.Collections;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.RouteTag;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPLinkState;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPNodeState;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.BGPPrefixState;
+import org.opendaylight.protocol.bgp.parser.BGPRouteState;
+import org.opendaylight.protocol.util.DefaultingTypesafeContainer;
+import com.google.common.collect.Sets;
+
+public class APITest {
+
+ BaseBGPObjectState objState = new BaseBGPObjectState(BGPOrigin.EGP, null);
+ NetworkObjectState netObjState = new NetworkObjectState(null, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+
+ @Test
+ public void testAPI() {
+ final BGPRouteState<IPv4Address> route1 = new BGPRouteState<IPv4Address>(this.objState, new NetworkRouteState<IPv4Address>(new IPv4NextHop(IPv4.FAMILY.addressForString("192.168.5.4"))));
+ final BGPRouteState<IPv4Address> route2 = new BGPRouteState<IPv4Address>(new BaseBGPObjectState(BGPOrigin.IGP, null), new NetworkRouteState<IPv4Address>(new IPv4NextHop(IPv4.FAMILY.addressForString("172.168.5.42"))));
+
+ assertEquals(route1, route1.newInstance());
+ assertNotSame(route1.hashCode(), new BGPRouteState<IPv4Address>(route2).hashCode());
+ assertEquals(route1.toString(), route1.toString());
+ assertNull(route1.getAggregator());
+ assertNotNull(route1.getObjectState().getNextHop());
+ assertEquals(route1.getOrigin(), BGPOrigin.EGP);
+
+ final BGPParsingException e = new BGPParsingException("Some error message.");
+ assertEquals("Some error message.", e.getError());
+
+ final BGPParsingException e2 = new BGPParsingException("Some error message.", new IllegalAccessException());
+ assertEquals("Some error message.", e2.getError());
+ assertTrue(e2.getCause() instanceof IllegalAccessException);
+ }
+
+ @Test
+ public void testBGPHeaderParser() {
+ final BGPMessageHeader h = new BGPMessageHeader();
+ try {
+ h.fromBytes(new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0, (byte) 0 });
+ fail("Exception should have occured.");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Too few bytes in passed array. Passed: 18. Expected: >= " + BGPMessageHeader.COMMON_HEADER_LENGTH + ".",
+ e.getMessage());
+ }
+
+ h.fromBytes(new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0,
+ (byte) 27, (byte) 1 });
+
+ assertEquals(h.getType(), 1);
+ assertEquals(h.getLength(), 27);
+ assertTrue(h.isParsed());
+
+ final BGPMessageHeader hh = new BGPMessageHeader(1, 27);
+
+ final byte[] expected = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0, (byte) 27, (byte) 1 };
+
+ assertArrayEquals(expected, hh.toBytes());
+
+ hh.setParsed();
+
+ assertFalse(hh.isParsed());
+ }
+
+ @Test
+ public void testPrefixes() throws UnknownHostException {
+ final NetworkPrefixState state = new NetworkPrefixState(this.netObjState, Sets.<RouteTag> newTreeSet(), null);
+
+ final BGPPrefixState ipv4 = new BGPPrefixState(this.objState, state);
+ final BGPPrefixState ipv6 = new BGPPrefixState(new BaseBGPObjectState(BGPOrigin.EGP, null), state);
+
+ assertEquals(ipv4.toString(), ipv4.newInstance().toString());
+ assertNotSame(ipv4, new BGPPrefixState(ipv6));
+ }
+
+ @Test
+ public void testNodeState() {
+ final BGPNodeState n1 = new BGPNodeState(this.objState, new NetworkNodeState(this.netObjState, Collections.<TopologyIdentifier, TopologyNodeInformation> emptyMap(), Collections.<ISISAreaIdentifier> emptySet(), false, false, Collections.<RouterIdentifier> emptySet(), ""));
+ assertEquals(n1, n1.newInstance());
+ assertEquals(n1, new BGPNodeState(n1));
+ }
+
+ @Test
+ public void testLinkState() {
+ final DefaultingTypesafeContainer<Metric<?>> m = new DefaultingTypesafeContainer<Metric<?>>();
+ m.setDefaultEntry(new TEMetric(15L));
+ final BGPLinkState l1 = new BGPLinkState(this.objState, new NetworkLinkState(this.netObjState, m, null, null, null, LinkProtectionType.UNPROTECTED, null, null, null, null));
+ assertEquals(l1, l1.newInstance());
+ assertEquals(l1, new BGPLinkState(l1));
+ }
+}
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-updated-parser-impl</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-parser-impl</artifactId>
+ <description>BGP Parser Implementation Updated to draft-02</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-linkstate</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>util</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-util</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Private-Package>
+ javax.annotation.*,
+ org.opendaylight.protocol.bgp.parser.impl.*
+ </Private-Package>
+ <Import-Package>
+ org.opendaylight.protocol.bgp.parser.message,
+ org.opendaylight.protocol.bgp.parser.parameter,
+ org.opendaylight.protocol.bgp.concepts,
+ org.opendaylight.protocol.bgp.linkstate,
+ org.opendaylight.protocol.bgp.parser,
+ org.opendaylight.protocol.bgp.util,
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.framework,
+ org.opendaylight.protocol.util,
+ com.google.common.*,
+ org.slf4j,
+ org.apache.commons.lang
+ </Import-Package>
+ <Export-Package>
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-PARSER-IMPL Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+
+/**
+ *
+ */
+public abstract class AbstractLinkstateMP<T> implements MPReach<T> {
+
+ private final boolean reachable;
+
+ private final long identifier;
+
+ private final SourceProtocol sourceProtocol;
+
+ protected AbstractLinkstateMP(final long identifier, final SourceProtocol sourceProtocol, final boolean reachable) {
+ this.identifier = identifier;
+ this.sourceProtocol = sourceProtocol;
+ this.reachable = reachable;
+ }
+
+ @Override
+ public boolean isReachable() {
+ return this.reachable;
+ }
+
+ public long getIdentifier() {
+ return this.identifier;
+ }
+
+ public SourceProtocol getSourceProtocol() {
+ return this.sourceProtocol;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (this.identifier ^ (this.identifier >>> 32));
+ result = prime * result + (this.reachable ? 1231 : 1237);
+ result = prime * result + ((this.sourceProtocol == null) ? 0 : this.sourceProtocol.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final AbstractLinkstateMP<?> other = (AbstractLinkstateMP<?>) obj;
+ if (this.identifier != other.identifier)
+ return false;
+ if (this.reachable != other.reachable)
+ return false;
+ if (this.sourceProtocol != other.sourceProtocol)
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("AbstractLinkstateMP [reachable=");
+ builder.append(this.reachable);
+ builder.append(", identifier=");
+ builder.append(this.identifier);
+ builder.append(", sourceProtocol=");
+ builder.append(this.sourceProtocol);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Implementation of BGP Aggregator object.
+ * @param <T> subtype of Network Address
+ */
+public class BGPAggregatorImpl<T extends NetworkAddress<T>> implements
+ BGPAggregator {
+
+ private final ASNumber asNumber;
+
+ private final T address;
+
+ public BGPAggregatorImpl(ASNumber asNumber, T address) {
+ this.address = address;
+ this.asNumber = asNumber;
+ }
+
+ @Override
+ public ASNumber getASNumber() {
+ return this.asNumber;
+ }
+
+ @Override
+ public T getNetworkAddress() {
+ return this.address;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.address == null) ? 0 : this.address.hashCode());
+ result = prime * result
+ + ((this.asNumber == null) ? 0 : this.asNumber.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final BGPAggregatorImpl<?> other = (BGPAggregatorImpl<?>) obj;
+ if (this.address == null) {
+ if (other.address != null)
+ return false;
+ } else if (!this.address.equals(other.address))
+ return false;
+ if (this.asNumber == null) {
+ if (other.asNumber != null)
+ return false;
+ } else if (!this.asNumber.equals(other.asNumber))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("BGPAggregatorImpl [asNumber=");
+ builder.append(this.asNumber);
+ builder.append(", address=");
+ builder.append(this.address);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+
+/**
+ * IPv4 implementation of {@link MPReach}.
+ */
+public class BGPIPv4PrefixMP extends AbstractLinkstateMP<IPv4PrefixIdentifier> {
+
+ private final Set<IPv4PrefixIdentifier> prefixes;
+
+ /**
+ * Creates BGP IPv4 Prefix.
+ *
+ * @param identifier long
+ * @param sourceProtocol {@link SourceProtocol}
+ * @param prefixes set of prefixes
+ * @param reachable true if the attribute is MPReach, false if the attribute is MPUnreach
+ */
+ public BGPIPv4PrefixMP(final long identifier, final SourceProtocol sourceProtocol, final Set<IPv4PrefixIdentifier> prefixes,
+ final boolean reachable) {
+ super(identifier, sourceProtocol, reachable);
+ this.prefixes = prefixes;
+ }
+
+ @Override
+ public Set<IPv4PrefixIdentifier> getNlri() {
+ return this.prefixes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import org.opendaylight.protocol.bgp.linkstate.IPv6PrefixIdentifier;
+
+/**
+ * IPv6 implementation of {@link MPReach}.
+ */
+public class BGPIPv6PrefixMP extends AbstractLinkstateMP<IPv6PrefixIdentifier> {
+
+ private final Set<IPv6PrefixIdentifier> prefixes;
+
+ /**
+ * Creates BGP IPv6 Prefix.
+ *
+ * @param identifier long
+ * @param sourceProtocol {@link SourceProtocol}
+ * @param prefixes set of prefix descriptors
+ * @param reachable true if the attribute is MPReach, false if the attribute is MPUnreach
+ */
+ public BGPIPv6PrefixMP(final long identifier, final SourceProtocol sourceProtocol, final Set<IPv6PrefixIdentifier> prefixes,
+ final boolean reachable) {
+ super(identifier, sourceProtocol, reachable);
+ this.prefixes = prefixes;
+ }
+
+ @Override
+ public Set<IPv6PrefixIdentifier> getNlri() {
+ return this.prefixes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+
+/**
+ *
+ * Link State MP_(UN)REACH_NLRI (contains BGP Link inf.)
+ *
+ */
+public class BGPLinkMP extends AbstractLinkstateMP<LinkIdentifier> {
+
+ private final Set<LinkIdentifier> link;
+
+ /**
+ * Creates BGP LINK MP Reach.
+ *
+ * @param identifier long
+ * @param sourceProtocol {@link SourceProtocol}
+ * @param prefixes set of prefix descriptors
+ * @param reachable true if the attribute is MPReach, false if the attribute is MPUnreach
+ */
+ public BGPLinkMP(final long identifier, final SourceProtocol sourceProtocol, final boolean reachable, final Set<LinkIdentifier> link) {
+ super(identifier, sourceProtocol, reachable);
+ this.link = link;
+ }
+
+ @Override
+ public Set<LinkIdentifier> getNlri() {
+ return this.link;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.link == null) ? 0 : this.link.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final BGPLinkMP other = (BGPLinkMP) obj;
+ if (this.link == null) {
+ if (other.link != null)
+ return false;
+ } else if (!this.link.equals(other.link))
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("BGPLinkMP [link=");
+ builder.append(this.link);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPNotificationMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPOpenMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ *
+ */
+public class BGPMessageFactory implements BGPMessageParser {
+
+ private final static Logger logger = LoggerFactory.getLogger(BGPMessageFactory.class);
+
+ public BGPMessageFactory() {
+ }
+
+ @Override
+ public BGPMessage parse(final byte[] bytes, final ProtocolMessageHeader msgH) throws DeserializerException, DocumentedException {
+ final BGPMessageHeader msgHeader = (BGPMessageHeader) msgH;
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory.");
+ if (msgHeader == null)
+ throw new IllegalArgumentException("BGPMessageHeader is mandatory.");
+ if (msgHeader.getLength() < BGPMessageHeader.COMMON_HEADER_LENGTH)
+ throw new BGPDocumentedException("Message length field not within valid range.", BGPError.BAD_MSG_LENGTH, ByteArray.intToBytes(msgHeader.getLength()));
+ if (bytes.length != (msgHeader.getLength() - BGPMessageHeader.COMMON_HEADER_LENGTH))
+ throw new BGPParsingException("Size doesn't match size specified in header. Passed: " + bytes.length + "; Expected: "
+ + (msgHeader.getLength() - BGPMessageHeader.COMMON_HEADER_LENGTH) + ". " + msgHeader.getLength());
+
+ logger.debug("Attempt to parse message from bytes: {}", ByteArray.bytesToHexString(bytes));
+
+ BGPMessage msg = null;
+
+ switch (msgHeader.getType()) {
+ case 1:
+ msg = BGPOpenMessageParser.parse(bytes);
+ logger.debug("Received and parsed Open Message: {}", msg);
+ break;
+ case 2:
+ msg = BGPUpdateMessageParser.parse(bytes, msgHeader.getLength());
+ logger.debug("Received and parsed Update Message: {}", msg);
+ break;
+ case 3:
+ msg = BGPNotificationMessageParser.parse(bytes);
+ logger.debug("Received and parsed Notification Message: {}", msg);
+ break;
+ case 4:
+ msg = new BGPKeepAliveMessage();
+ if (msgHeader.getLength() != BGPMessageHeader.COMMON_HEADER_LENGTH)
+ throw new BGPDocumentedException("Message length field not within valid range.", BGPError.BAD_MSG_LENGTH, ByteArray.intToBytes(msgHeader.getLength()));
+ break;
+ default:
+ throw new BGPDocumentedException("Unhandled message type " + msgHeader.getType(), BGPError.BAD_MSG_TYPE, ByteArray.intToBytes(msgHeader.getType()));
+ }
+ return msg;
+ }
+
+ @Override
+ public byte[] put(final ProtocolMessage msg) {
+ final BGPMessage bgpMsg = (BGPMessage) msg;
+ if (bgpMsg == null)
+ throw new IllegalArgumentException("BGPMessage is mandatory.");
+
+ logger.trace("Serializing {}", bgpMsg);
+
+ byte[] msgBody = null;
+ int msgType = 0;
+
+ /*
+ * Update message is not supported
+ */
+ if (bgpMsg instanceof BGPOpenMessage) {
+ msgType = 1;
+ msgBody = BGPOpenMessageParser.put((BGPOpenMessage) bgpMsg);
+ } else if (bgpMsg instanceof BGPNotificationMessage) {
+ msgType = 3;
+ msgBody = BGPNotificationMessageParser.put((BGPNotificationMessage) bgpMsg);
+ } else if (bgpMsg instanceof BGPKeepAliveMessage) {
+ msgType = 4;
+ msgBody = new byte[0];
+ } else {
+ throw new IllegalArgumentException("Unknown instance of BGPMessage. Passed " + bgpMsg.getClass());
+ }
+
+ final BGPMessageHeader msgHeader = new BGPMessageHeader(msgType, msgBody.length + BGPMessageHeader.COMMON_HEADER_LENGTH);
+
+ final byte[] headerBytes = msgHeader.toBytes();
+ final byte[] retBytes = new byte[headerBytes.length + msgBody.length];
+
+ ByteArray.copyWhole(headerBytes, retBytes, 0);
+ ByteArray.copyWhole(msgBody, retBytes, BGPMessageHeader.COMMON_HEADER_LENGTH);
+
+ logger.trace("Serialized BGP message {}.", Arrays.toString(retBytes));
+ return retBytes;
+ }
+
+ @Override
+ public void close() throws IOException {
+ // nothing to close
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+
+/**
+ *
+ * Link State MP_(UN)REACH_NLRI (contains BGP Node inf.)
+ *
+ */
+public class BGPNodeMP extends AbstractLinkstateMP<NodeIdentifier> {
+
+ private final Set<NodeIdentifier> nodes;
+
+ /**
+ * Creates BGP Node MP Reach.
+ *
+ * @param identifier long
+ * @param sourceProtocol {@link SourceProtocol}
+ * @param prefixes set of prefix descriptors
+ * @param reachable true if the attribute is MPReach, false if the attribute is MPUnreach
+ */
+ public BGPNodeMP(final long identifier, final SourceProtocol sourceProtocol, final boolean reachable, final Set<NodeIdentifier> nodes) {
+ super(identifier, sourceProtocol, reachable);
+ this.nodes = nodes;
+ }
+
+ @Override
+ public Set<NodeIdentifier> getNlri() {
+ return this.nodes;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.nodes == null) ? 0 : this.nodes.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final BGPNodeMP other = (BGPNodeMP) obj;
+ if (this.nodes == null) {
+ if (other.nodes != null)
+ return false;
+ } else if (!this.nodes.equals(other.nodes))
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("BGPNodeMP [nodes=");
+ builder.append(this.nodes);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateEvent;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.LinkStateParser;
+import org.opendaylight.protocol.bgp.util.BGPIPv4PrefixImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6PrefixImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPLinkImpl;
+import org.opendaylight.protocol.bgp.util.BGPNodeImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkImpl;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeImpl;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ *
+ * Builds BGPUpdateEvent. This code was originally in {@link BGPUpdateMessageParser}. Moved here during refactoring.
+ *
+ * Withdrawn routes or nlri that contain directly prefixes, can contain only IPv4 Prefixes.
+ */
+@NotThreadSafe
+public class BGPUpdateEventBuilder {
+
+ private static final Logger log = LoggerFactory.getLogger(BGPUpdateEventBuilder.class);
+
+ /**
+ *
+ * Length of the withdrawn_routes field, in bytes.
+ */
+
+ private int withdrawnRoutesLength;
+
+ /**
+ *
+ * List of IP address prefixes for the routes that are being withdrawn. Can be empty when there are no routes to
+ *
+ * withdraw.
+ */
+
+ private Set<Prefix<IPv4Address>> withdrawnRoutes;
+
+ /**
+ *
+ * Length of the total_path_attributes field, in bytes.
+ */
+
+ private int totalPathAttrLength;
+
+ /**
+ *
+ * List of path attributes. Can be empty when there are only withdrawn routes present.
+ */
+
+ private List<PathAttribute> pathAttributes;
+
+ /**
+ *
+ * List of IP address prefixes of routes that are advertised.
+ */
+
+ private Set<Prefix<IPv4Address>> nlri;
+
+ /**
+ *
+ * Fills in BGP Objects that need to be added to topology. The method first checks and sets Path Attributes. If the
+ *
+ * NLRI field is not empty, create for each of the prefixes present in NLRI, a BGPRoute with the attributes and
+ *
+ * corresponding Prefix. If MP_REACH_NLRI attribute is found, check its NLRI, if its not of type Link State, do the
+ *
+ * same.
+ *
+ *
+ *
+ * @param pathAttributes
+ *
+ * @param nlri
+ *
+ *
+ *
+ * @return set of BGP Objects that need to be added
+ *
+ * @throws BGPParsingException
+ */
+
+ private Set<BGPObject> fillAddedObjects(final List<PathAttribute> pathAttributes, final Set<Prefix<IPv4Address>> nlri)
+ throws BGPParsingException {
+ BGPOrigin origin = null;
+ ASPath aspath = null;
+ IPv4NextHop nextHop = null;
+ BGPAggregator aggregator = null;
+ final Set<ExtendedCommunity> ecomm = Sets.newHashSet();
+ final Set<Community> comm = Sets.newHashSet();
+ final Map<Integer, ByteList> linkstate = Maps.newHashMap();
+ for (final PathAttribute pa : pathAttributes) {
+ if (pa.getValue() instanceof BGPOrigin) {
+ origin = (BGPOrigin) pa.getValue();
+ } else if (pa.getValue() instanceof ASPath) {
+ aspath = (ASPath) pa.getValue();
+ } else if (pa.getValue() instanceof IPv4NextHop) {
+ nextHop = (IPv4NextHop) pa.getValue();
+ } else if (pa.getValue() instanceof BGPAggregator) {
+ aggregator = (BGPAggregator) pa.getValue();
+ } else if (pa.getValue() instanceof Set) {
+ for (final Object o : (Set<?>) pa.getValue()) {
+ if (o instanceof ExtendedCommunity) {
+ ecomm.add((ExtendedCommunity) o);
+ } else if (o instanceof Community) {
+ comm.add((Community) o);
+ }
+ }
+ } else if (pa.getValue() instanceof Map) {
+ for (final Entry<?, ?> entry : ((Map<?, ?>) pa.getValue()).entrySet()) {
+ if (entry.getValue() instanceof ByteList) {
+ final ByteList lb = (ByteList) entry.getValue();
+ linkstate.put((Integer) entry.getKey(), lb);
+ }
+ }
+ }
+ }
+
+ final BaseBGPObjectState base = new BaseBGPObjectState(origin, aggregator);
+ final NetworkObjectState nos = new NetworkObjectState(aspath, comm, ecomm);
+ final Set<BGPObject> added = new HashSet<BGPObject>();
+ if (!nlri.isEmpty()) {
+ final NetworkRouteState<IPv4Address> nrs = new NetworkRouteState<>(nos, nextHop);
+ for (final Prefix<IPv4Address> p : nlri) {
+ added.add(new BGPIPv4RouteImpl(p, base, nrs));
+ }
+ }
+
+ final MPReach<?> mpreach = findMP(pathAttributes, true);
+ if (mpreach != null) {
+ if (mpreach instanceof IPv4MP) {
+ final IPv4MP ipv4mp = (IPv4MP) mpreach;
+ final IPv4NextHop v4nextHop = ipv4mp.getNextHop();
+ final NetworkRouteState<IPv4Address> nrs = new NetworkRouteState<>(nos, v4nextHop);
+ for (final Prefix<IPv4Address> p : ipv4mp.getNlri()) {
+ added.add(new BGPIPv4RouteImpl(p, base, nrs));
+ }
+ } else if (mpreach instanceof IPv6MP) {
+ final IPv6MP ipv6mp = (IPv6MP) mpreach;
+ final IPv6NextHop v6nextHop = ipv6mp.getNextHop();
+ final NetworkRouteState<IPv6Address> nrs = new NetworkRouteState<>(nos, v6nextHop);
+ for (final Prefix<IPv6Address> p : ipv6mp.getNlri()) {
+ added.add(new BGPIPv6RouteImpl(p, base, nrs));
+ }
+ } else if (mpreach instanceof BGPNodeMP) {
+ final Set<NodeIdentifier> nodes = ((BGPNodeMP) mpreach).getNlri();
+ if (!LinkStateParser.verifyNode(linkstate.keySet()))
+ throw new BGPParsingException("Some attributes from LINK_STATE Path attribute don't belong to advertised node.");
+ for (final NodeIdentifier desc : nodes) {
+ final NetworkNodeImpl n = LinkStateParser.parseNodeAttributes(desc, linkstate);
+ n.setASPath(aspath);
+ n.setExtendedCommunities(ecomm);
+ n.setCommunities(comm);
+ final BGPNodeImpl bgpNode = new BGPNodeImpl(base, desc, n.currentState());
+ log.debug("Adding bgp node {}", bgpNode);
+ added.add(bgpNode);
+ }
+ } else if (mpreach instanceof BGPLinkMP) {
+ final Set<LinkIdentifier> links = ((BGPLinkMP) mpreach).getNlri();
+ if (!LinkStateParser.verifyLink(linkstate.keySet()))
+ throw new BGPParsingException("Some attributes from LINK_STATE Path attribute don't belong to advertised link.");
+ for (final LinkIdentifier desc : links) {
+ final NetworkLinkImpl l = LinkStateParser.parseLinkAttributes(desc, linkstate);
+ l.setASPath(aspath);
+ l.setExtendedCommunities(ecomm);
+ l.setCommunities(comm);
+ log.debug("Adding bgp link {}", l);
+ added.add(new BGPLinkImpl(base, desc, l.currentState()));
+ }
+ } else if (mpreach instanceof BGPIPv4PrefixMP) {
+ final Set<IPv4PrefixIdentifier> prefixes = ((BGPIPv4PrefixMP) mpreach).getNlri();
+ if (!LinkStateParser.verifyPrefix(linkstate.keySet()))
+ throw new BGPParsingException("Some attributes from LINK_STATE Path attribute don't belong to advertised prefix.");
+ final NetworkPrefixState nps = LinkStateParser.parsePrefixAttributes(((BGPIPv4PrefixMP) mpreach).getSourceProtocol(), nos,
+ linkstate);
+ for (final IPv4PrefixIdentifier desc : prefixes) {
+ log.debug("Adding IPv4 Prefix {} State {}", desc, nps);
+ added.add(new BGPIPv4PrefixImpl(base, desc, nps));
+ }
+ } else if (mpreach instanceof BGPIPv6PrefixMP) {
+ final Set<IPv6PrefixIdentifier> prefixes = ((BGPIPv6PrefixMP) mpreach).getNlri();
+ if (!LinkStateParser.verifyPrefix(linkstate.keySet()))
+ throw new BGPParsingException("Some attributes from LINK_STATE Path attribute don't belong to advertised prefix.");
+
+ final NetworkPrefixState nps = LinkStateParser.parsePrefixAttributes(((BGPIPv6PrefixMP) mpreach).getSourceProtocol(), nos,
+ linkstate);
+ for (final IPv6PrefixIdentifier desc : prefixes) {
+ log.debug("Adding IPv6 Prefix {} State {}", desc, nps);
+ added.add(new BGPIPv6PrefixImpl(base, desc, nps));
+ }
+ }
+ }
+ return added;
+
+ }
+
+ /**
+ * Fills in Identifiers that need to be removed. First, check field withdrawn routes, that can contain only IPv4
+ * prefixes. Then, check the presence of MP_UNREACH_NLRI and if its NLRI contains Prefixes, add them to removed
+ * field. For link state information, Node & LinkIdentifiers are added to the Set.
+ *
+ * @param pathAttributes
+ * @param withdrawnRoutes
+ *
+ * @return set of identifiers that need to be removed
+ */
+
+ private Set<?> fillRemovedObjects(final List<PathAttribute> pathAttributes, final Set<Prefix<IPv4Address>> withdrawnRoutes) {
+ final Set<Object> removed = Sets.newHashSet();
+ if (!withdrawnRoutes.isEmpty()) {
+ removed.addAll(withdrawnRoutes);
+ }
+ final MPReach<?> mpunreach = findMP(pathAttributes, false);
+ if (mpunreach != null) {
+ if (mpunreach instanceof IPv4MP) {
+ final IPv4MP ipv4mp = (IPv4MP) mpunreach;
+ if (!ipv4mp.getNlri().isEmpty()) {
+ removed.addAll(ipv4mp.getNlri());
+ }
+ } else if (mpunreach instanceof IPv6MP) {
+ final IPv6MP ipv6mp = (IPv6MP) mpunreach;
+ if (!ipv6mp.getNlri().isEmpty()) {
+ removed.addAll(ipv6mp.getNlri());
+ }
+ } else if (mpunreach instanceof BGPNodeMP) {
+ for (final NodeIdentifier node : ((BGPNodeMP) mpunreach).getNlri()) {
+ removed.add(node);
+ }
+ } else if (mpunreach instanceof BGPLinkMP) {
+ for (final LinkIdentifier link : ((BGPLinkMP) mpunreach).getNlri()) {
+ removed.add(link);
+ }
+ } else if (mpunreach instanceof BGPIPv4PrefixMP) {
+ for (final IPv4PrefixIdentifier pref : ((BGPIPv4PrefixMP) mpunreach).getNlri()) {
+ removed.add(pref);
+ }
+ } else if (mpunreach instanceof BGPIPv6PrefixMP) {
+ for (final IPv6PrefixIdentifier pref : ((BGPIPv6PrefixMP) mpunreach).getNlri()) {
+ removed.add(pref);
+ }
+ }
+ }
+ return removed;
+
+ }
+
+ /**
+ * Finds MPReach object in Path Attribute list (depending on reachability boolean) and returns typecasted object.
+ *
+ * @param arrayList list of path attributes
+ * @param reachable true if we search for MP_REACH_NLRI, false if we search for MP_UNREACH_NLRI
+ *
+ * @return cated MPReach object
+ */
+ private static <T> MPReach<?> findMP(final Collection<PathAttribute> arrayList, final boolean reachable) {
+ for (final PathAttribute o : arrayList) {
+ final Object v = o.getValue();
+ if (v != null && v instanceof MPReach<?>) {
+ final MPReach<?> t = (MPReach<?>) v;
+ if (t.isReachable() == reachable)
+ return t;
+ }
+ }
+ return null;
+ }
+
+ int getWithdrawnRoutesLength() {
+ return this.withdrawnRoutesLength;
+ }
+
+ public void setWithdrawnRoutesLength(final int withdrawnRoutesLength) {
+ this.withdrawnRoutesLength = withdrawnRoutesLength;
+ }
+
+ Set<Prefix<IPv4Address>> getWithdrawnRoutes() {
+ return this.withdrawnRoutes;
+ }
+
+ public void setWithdrawnRoutes(final Set<Prefix<IPv4Address>> withdrawnRoutes) {
+ this.withdrawnRoutes = withdrawnRoutes;
+ }
+
+ int getTotalPathAttrLength() {
+ return this.totalPathAttrLength;
+ }
+
+ public void setTotalPathAttrLength(final int totalPathAttrLength) {
+ this.totalPathAttrLength = totalPathAttrLength;
+ }
+
+ List<PathAttribute> getPathAttributes() {
+ return this.pathAttributes;
+ }
+
+ public void setPathAttributes(final List<PathAttribute> pathAttributes) {
+ this.pathAttributes = pathAttributes;
+ }
+
+ Set<Prefix<IPv4Address>> getNlri() {
+ return this.nlri;
+ }
+
+ public void setNlri(final Set<Prefix<IPv4Address>> nlri) {
+ this.nlri = nlri;
+ }
+
+ /**
+ * Builds BGP Update message.
+ *
+ * @return BGP Update message
+ * @throws BGPParsingException
+ */
+ public BGPUpdateEvent buildEvent() throws BGPParsingException {
+ final Set<BGPObject> added = fillAddedObjects(this.pathAttributes, this.nlri);
+ final Set<?> removed = fillRemovedObjects(this.pathAttributes, this.withdrawnRoutes);
+ return new BGPUpdateMessageImpl(added, removed);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+
+
+/**
+ * BGP Update Message.
+ *
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.3">BGP-4 Update Message Format</a>
+ *
+ */
+public class BGPUpdateMessageImpl implements BGPUpdateMessage {
+
+ private static final long serialVersionUID = -1336770400381759349L;
+
+ private final Set<BGPObject> addedObjects;
+
+ private final Set<?> removedObjects;
+
+ public BGPUpdateMessageImpl(final Set<BGPObject> addedObjects, final Set<?> removedObjects) {
+ super();
+ this.addedObjects = addedObjects;
+ this.removedObjects = removedObjects;
+ }
+
+ @Override
+ public Set<BGPObject> getAddedObjects() {
+ return this.addedObjects;
+ }
+
+ @Override
+ public Set<?> getRemovedObjects() {
+ return this.removedObjects;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.addedObjects == null) ? 0 : this.addedObjects.hashCode());
+ result = prime * result + ((this.removedObjects == null) ? 0 : this.removedObjects.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final BGPUpdateMessageImpl other = (BGPUpdateMessageImpl) obj;
+ if (this.addedObjects == null) {
+ if (other.addedObjects != null)
+ return false;
+ } else if (!this.addedObjects.equals(other.addedObjects))
+ return false;
+ if (this.removedObjects == null) {
+ if (other.removedObjects != null)
+ return false;
+ } else if (!this.removedObjects.equals(other.removedObjects))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("BGPUpdateMessageImpl [addedObjects=");
+ builder.append(this.addedObjects);
+ builder.append(", removedObjects=");
+ builder.append(this.removedObjects);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * DTO class to avoid class cast warnings.
+ */
+public class ByteList {
+
+ private final List<byte[]> bytes;
+
+ /**
+ * Creates an empty list of byte arrays.
+ */
+ public ByteList() {
+ this.bytes = new ArrayList<byte[]>();
+ }
+
+ /**
+ * Returns underlying list of byte arrays
+ * @return underlying list of byte arrays
+ */
+ public List<byte[]> getBytes() {
+ return this.bytes;
+ }
+
+ /**
+ * Adds byte array to underlying list
+ * @param value byte array
+ */
+ public void add(byte[] value) {
+ this.bytes.add(value);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.bytes == null) ? 0 : this.bytes.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof ByteList))
+ return false;
+ final ByteList other = (ByteList) obj;
+ if (this.bytes == null) {
+ if (other.bytes != null)
+ return false;
+ } else if (this.bytes.size() != other.bytes.size())
+ return false;
+ else {
+ for (int i = 0; i < this.bytes.size(); i ++) {
+ if (!Arrays.equals(this.bytes.get(i), other.bytes.get(i))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("ByteList [bytes=");
+ for (final byte[] b : this.bytes) {
+ builder.append(Arrays.toString(b));
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ *
+ * MP_(UN)REACH_NLRI (basic, IPv4)
+ *
+ */
+public class IPv4MP implements MPReach<Prefix<IPv4Address>> {
+
+ private final boolean reachable;
+
+ private final IPv4NextHop nextHop;
+
+ private final Set<Prefix<IPv4Address>> nlri;
+
+ public IPv4MP(final boolean reachable, final IPv4NextHop nextHop, final Set<Prefix<IPv4Address>> nlri) {
+ this.reachable = reachable;
+ this.nextHop = nextHop;
+ this.nlri = nlri;
+ }
+
+ @Override
+ public boolean isReachable() {
+ return this.reachable;
+ }
+
+ @Override
+ public Set<Prefix<IPv4Address>> getNlri() {
+ return this.nlri;
+ }
+
+ public IPv4NextHop getNextHop() {
+ return this.nextHop;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.nextHop == null) ? 0 : this.nextHop.hashCode());
+ result = prime * result + ((this.nlri == null) ? 0 : this.nlri.hashCode());
+ result = prime * result + (this.reachable ? 1231 : 1237);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof IPv4MP))
+ return false;
+ final IPv4MP other = (IPv4MP) obj;
+ if (this.nextHop == null) {
+ if (other.nextHop != null)
+ return false;
+ } else if (!this.nextHop.equals(other.nextHop))
+ return false;
+ if (this.nlri == null) {
+ if (other.nlri != null)
+ return false;
+ } else if (!this.nlri.equals(other.nlri))
+ return false;
+ if (this.reachable != other.reachable)
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("IPv4MP [reachable=");
+ builder.append(this.reachable);
+ builder.append(", nextHop=");
+ builder.append(this.nextHop);
+ builder.append(", nlri=");
+ builder.append(this.nlri);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ *
+ * MP_(UN)REACH_NLRI (basic, for IPv6)
+ *
+ */
+public class IPv6MP implements MPReach<Prefix<IPv6Address>> {
+
+ private final boolean reachable;
+
+ private final IPv6NextHop nextHop;
+
+ private final Set<Prefix<IPv6Address>> nlri;
+
+ public IPv6MP(final boolean reachable, final IPv6NextHop nextHop, final Set<Prefix<IPv6Address>> nlri) {
+ this.reachable = reachable;
+ this.nextHop = nextHop;
+ this.nlri = nlri;
+ }
+
+ @Override
+ public boolean isReachable() {
+ return this.reachable;
+ }
+
+ @Override
+ public Set<Prefix<IPv6Address>> getNlri() {
+ return this.nlri;
+ }
+
+ public IPv6NextHop getNextHop() {
+ return this.nextHop;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.nextHop == null) ? 0 : this.nextHop.hashCode());
+ result = prime * result + ((this.nlri == null) ? 0 : this.nlri.hashCode());
+ result = prime * result + (this.reachable ? 1231 : 1237);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof IPv6MP))
+ return false;
+ final IPv6MP other = (IPv6MP) obj;
+ if (this.nextHop == null) {
+ if (other.nextHop != null)
+ return false;
+ } else if (!this.nextHop.equals(other.nextHop))
+ return false;
+ if (this.nlri == null) {
+ if (other.nlri != null)
+ return false;
+ } else if (!this.nlri.equals(other.nlri))
+ return false;
+ if (this.reachable != other.reachable)
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("IPv6MP [reachable=");
+ builder.append(this.reachable);
+ builder.append(", nextHop=");
+ builder.append(this.nextHop);
+ builder.append(", nlri=");
+ builder.append(this.nlri);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import org.opendaylight.protocol.bgp.linkstate.AreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.DomainIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouteType;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+
+/**
+ * DTO for the subTlvs from Identifier TLV.
+ *
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-idr-ls-distribution-02#section-3.2.1">Identifier TLV</a>
+ */
+public class IdentifierTlv {
+
+ private final SourceProtocol sourceProtocol;
+
+ private final DomainIdentifier domainId;
+
+ private final AreaIdentifier areaId;
+
+ private final OSPFRouteType routeType;
+
+ private final TopologyIdentifier topologyId;
+
+ private final TopologyNodeInformation topologyNodeInfo;
+
+ public IdentifierTlv(final SourceProtocol sourceProtocol,
+ final DomainIdentifier domainId, final AreaIdentifier areaId,
+ final OSPFRouteType routeType, final TopologyIdentifier topologyId,
+ final TopologyNodeInformation topologyNodeInfo) {
+ this.sourceProtocol = sourceProtocol;
+ this.domainId = domainId;
+ this.areaId = areaId;
+ this.routeType = routeType;
+ this.topologyId = topologyId;
+ this.topologyNodeInfo = topologyNodeInfo;
+ }
+
+ /**
+ * @return the sourceProtocolId
+ */
+ public final SourceProtocol getSourceProtocol() {
+ return this.sourceProtocol;
+ }
+
+ /**
+ * @return the domainId
+ */
+ public final DomainIdentifier getDomainId() {
+ return this.domainId;
+ }
+
+ /**
+ * @return the areaId
+ */
+ public final AreaIdentifier getAreaId() {
+ return this.areaId;
+ }
+
+ /**
+ * @return the routeType
+ */
+ public final OSPFRouteType getRouteType() {
+ return this.routeType;
+ }
+
+ /**
+ * @return the topologyId
+ */
+ public final TopologyIdentifier getTopologyId() {
+ return this.topologyId;
+ }
+
+ /**
+ * @return the topologyNodeInfo
+ */
+ public final TopologyNodeInformation getTopologyNodeInfo() {
+ return this.topologyNodeInfo;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import java.util.Set;
+
+/**
+ *
+ * Common interface for MP_(UN)REACH Attribute.
+ *
+ * @param <T> Link State NLRI, T represents an Identifier
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4760">MultiProtocol Extensions for BGP-4</a>
+ */
+public interface MPReach<T> {
+
+ /**
+ * Determines if we have an MP_REACH or MP_UNREACH
+ *
+ * @return true if the object is MP_REACH, false if its MP_UNREACH
+ */
+ public boolean isReachable();
+
+ /**
+ *
+ * NLRI without Link-State information are just IP address prefixes, with Link-State inf. it can be also Network
+ * Links or Network Nodes.
+ *
+ * @return set of objects present in NLRI
+ */
+ public Set<T> getNlri();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+
+/**
+ * Path Attribute Object defines attributes to routes that are advertised
+ * through BGP. Each Attribute is a triplet <type, length, value>.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.3">BGP-4</a>
+ *
+ */
+public final class PathAttribute {
+
+ /**
+ * Currently known path attributes. Although AS4_PATH and AS4_AGGREGATOR
+ * will not be used, as this is a NEW BGP Speaker, they must be recognizable
+ * and an Update message that contains them, must be parsed properly.
+ *
+ * Added LINK_STATE to conform: <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-02#section-3.3">LINK_STATE Attribute</a>
+ * Added COMMUNITIES from: <a href="http://tools.ietf.org/html/rfc1997">COMMUNITIES Attribute</a>
+ * Added ORIGINATION_ID and CLUSTER_LIST from: <a href="http://tools.ietf.org/html/rfc4456">BGP Route Reflection</a>
+ */
+ public enum TypeCode {
+ ORIGIN, AS_PATH, NEXT_HOP, MULTI_EXIT_DISC, LOCAL_PREF, AGGREGATOR,
+ ATOMIC_AGGREGATE, MP_REACH_NLRI, MP_UNREACH_NLRI, EXTENDED_COMMUNITIES,
+ AS4_PATH, AS4_AGGREGATOR, LINK_STATE, COMMUNITIES, ORIGINATOR_ID,
+ CLUSTER_LIST;
+
+ /**
+ * Parse typecode from int to enum.
+ *
+ * @param type
+ * int parsed from byte array
+ * @return enum TypeCode
+ */
+ public static TypeCode parseType(final int type) {
+ switch (type) {
+ case 1:
+ return ORIGIN;
+ case 2:
+ return AS_PATH;
+ case 3:
+ return NEXT_HOP;
+ case 4:
+ return MULTI_EXIT_DISC;
+ case 5:
+ return LOCAL_PREF;
+ case 6:
+ return ATOMIC_AGGREGATE;
+ case 7:
+ return AGGREGATOR;
+ case 8:
+ return COMMUNITIES;
+ case 9:
+ return ORIGINATOR_ID;
+ case 10:
+ return CLUSTER_LIST;
+ case 14:
+ return MP_REACH_NLRI;
+ case 15:
+ return MP_UNREACH_NLRI;
+ case 16:
+ return EXTENDED_COMMUNITIES;
+ case 17:
+ return AS4_PATH;
+ case 18:
+ return AS4_AGGREGATOR;
+ case 99: //TODO: to actual value, after it is approved by IANA
+ return LINK_STATE;
+ default:
+ return null;
+ }
+ }
+ }
+
+ // Attribute type -------------------------------------------------------
+ /**
+ * Size of the flags field in path attribute, in bytes.
+ */
+ public static final int ATTR_FLAGS_SIZE = 1;
+
+ /**
+ * 0 - Optional bit: attribute is optional (if set to 1) or well-known (if
+ * set to 0)
+ */
+ private final boolean optional;
+
+ /**
+ * 1 - Transitive bit: attribute is transitive (if set to 1) or
+ * non-transitive (if set to 0)
+ */
+ private final boolean transitive;
+
+ /**
+ * 2 - Partial bit: attribute is partial (if set to 1) or complete (if set
+ * to 0)
+ */
+ private final boolean partial;
+
+ /**
+ * 3 - Extended Length bit: attribute length is one octet (if set to 0) or
+ * two octets (if set to 1)
+ */
+ private final boolean extendedLength;
+
+ /**
+ * Size of the field Attribute Type Code, in bytes.
+ */
+ public static final int ATTR_TYPE_CODE_SIZE = 1;
+
+ private TypeCode type;
+
+ // Attribute Length ------------------------------------------------------
+
+ /**
+ * Size of the attribute length field, in bytes. Depends on
+ * extendedLengthBit.
+ */
+ private final int attrLengthSize;
+
+ /**
+ * Length of the attribute value, in bytes.
+ */
+ private int length;
+
+ // -----------------------------------------------------------------------
+
+ /**
+ * Attribute value
+ */
+ private Object value;
+
+ // Constructors ----------------------------------------------------------
+
+ public PathAttribute(final boolean optional, final boolean transitive,
+ final boolean partial, final boolean extendedLength) {
+ this(null, optional, transitive, partial, extendedLength, null);
+ }
+
+ public PathAttribute(final TypeCode type, final boolean optional,
+ final boolean transitive, final boolean partial,
+ final boolean extendedLength, final Object value) {
+ this.type = type;
+ this.optional = optional;
+ this.transitive = transitive;
+ this.partial = partial;
+ this.extendedLength = extendedLength;
+ this.value = value;
+ this.attrLengthSize = (this.extendedLength) ? 2 : 1;
+ }
+
+ // Getters & setters -----------------------------------------------------
+
+ public TypeCode getType() {
+ return this.type;
+ }
+
+ public int getLength() {
+ return this.length;
+ }
+
+ public Object getValue() {
+ return this.value;
+ }
+
+ public int getAttrLengthSize() {
+ return this.attrLengthSize;
+ }
+
+ public void setType(final TypeCode type) {
+ this.type = type;
+ }
+
+ public void setValue(final Object value) {
+ this.value = value;
+ }
+
+ public void setLength(final int length) {
+ this.length = length;
+ }
+
+ public boolean isOptional() {
+ return this.optional;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PathAttribute [optional=");
+ builder.append(this.optional);
+ builder.append(", transitive=");
+ builder.append(this.transitive);
+ builder.append(", partial=");
+ builder.append(this.partial);
+ builder.append(", extendedLength=");
+ builder.append(this.extendedLength);
+ builder.append(", type=");
+ builder.append(this.type);
+ builder.append(", attrLengthSize=");
+ builder.append(this.attrLengthSize);
+ builder.append(", length=");
+ builder.append(this.length);
+ builder.append(", value=");
+ builder.append(this.value);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.attrLengthSize;
+ result = prime * result + (this.extendedLength ? 1231 : 1237);
+ result = prime * result + (this.optional ? 1231 : 1237);
+ result = prime * result + (this.partial ? 1231 : 1237);
+ result = prime * result + (this.transitive ? 1231 : 1237);
+ result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
+ result = prime * result + ((this.value == null) ? 0 : this.value.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PathAttribute other = (PathAttribute) obj;
+ if (this.attrLengthSize != other.attrLengthSize)
+ return false;
+ if (this.extendedLength != other.extendedLength)
+ return false;
+ if (this.optional != other.optional)
+ return false;
+ if (this.partial != other.partial)
+ return false;
+ if (this.transitive != other.transitive)
+ return false;
+ if (this.type != other.type)
+ return false;
+ if (this.value == null) {
+ if (other.value != null)
+ return false;
+ } else if (!this.value.equals(other.value))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message;
+
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for BGPNotification message.
+ */
+public final class BGPNotificationMessageParser {
+
+ private static final Logger logger = LoggerFactory.getLogger(BGPNotificationMessageParser.class);
+
+ private static final int ERROR_SIZE = 2; // bytes
+
+ private static class BGPErr {
+ private final int errorCode;
+ private final int errorSubcode;
+
+ public BGPErr(final int errorCode, final int errorSubcode) {
+ this.errorCode = errorCode;
+ this.errorSubcode = errorSubcode;
+ }
+
+ public int getErrorCode() {
+ return this.errorCode;
+ }
+
+ public int getErrorSubcode() {
+ return this.errorSubcode;
+ }
+ }
+
+ /**
+ * Serializes BGP Notification message.
+ *
+ * @param msg to be serialized
+ * @return BGP Notification message converted to byte array
+ */
+ public static byte[] put(final BGPNotificationMessage msg) {
+ if (msg == null)
+ throw new IllegalArgumentException("BGP Notification message cannot be null");
+ logger.trace("Started serializing Notification message: {}", msg);
+
+ final byte[] msgBody = (msg.getData() == null) ? new byte[ERROR_SIZE] : new byte[ERROR_SIZE + msg.getData().length];
+
+ final BGPErr numError = parseBGPError(msg.getError());
+
+ if (numError == null)
+ throw new IllegalArgumentException("Cannot parse BGP Error: " + msg.getError());
+
+ msgBody[0] = ByteArray.intToBytes(numError.getErrorCode())[Integer.SIZE / Byte.SIZE - 1];
+
+ msgBody[1] = ByteArray.intToBytes(numError.getErrorSubcode())[Integer.SIZE / Byte.SIZE - 1];
+
+ if (msg.getData() != null)
+ System.arraycopy(msg.getData(), 0, msgBody, ERROR_SIZE, msg.getData().length);
+ logger.trace("Notification message serialized to: {}", Arrays.toString(msgBody));
+ return msgBody;
+ }
+
+ /**
+ * Parses BGP Notification message to bytes.
+ *
+ * @param bytes byte array to be parsed
+ * @return BGPNotification message
+ * @throws BGPDocumentedException
+ */
+ public static BGPNotificationMessage parse(final byte[] bytes) throws BGPDocumentedException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array cannot be null or empty.");
+ logger.trace("Started parsing of notification message: {}", Arrays.toString(bytes));
+
+ if (bytes.length < ERROR_SIZE)
+ throw new BGPDocumentedException("Notification message too small.", BGPError.BAD_MSG_LENGTH, ByteArray.intToBytes(bytes.length));
+ final int errorCode = UnsignedBytes.toInt(bytes[0]);
+ final int errorSubcode = UnsignedBytes.toInt(bytes[1]);
+
+ final BGPError err = putBGPError(new BGPErr(errorCode, errorSubcode));
+ byte[] data = null;
+ if (bytes.length > ERROR_SIZE) {
+ data = ByteArray.subByte(bytes, ERROR_SIZE, bytes.length - ERROR_SIZE);
+ }
+ logger.trace("Notification message was parsed: err = {}, data = {}.", err, Arrays.toString(data));
+ return (data == null) ? new BGPNotificationMessage(err) : new BGPNotificationMessage(err, data);
+ }
+
+ private static BGPErr parseBGPError(final BGPError err) {
+ switch (err) {
+ case CONNECTION_NOT_SYNC:
+ return new BGPErr(1, 1);
+ case BAD_MSG_LENGTH:
+ return new BGPErr(1, 2);
+ case BAD_MSG_TYPE:
+ return new BGPErr(1, 3);
+ case UNSPECIFIC_OPEN_ERROR:
+ return new BGPErr(2, 0);
+ case VERSION_NOT_SUPPORTED:
+ return new BGPErr(2, 1);
+ case BAD_PEER_AS:
+ return new BGPErr(2, 2);
+ case BAD_BGP_ID:
+ return new BGPErr(2, 3);
+ case OPT_PARAM_NOT_SUPPORTED:
+ return new BGPErr(2, 4);
+ case HOLD_TIME_NOT_ACC:
+ return new BGPErr(2, 6);
+ case MALFORMED_ATTR_LIST:
+ return new BGPErr(3, 1);
+ case WELL_KNOWN_ATTR_NOT_RECOGNIZED:
+ return new BGPErr(3, 2);
+ case WELL_KNOWN_ATTR_MISSING:
+ return new BGPErr(3, 3);
+ case ATTR_FLAGS_MISSING:
+ return new BGPErr(3, 4);
+ case ATTR_LENGTH_ERROR:
+ return new BGPErr(3, 5);
+ case ORIGIN_ATTR_NOT_VALID:
+ return new BGPErr(3, 6);
+ case NEXT_HOP_NOT_VALID:
+ return new BGPErr(3, 8);
+ case OPT_ATTR_ERROR:
+ return new BGPErr(3, 9);
+ case NETWORK_NOT_VALID:
+ return new BGPErr(3, 10);
+ case AS_PATH_MALFORMED:
+ return new BGPErr(3, 11);
+ case HOLD_TIMER_EXPIRED:
+ return new BGPErr(4, 0);
+ case FSM_ERROR:
+ return new BGPErr(5, 0);
+ case CEASE:
+ return new BGPErr(6, 0);
+ default:
+ return null;
+ }
+ }
+
+ private static BGPError putBGPError(final BGPErr err) {
+ final int e = err.getErrorCode();
+ final int s = err.getErrorSubcode();
+ if (e == 1) {
+ if (s == 1)
+ return BGPError.CONNECTION_NOT_SYNC;
+ if (s == 2)
+ return BGPError.BAD_MSG_LENGTH;
+ if (s == 3)
+ return BGPError.BAD_MSG_TYPE;
+ } else if (e == 2) {
+ if (s == 0)
+ return BGPError.UNSPECIFIC_OPEN_ERROR;
+ if (s == 1)
+ return BGPError.VERSION_NOT_SUPPORTED;
+ if (s == 2)
+ return BGPError.BAD_PEER_AS;
+ if (s == 3)
+ return BGPError.BAD_BGP_ID;
+ if (s == 4)
+ return BGPError.OPT_PARAM_NOT_SUPPORTED;
+ if (s == 6)
+ return BGPError.HOLD_TIME_NOT_ACC;
+ } else if (e == 3) {
+ if (s == 1)
+ return BGPError.MALFORMED_ATTR_LIST;
+ if (s == 2)
+ return BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED;
+ if (s == 3)
+ return BGPError.WELL_KNOWN_ATTR_MISSING;
+ if (s == 4)
+ return BGPError.ATTR_FLAGS_MISSING;
+ if (s == 5)
+ return BGPError.ATTR_LENGTH_ERROR;
+ if (s == 6)
+ return BGPError.ORIGIN_ATTR_NOT_VALID;
+ if (s == 8)
+ return BGPError.NEXT_HOP_NOT_VALID;
+ if (s == 9)
+ return BGPError.OPT_ATTR_ERROR;
+ if (s == 10)
+ return BGPError.NETWORK_NOT_VALID;
+ if (s == 11)
+ return BGPError.AS_PATH_MALFORMED;
+ } else if (e == 4)
+ return BGPError.HOLD_TIMER_EXPIRED;
+ else if (e == 5)
+ return BGPError.FSM_ERROR;
+ else if (e == 6)
+ return BGPError.CEASE;
+ throw new IllegalArgumentException("BGP Error code " + e + " and subcode " + s + " not recognized.");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.message.open.BGPParameterParser;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for BGP Open message.
+ */
+public final class BGPOpenMessageParser {
+
+ private static final Logger logger = LoggerFactory.getLogger(BGPOpenMessageParser.class);
+
+ private static final int VERSION_SIZE = 1;
+ private static final int AS_SIZE = 2;
+ private static final int HOLD_TIME_SIZE = 2;
+ private static final int BGP_ID_SIZE = 4;
+ private static final int OPT_PARAM_LENGTH_SIZE = 1;
+
+ private static final int MIN_MSG_LENGTH = VERSION_SIZE + AS_SIZE + HOLD_TIME_SIZE + BGP_ID_SIZE + OPT_PARAM_LENGTH_SIZE;
+
+ private BGPOpenMessageParser() {
+
+ }
+
+ /**
+ * Serializes given BGP Open message to byte array, without the header.
+ *
+ * @param msg BGP Open message to be serialized.
+ * @return BGP Open message converted to byte array
+ */
+ public static byte[] put(final BGPOpenMessage msg) {
+ if (msg == null)
+ throw new IllegalArgumentException("BGPOpen message cannot be null");
+ logger.trace("Started serializing open message: {}", msg);
+
+ final Map<byte[], Integer> optParams = Maps.newHashMap();
+
+ int optParamsLength = 0;
+
+ if (msg.getOptParams() != null) {
+ for (final BGPParameter param : msg.getOptParams()) {
+ final byte[] p = BGPParameterParser.put(param);
+ optParams.put(p, p.length);
+ optParamsLength += p.length;
+ }
+ }
+
+ final byte[] msgBody = (msg.getOptParams() == null || msg.getOptParams().isEmpty()) ? new byte[MIN_MSG_LENGTH]
+ : new byte[MIN_MSG_LENGTH + optParamsLength];
+
+ int offset = 0;
+
+ msgBody[offset] = ByteArray.intToBytes(BGPOpenMessage.BGP_VERSION)[(Integer.SIZE / Byte.SIZE) - 1];
+ offset += VERSION_SIZE;
+
+ // When our AS number does not fit into two bytes, we report it as AS_TRANS
+ ASNumber openAS = msg.getMyAS();
+ if (openAS.getHighValue() != 0)
+ openAS = ASNumber.TRANS;
+
+ System.arraycopy(ByteArray.intToBytes(openAS.getLowValue()), 2, msgBody, offset, AS_SIZE);
+ offset += AS_SIZE;
+
+ System.arraycopy(ByteArray.shortToBytes(msg.getHoldTime()), 0, msgBody, offset, HOLD_TIME_SIZE);
+ offset += HOLD_TIME_SIZE;
+
+ System.arraycopy(msg.getBgpId().getAddress(), 0, msgBody, offset, BGP_ID_SIZE);
+ offset += BGP_ID_SIZE;
+
+ msgBody[offset] = ByteArray.intToBytes(optParamsLength)[Integer.SIZE / Byte.SIZE - 1];
+
+ int index = MIN_MSG_LENGTH;
+ if (optParams != null) {
+ for (final Entry<byte[], Integer> entry : optParams.entrySet()) {
+ System.arraycopy(entry.getKey(), 0, msgBody, index, entry.getValue());
+ index += entry.getValue();
+ }
+ }
+ logger.trace("Open message serialized to: {}", Arrays.toString(msgBody));
+ return msgBody;
+ }
+
+ /**
+ * Parses given byte array to BGP Open message
+ *
+ * @param bytes byte array representing BGP Open message, without header
+ * @return BGP Open Message
+ * @throws BGPDocumentedException if the parsing was unsuccessful
+ */
+ public static BGPOpenMessage parse(final byte[] bytes) throws BGPDocumentedException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array cannot be null or empty.");
+ logger.trace("Started parsing of open message: {}", Arrays.toString(bytes));
+
+ if (bytes.length < MIN_MSG_LENGTH)
+ throw new BGPDocumentedException("Open message too small.", BGPError.BAD_MSG_LENGTH, ByteArray.intToBytes(bytes.length));
+ if (UnsignedBytes.toInt(bytes[0]) != BGPOpenMessage.BGP_VERSION)
+ throw new BGPDocumentedException("BGP Protocol version " + UnsignedBytes.toInt(bytes[0]) + " not supported.", BGPError.VERSION_NOT_SUPPORTED, ByteArray.subByte(
+ ByteArray.intToBytes(BGPOpenMessage.BGP_VERSION), 2, 2));
+
+ int offset = VERSION_SIZE;
+ final ASNumber as = new ASNumber(0, ByteArray.bytesToInt(ByteArray.subByte(bytes, offset, AS_SIZE)));
+ offset += AS_SIZE;
+
+ // TODO: BAD_PEER_AS Error: when is an AS unacceptable?
+
+ final short holdTime = ByteArray.bytesToShort(ByteArray.subByte(bytes, offset, HOLD_TIME_SIZE));
+ offset += HOLD_TIME_SIZE;
+ if (holdTime == 1 || holdTime == 2)
+ throw new BGPDocumentedException("Hold time value not acceptable.", BGPError.HOLD_TIME_NOT_ACC);
+
+ IPv4Address bgpId = null;
+ try {
+ bgpId = new IPv4Address(ByteArray.subByte(bytes, offset, BGP_ID_SIZE));
+ } catch (final IllegalArgumentException e) {
+ throw new BGPDocumentedException("BGP Identifier is not a valid IPv4 Address", BGPError.BAD_BGP_ID);
+ }
+ offset += BGP_ID_SIZE;
+
+ final int optLength = UnsignedBytes.toInt(bytes[offset]);
+
+ List<BGPParameter> optParams = Lists.newArrayList();
+ if (optLength > 0) {
+ try {
+ optParams = BGPParameterParser.parse(ByteArray.subByte(bytes, MIN_MSG_LENGTH, optLength));
+ } catch (final BGPParsingException e) {
+ throw new BGPDocumentedException("Optional parameter not parsed: ." + e.getMessage(), BGPError.UNSPECIFIC_OPEN_ERROR);
+ }
+ }
+ logger.trace("Open message was parsed: AS = {}, holdTimer = {}, bgpId = {}, optParams = {}", as, holdTime, bgpId, optParams);
+ return new BGPOpenMessage(as, holdTime, bgpId, optParams);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateEvent;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateEventBuilder;
+import org.opendaylight.protocol.bgp.parser.impl.IPv6MP;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute.TypeCode;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.PathAttributeParser;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.collect.Lists;
+
+/**
+ * LENGTH fields, that denote the length of the fields with variable length, have fixed SIZE.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4271#section-4.3">BGP-4 Update Message Format</a>
+ *
+ */
+public class BGPUpdateMessageParser {
+
+ private static Logger logger = LoggerFactory.getLogger(BGPUpdateMessageParser.class);
+
+ /**
+ * Size of the withdrawn_routes_length field, in bytes.
+ */
+ public static final int WITHDRAWN_ROUTES_LENGTH_SIZE = 2;
+
+ /**
+ * Size of the total_path_attr_length field, in bytes.
+ */
+ public static final int TOTAL_PATH_ATTR_LENGTH_SIZE = 2;
+
+ // Constructors -------------------------------------------------------
+
+ public BGPUpdateMessageParser() {
+
+ }
+
+ // Getters & setters --------------------------------------------------
+
+ public static BGPUpdateEvent parse(final byte[] bytes, final int msgLength) throws BGPDocumentedException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array cannot be null or empty.");
+ logger.trace("Started parsing of update message: {}", Arrays.toString(bytes));
+
+ int byteOffset = 0;
+
+ final int withdrawnRoutesLength = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, WITHDRAWN_ROUTES_LENGTH_SIZE));
+ byteOffset += WITHDRAWN_ROUTES_LENGTH_SIZE;
+
+ final BGPUpdateEventBuilder eventBuilder = new BGPUpdateEventBuilder();
+ eventBuilder.setWithdrawnRoutesLength(withdrawnRoutesLength);
+
+ Set<Prefix<IPv4Address>> withdrawnRoutes;
+ if (withdrawnRoutesLength > 0) {
+ withdrawnRoutes = IPv4.FAMILY.prefixListForBytes(ByteArray.subByte(bytes, byteOffset, withdrawnRoutesLength));
+ byteOffset += withdrawnRoutesLength;
+ } else {
+ withdrawnRoutes = Collections.emptySet();
+ }
+ eventBuilder.setWithdrawnRoutes(withdrawnRoutes);
+
+ final int totalPathAttrLength = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TOTAL_PATH_ATTR_LENGTH_SIZE));
+ byteOffset += TOTAL_PATH_ATTR_LENGTH_SIZE;
+ eventBuilder.setTotalPathAttrLength(totalPathAttrLength);
+
+ if (withdrawnRoutesLength + totalPathAttrLength + BGPMessageHeader.COMMON_HEADER_LENGTH > msgLength)
+ throw new BGPDocumentedException("Message length inconsistent with withdrawn router length.", BGPError.MALFORMED_ATTR_LIST);
+
+ if (withdrawnRoutesLength == 0 && totalPathAttrLength == 0) {
+ final BGPUpdateSynchronized event = new BGPUpdateSynchronized() {
+
+ private static final long serialVersionUID = 5709361453437508337L;
+
+ @Override
+ public BGPTableType getTableType() {
+ return new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+ }
+ };
+ return event;
+ }
+
+ List<PathAttribute> pathAttributes;
+ if (totalPathAttrLength > 0) {
+ pathAttributes = parsePathAttributes(ByteArray.subByte(bytes, byteOffset, totalPathAttrLength));
+ byteOffset += totalPathAttrLength;
+ if (pathAttributes.get(0).getType() == TypeCode.MP_UNREACH_NLRI && totalPathAttrLength == 6) {
+ if (pathAttributes.get(0).getValue() instanceof IPv6MP) {
+ final BGPUpdateEvent event = new BGPUpdateSynchronized() {
+
+ private static final long serialVersionUID = -6026212683738125407L;
+
+ @Override
+ public BGPTableType getTableType() {
+ return new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast);
+ }
+
+ };
+ return event;
+ } else if (pathAttributes.get(0).getValue() == null) {
+ final BGPUpdateSynchronized event = new BGPUpdateSynchronized() {
+
+ private static final long serialVersionUID = 5888562784007786559L;
+
+ @Override
+ public BGPTableType getTableType() {
+ return new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Unicast);
+ }
+
+ };
+ return event;
+ }
+ }
+ } else {
+ pathAttributes = Collections.emptyList();
+ }
+ eventBuilder.setPathAttributes(pathAttributes);
+
+ final Set<Prefix<IPv4Address>> nlri = IPv4.FAMILY.prefixListForBytes(ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset));
+ eventBuilder.setNlri(nlri);
+
+ try {
+ logger.trace("Update message was parsed.");
+ return eventBuilder.buildEvent();
+ } catch (final BGPParsingException e) {
+ throw new BGPDocumentedException("Parsing unsuccessful: {}" + e.getMessage(), BGPError.MALFORMED_ATTR_LIST);
+ }
+ }
+
+ /**
+ * Parse different Path Attributes from given bytes.
+ *
+ * @param bytes byte array to be parsed
+ * @return list of Path Attributes
+ * @throws BGPParsingException
+ */
+ private static List<PathAttribute> parsePathAttributes(byte[] bytes) throws BGPDocumentedException {
+ if (bytes.length == 0) {
+ return Collections.emptyList();
+ }
+ final List<PathAttribute> list = Lists.newArrayList();
+ while (bytes.length != 0) {
+ PathAttribute attr;
+ try {
+ attr = PathAttributeParser.parseAttribute(bytes);
+ bytes = ByteArray.cutBytes(bytes,
+ PathAttribute.ATTR_FLAGS_SIZE + PathAttribute.ATTR_TYPE_CODE_SIZE + attr.getAttrLengthSize() + attr.getLength());
+ list.add(attr);
+ } catch (final BGPParsingException e) {
+ logger.warn("Could not parse BGP attributes: {}", e.getMessage(), e);
+ throw new BGPDocumentedException("Could not parse BGP attributes.", BGPError.MALFORMED_ATTR_LIST);
+ }
+ }
+ return list;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message.open;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.parameter.CapabilityParameter;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for parameters in BGP Open message.
+ */
+public final class BGPParameterParser {
+
+ private static final Logger logger = LoggerFactory.getLogger(BGPParameterParser.class);
+
+ private static final int TYPE_SIZE = 1; // bytes
+ private static final int LENGTH_SIZE = 1; // bytes
+ private static final int CAPABILITIES_OPT_PARAM_TYPE = 2;
+
+ private BGPParameterParser() {
+
+ }
+
+ /**
+ * Serializes given BGP Parameter to byte array. Currently supported only Capability parameters.
+ *
+ * @param param BGP Parameter to be serialized
+ * @return BGP Parameter converted to byte array
+ */
+ public static byte[] put(final BGPParameter param) {
+ if (param == null)
+ throw new IllegalArgumentException("BGP Parameter cannot be null");
+ logger.trace("Started serializing BGPParameter: {}", param);
+
+ byte[] value = null;
+
+ if (param instanceof CapabilityParameter) {
+ value = CapabilityParameterParser.put((CapabilityParameter) param);
+ } else {
+ logger.debug("BGP Parameter not supported.");
+ return new byte[] {};
+ }
+
+ final byte[] bytes = new byte[TYPE_SIZE + LENGTH_SIZE + value.length];
+ System.arraycopy(ByteArray.intToBytes(param.getType()), 3, bytes, 0, TYPE_SIZE);
+ System.arraycopy(ByteArray.intToBytes(value.length), 3, bytes, TYPE_SIZE, LENGTH_SIZE);
+ System.arraycopy(value, 0, bytes, TYPE_SIZE + LENGTH_SIZE, value.length);
+ logger.trace("BGP Parameter serialized to: {}", Arrays.toString(bytes));
+ return bytes;
+ }
+
+ /**
+ * Parses given byte array to a list of BGP Parameters. Currently supporting only Capability parameters.
+ *
+ * @param bytes byte array representing BGP Parameters
+ * @return list of BGP Parameters
+ * @throws BGPParsingException if the parsing was unsuccessful
+ */
+ public static List<BGPParameter> parse(final byte[] bytes) throws BGPParsingException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array cannot be null or empty.");
+ logger.trace("Started parsing of BGP parameter: {}", Arrays.toString(bytes));
+ int byteOffset = 0;
+ final List<BGPParameter> params = Lists.newArrayList();
+ while (byteOffset < bytes.length) {
+ final int paramType = UnsignedBytes.toInt(bytes[byteOffset++]);
+ final int paramLength = UnsignedBytes.toInt(bytes[byteOffset++]);
+ if (paramType == CAPABILITIES_OPT_PARAM_TYPE) {
+ final BGPParameter param = CapabilityParameterParser.parse(ByteArray.subByte(bytes, byteOffset, paramLength));
+ if (param != null)
+ params.add(param);
+ } else
+ logger.debug("BGP Parameter not recognized. Type: {}", paramType);
+ byteOffset += paramLength;
+ }
+ logger.trace("Parsed BGP parameters: {}", Arrays.toString(params.toArray()));
+ return params;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message.open;
+
+import java.util.Arrays;
+import java.util.Map.Entry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.MPReachParser;
+import org.opendaylight.protocol.bgp.parser.parameter.AS4BytesCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.CapabilityParameter;
+import org.opendaylight.protocol.bgp.parser.parameter.GracefulCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for BGP Capability Parameter.
+ */
+public final class CapabilityParameterParser {
+
+ private static final Logger logger = LoggerFactory.getLogger(CapabilityParameterParser.class);
+
+ private static final int CODE_SIZE = 1; // bytes
+ private static final int LENGTH_SIZE = 1; // bytes
+ private static final int AFI_SIZE = 2; // bytes
+ private static final int SAFI_SIZE = 1; // bytes
+
+ private CapabilityParameterParser() {
+
+ }
+
+ /**
+ * Serializes given BGP Capability Parameter to byte array.
+ *
+ * @param param BGP Capability to be serialized
+ * @return BGP Capability converted to byte array
+ */
+ public static byte[] put(final CapabilityParameter cap) {
+ if (cap == null)
+ throw new IllegalArgumentException("BGP Capability cannot be null");
+ logger.trace("Started serializing BGP Capability: {}", cap);
+ byte[] value = null;
+ if (cap instanceof MultiprotocolCapability) {
+ value = putMultiProtocolParameterValue((MultiprotocolCapability) cap);
+ } else if (cap instanceof GracefulCapability) {
+ value = putGracefulParameterValue((GracefulCapability) cap);
+ } else if (cap instanceof AS4BytesCapability) {
+ value = putAS4BytesParameterValue((AS4BytesCapability) cap);
+ }
+ final byte[] bytes = new byte[CODE_SIZE + LENGTH_SIZE + value.length];
+ bytes[0] = ByteArray.intToBytes(cap.getCode())[Integer.SIZE / Byte.SIZE - 1];
+ bytes[1] = ByteArray.intToBytes(value.length)[Integer.SIZE / Byte.SIZE - 1];
+ System.arraycopy(value, 0, bytes, CODE_SIZE + LENGTH_SIZE, value.length);
+ logger.trace("BGP Parameter serialized to: {}", Arrays.toString(bytes));
+ return bytes;
+ }
+
+ /**
+ * Parses given byte array to Capability Parameter. Only Multiprotocol capability is supported.
+ *
+ * @param bytes byte array representing BGP Parameters
+ * @return list of BGP Parameters
+ * @throws BGPParsingException if the parsing was unsuccessful
+ */
+ public static CapabilityParameter parse(final byte[] bytes) throws BGPParsingException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array cannot be null or empty.");
+ logger.trace("Started parsing of BGP Capability: {}", Arrays.toString(bytes));
+ int byteOffset = 0;
+ final int capCode = UnsignedBytes.toInt(bytes[byteOffset++]);
+ final int capLength = UnsignedBytes.toInt(bytes[byteOffset++]);
+ if (capCode == MultiprotocolCapability.CODE) {
+ logger.trace("Parsed BGP Capability.");
+ return parseMultiProtocolParameterValue(ByteArray.subByte(bytes, byteOffset, capLength));
+ } else if (capCode == AS4BytesCapability.CODE) {
+ logger.trace("Parsed AS4B Capability.");
+ return parseAS4BParameterValue(ByteArray.subByte(bytes, byteOffset, capLength));
+ } else
+ logger.debug("Only Multiprotocol Capability Parameter is supported. Received code {}", capCode);
+ return null;
+ }
+
+ private static byte[] putGracefulParameterValue(final GracefulCapability param) {
+ final int RESTART_FLAGS_SIZE = 4; // bits
+ final int TIMER_SIZE = 12; // bits
+ final int AFI_SIZE = 2; // bytes
+ final int SAFI_SIZE = 1; // bytes
+ final int AF_FLAGS_SIZE = 1; // bytes
+ final byte[] bytes = new byte[(RESTART_FLAGS_SIZE + TIMER_SIZE + (AFI_SIZE * Byte.SIZE + SAFI_SIZE * Byte.SIZE + AF_FLAGS_SIZE
+ * Byte.SIZE)
+ * param.getTableTypes().size())
+ / Byte.SIZE];
+ if (param.isRestartFlag())
+ bytes[0] = (byte) 0x80;
+ int index = (RESTART_FLAGS_SIZE + TIMER_SIZE) / Byte.SIZE;
+ for (final Entry<BGPTableType, Boolean> entry : param.getTableTypes().entrySet()) {
+ final byte[] a = putAfi(entry.getKey().getAddressFamily());
+ final byte s = putSafi(entry.getKey().getSubsequentAddressFamily());
+ final byte f = (entry.getValue()) ? (byte) 0x80 : (byte) 0x00;
+ System.arraycopy(a, 0, bytes, index, AFI_SIZE);
+ index += AFI_SIZE;
+ bytes[index] = s;
+ index += SAFI_SIZE;
+ bytes[index] = f;
+ index += AF_FLAGS_SIZE;
+ }
+ return bytes;
+ }
+
+ private static byte[] putMultiProtocolParameterValue(final MultiprotocolCapability param) {
+ final byte[] a = putAfi(param.getAfi());
+ final byte s = putSafi(param.getSafi());
+
+ final byte[] bytes = new byte[AFI_SIZE + SAFI_SIZE + 1]; // 2 byte is reserved 2B AFI + 1B Reserved + 1B SAFI
+ System.arraycopy(a, 0, bytes, 0, AFI_SIZE);
+ bytes[AFI_SIZE + 1] = s; // +1 = reserved
+ return bytes;
+ }
+
+ private static byte[] putAS4BytesParameterValue(final AS4BytesCapability param) {
+ return ByteArray.subByte(ByteArray.longToBytes(param.getASNumber().getAsn()), 4, 4);
+ }
+
+ private static MultiprotocolCapability parseMultiProtocolParameterValue(final byte[] bytes) throws BGPParsingException {
+ final BGPAddressFamily afi = MPReachParser.parseAfi(ByteArray.bytesToInt(ByteArray.subByte(bytes, 0, AFI_SIZE)));
+ final BGPSubsequentAddressFamily safi = MPReachParser.parseSafi(ByteArray.bytesToInt(ByteArray.subByte(bytes, AFI_SIZE + 1,
+ SAFI_SIZE)));
+ return new MultiprotocolCapability(new BGPTableType(afi, safi));
+ }
+
+ private static AS4BytesCapability parseAS4BParameterValue(final byte[] bytes) {
+ return new AS4BytesCapability(new ASNumber(ByteArray.bytesToLong(bytes)));
+ }
+
+ static byte[] putAfi(final BGPAddressFamily afi) {
+ final byte[] a = ByteArray.intToBytes(serializeAfi(afi));
+ return ByteArray.subByte(a, Integer.SIZE / Byte.SIZE - AFI_SIZE, AFI_SIZE);
+ }
+
+ static byte putSafi(final BGPSubsequentAddressFamily safi) {
+ final byte[] a = ByteArray.intToBytes(serializeSafi(safi));
+ return ByteArray.subByte(a, Integer.SIZE / Byte.SIZE - SAFI_SIZE, SAFI_SIZE)[0];
+ }
+
+ private static int serializeSafi(final BGPSubsequentAddressFamily type) {
+ switch (type) {
+ case Unicast:
+ return 1;
+ case MPLSLabeledVPN:
+ return 128;
+ case Linkstate:
+ return MPReachParser.LS_SAFI;
+ }
+ return 0;
+ }
+
+ private static int serializeAfi(final BGPAddressFamily type) {
+ switch (type) {
+ case IPv4:
+ return 1;
+ case IPv6:
+ return 2;
+ case LinkState:
+ return MPReachParser.LS_AFI;
+ }
+ return 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message.update;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ *
+ * Representation of one AS Path Segment. It is, in fact, a TLV, but the length
+ * field is representing the count of AS Numbers in the collection (in its
+ * value). If the segment is of type AS_SEQUENCE, the collection is a List, if
+ * AS_SET, the collection is a Set.
+ *
+ */
+public class AsPathSegmentParser {
+
+ public static final int TYPE_LENGTH = 1; // bytes
+
+ public static final int LENGTH_SIZE = 1; // bytes
+
+ public static final int AS_NUMBER_LENGTH = 4; // bytes
+
+ /**
+ * Possible types of AS Path segments.
+ */
+ public enum SegmentType {
+ AS_SEQUENCE, AS_SET
+ }
+
+ private AsPathSegmentParser() {
+
+ }
+
+ static SegmentType parseType(final int type) {
+ switch (type) {
+ case 1:
+ return SegmentType.AS_SET;
+ case 2:
+ return SegmentType.AS_SEQUENCE;
+ default:
+ return null;
+ }
+ }
+
+ static Collection<ASNumber> parseAsPathSegment(final SegmentType type,
+ final int count, final byte[] bytes) {
+ final Collection<ASNumber> coll = (type == SegmentType.AS_SEQUENCE) ? new ArrayList<ASNumber>()
+ : new HashSet<ASNumber>();
+ int byteOffset = 0;
+ for (int i = 0; i < count; i++) {
+ coll.add(new ASNumber(ByteArray.bytesToLong(ByteArray.subByte(
+ bytes, byteOffset, AS_NUMBER_LENGTH))));
+ byteOffset += AS_NUMBER_LENGTH;
+ }
+ return coll;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message.update;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.bgp.concepts.ASSpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.Inet4SpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.OpaqueExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteOriginCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteTargetCommunity;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for Extended Communities Path Attribute.
+ */
+public class CommunitiesParser {
+
+ public static final int EXTENDED_COMMUNITY_LENGTH = 8; // bytes
+
+ public static final int COMMUNITY_LENGTH = 4; // bytes
+
+ private static final int TYPE_LENGTH = 2; // bytes
+
+ private static final int AS_NUMBER_LENGTH = 2; // bytes
+
+ private static final int AS_LOCAL_ADMIN_LENGTH = 4; // bytes
+
+ private CommunitiesParser() {
+
+ }
+
+ /**
+ * Parse known Community, if unknown, a new one will be created.
+ *
+ * @param bytes byte array to be parsed
+ * @return new Community
+ * @throws BGPDocumentedException
+ */
+ static Community parseCommunity(final byte[] bytes) throws BGPDocumentedException {
+ if (bytes.length != COMMUNITY_LENGTH)
+ throw new BGPDocumentedException("Community with wrong length: " + bytes.length, BGPError.OPT_ATTR_ERROR);
+ if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x01 })) {
+ return Community.NO_EXPORT;
+ } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x02 })) {
+ return Community.NO_ADVERTISE;
+ } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x03 })) {
+ return Community.NO_EXPORT_SUBCONFED;
+ }
+ return new Community(new ASNumber(ByteArray.bytesToLong(Arrays.copyOfRange(bytes, 0, AS_NUMBER_LENGTH))), ByteArray.bytesToInt(Arrays.copyOfRange(
+ bytes, AS_NUMBER_LENGTH, AS_NUMBER_LENGTH + AS_NUMBER_LENGTH)));
+ }
+
+ /**
+ * Parse Extended Community according to their type.
+ *
+ * @param bytes byte array to be parsed
+ * @return new Specific Extended Community
+ * @throws BGPDocumentedException if the type is not recognized
+ */
+ @VisibleForTesting
+ public static ExtendedCommunity parseExtendedCommunity(final byte[] bytes) throws BGPDocumentedException {
+ // final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, 0, TYPE_LENGTH));
+ final int type = UnsignedBytes.toInt(bytes[0]);
+ final int subType = UnsignedBytes.toInt(bytes[1]);
+ final byte[] value = ByteArray.subByte(bytes, TYPE_LENGTH, bytes.length - TYPE_LENGTH);
+ switch (type) {
+ case 0:
+ if (subType == 2) {
+ return new RouteTargetCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+ value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+ } else if (subType == 3) {
+ return new RouteOriginCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+ value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+ } else
+ return new ASSpecificExtendedCommunity(false, subType, new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0,
+ AS_NUMBER_LENGTH))), ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+ case 40: // 01000000
+ return new ASSpecificExtendedCommunity(true, subType, new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0,
+ AS_NUMBER_LENGTH))), ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+ case 2:
+ if (subType == 2) {
+ return new RouteTargetCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+ value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+ } else if (subType == 3) {
+ return new RouteOriginCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+ value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+ } else
+ throw new BGPDocumentedException("Could not parse Extended Community subtype: " + subType, BGPError.OPT_ATTR_ERROR);
+ case 1:
+ if (subType == 2) {
+ return new RouteTargetCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+ value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+ } else if (subType == 3) {
+ return new RouteOriginCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
+ value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
+ } else
+ return new Inet4SpecificExtendedCommunity(false, subType, new IPv4Address(ByteArray.subByte(value, 0, 4)), ByteArray.subByte(
+ value, 4, 2));
+ case 41: // 01000001
+ return new Inet4SpecificExtendedCommunity(true, subType, new IPv4Address(ByteArray.subByte(value, 0, 4)), ByteArray.subByte(
+ value, 4, 2));
+ case 3:
+ return new OpaqueExtendedCommunity(false, subType, value);
+ case 43: // 01000011
+ return new OpaqueExtendedCommunity(true, subType, value);
+ default:
+ throw new BGPDocumentedException("Could not parse Extended Community type: " + type, BGPError.OPT_ATTR_ERROR);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message.update;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedSet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.BGPLinkMP;
+import org.opendaylight.protocol.bgp.parser.impl.BGPNodeMP;
+import org.opendaylight.protocol.bgp.parser.impl.ByteList;
+import org.opendaylight.protocol.bgp.parser.impl.MPReach;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.bgp.linkstate.AdministrativeGroup;
+import org.opendaylight.protocol.bgp.linkstate.AreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.DomainIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ExtendedRouteTag;
+import org.opendaylight.protocol.bgp.linkstate.IPv4InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv4RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISLANIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkAnchor;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.MPLSProtocol;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFInterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFPrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouteType;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFv3LANIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouteTag;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import org.opendaylight.protocol.bgp.linkstate.UnnumberedLinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISNetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.OSPFNetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkImpl;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeImpl;
+import com.google.common.base.Charsets;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for Link State information.
+ *
+ * @see <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-01">BGP-LS draft</a>
+ */
+public class LinkStateParser {
+
+ private static final Logger logger = LoggerFactory.getLogger(LinkStateParser.class);
+
+ private static final int TYPE_LENGTH = 2;
+
+ private static final int LENGTH_SIZE = 2;
+
+ private static final int ROUTE_DISTINGUISHER_LENGTH = 8;
+
+ private static final int PROTOCOL_ID_LENGTH = 1;
+
+ private static final int IDENTIFIER_LENGTH = 8;
+
+ private static final Set<Integer> nodeTlvs = Sets.newHashSet(263, 1024, 1025, 1026, 1027, 1028, 1029);
+
+ private static final Set<Integer> linkTlvs = Sets.newHashSet(1028, 1029, 1030, 1031, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095,
+ 1096, 1097, 1098);
+
+ private static final Set<Integer> prefixTlvs = Sets.newHashSet(1152, 1153, 1154, 1155, 1156, 1157);
+
+ private enum NlriType {
+ LinkNLRI, NodeNLRI, IPv4Prefixes, IPv6Prefixes
+ }
+
+ private LinkStateParser() {
+ }
+
+ /**
+ * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
+ *
+ * @param reachable
+ * @param safi
+ * @param bytes
+ * @return BGPLinkMP or BGPNodeMP
+ * @throws BGPParsingException
+ */
+ protected static MPReach<?> parseLSNlri(final boolean reachable, final BGPSubsequentAddressFamily safi, final NextHop<?> nextHop,
+ final byte[] bytes) throws BGPParsingException {
+ if (bytes.length == 0)
+ return null;
+ int byteOffset = 0;
+ final Set<LinkIdentifier> links = Sets.newHashSet();
+ final Set<NodeIdentifier> nodes = Sets.newHashSet();
+ final Set<PrefixIdentifier<?>> descs = Sets.newHashSet();
+
+ long identifier = 0;
+ SourceProtocol sp = null;
+
+ while (byteOffset != bytes.length) {
+ final NlriType type = parseNLRItype(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH)));
+ byteOffset += TYPE_LENGTH;
+ // length means total length of the tlvs including route distinguisher not including the type field
+ final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+ byteOffset += LENGTH_SIZE;
+ if (safi == BGPSubsequentAddressFamily.MPLSLabeledVPN) {
+ // this parses route distinguisher
+ ByteArray.bytesToLong(ByteArray.subByte(bytes, byteOffset, ROUTE_DISTINGUISHER_LENGTH));
+ byteOffset += ROUTE_DISTINGUISHER_LENGTH;
+ }
+ // parse source protocol
+ sp = parseProtocolId(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, PROTOCOL_ID_LENGTH)));
+ byteOffset += PROTOCOL_ID_LENGTH;
+
+ // parse identifier
+ identifier = ByteArray.bytesToLong(ByteArray.subByte(bytes, byteOffset, IDENTIFIER_LENGTH));
+ byteOffset += IDENTIFIER_LENGTH;
+
+ // if we are dealing with linkstate nodes/links, parse local node descriptor
+ NodeIdentifier localDescriptor = null;
+ int locallength = 0;
+ final int localtype = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+ byteOffset += TYPE_LENGTH;
+ locallength = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+ byteOffset += LENGTH_SIZE;
+ if (localtype == 256) {
+ localDescriptor = parseNodeDescriptors(ByteArray.subByte(bytes, byteOffset, locallength));
+ }
+ byteOffset += locallength;
+ final int restLength = length - ((safi == BGPSubsequentAddressFamily.MPLSLabeledVPN) ? ROUTE_DISTINGUISHER_LENGTH : 0)
+ - PROTOCOL_ID_LENGTH - IDENTIFIER_LENGTH - TYPE_LENGTH - LENGTH_SIZE - locallength;
+ logger.debug("Restlength {}", restLength);
+ switch (type) {
+ case LinkNLRI:
+ links.add(parseLink(localDescriptor, sp, ByteArray.subByte(bytes, byteOffset, restLength)));
+ break;
+ case IPv4Prefixes:
+ case IPv6Prefixes:
+ descs.add(parsePrefixDescriptors(localDescriptor, ByteArray.subByte(bytes, byteOffset, restLength)));
+ break;
+ case NodeNLRI:
+ // node nlri is already parsed as it contains only the common fields for node and link nlri
+ nodes.add(localDescriptor);
+ break;
+ }
+ byteOffset += restLength;
+ }
+ if (!links.isEmpty())
+ return new BGPLinkMP(identifier, sp, reachable, links);
+ else if (!nodes.isEmpty())
+ return new BGPNodeMP(identifier, sp, reachable, nodes);
+ // else if (!descs.isEmpty())
+ // return new BGPIPv4PrefixMP(identifier, sp, descs, reachable);
+ return null;
+ }
+
+ protected static Map<Integer, ByteList> parseLinkState(final byte[] bytes) {
+ final Map<Integer, ByteList> map = new HashMap<Integer, ByteList>();
+ int byteOffset = 0;
+ while (byteOffset != bytes.length) {
+ final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+ byteOffset += TYPE_LENGTH;
+ final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+ byteOffset += LENGTH_SIZE;
+ final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
+ ByteList values = map.containsKey(type) ? values = map.get(type) : new ByteList();
+ values.add(value);
+ map.put(type, values);
+ byteOffset += length;
+ }
+ return map;
+ }
+
+ public static boolean verifyLink(final Set<Integer> keys) {
+ for (final Integer i : keys)
+ if (!linkTlvs.contains(i)) {
+ logger.warn("Invalid link attribute {}", i);
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean verifyNode(final Set<Integer> keys) {
+ for (final Integer i : keys)
+ if (!nodeTlvs.contains(i)) {
+ logger.warn("Invalid node attribute {}", i);
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean verifyPrefix(final Set<Integer> keys) {
+ for (final Integer i : keys)
+ if (!prefixTlvs.contains(i)) {
+ logger.warn("Invalid prefix attribute {}", i);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Parse protocol ID from int to enum
+ *
+ * @param protocolId int parsed from byte array
+ * @return enum SourceProtocol
+ * @throws BGPParsingException if the type is unrecognized
+ */
+ private static SourceProtocol parseProtocolId(final int protocolId) throws BGPParsingException {
+ switch (protocolId) {
+ case 0:
+ return SourceProtocol.Unknown;
+ case 1:
+ return SourceProtocol.ISISLevel1;
+ case 2:
+ return SourceProtocol.ISISLevel2;
+ case 3:
+ return SourceProtocol.OSPF;
+ case 4:
+ return SourceProtocol.Direct;
+ case 5:
+ return SourceProtocol.Static;
+ default:
+ throw new BGPParsingException("Unknown Source Protocol ID: " + protocolId);
+ }
+ }
+
+ private static OSPFRouteType parseRouteType(final int type) throws BGPParsingException {
+ switch (type) {
+ case 0:
+ return null; // for IS-IS it needs to be 0
+ case 1:
+ return OSPFRouteType.Intra_Area;
+ case 2:
+ return OSPFRouteType.Inter_Area;
+ case 3:
+ return OSPFRouteType.External1;
+ case 4:
+ return OSPFRouteType.External2;
+ case 5:
+ return OSPFRouteType.NSSA1;
+ case 6:
+ return OSPFRouteType.NSSA2;
+ default:
+ throw new BGPParsingException("Unknown OSPF Route Type: " + type);
+ }
+ }
+
+ private static LinkIdentifier parseLink(final NodeIdentifier local, final SourceProtocol spi, final byte[] bytes)
+ throws BGPParsingException {
+ int byteOffset = 0;
+ final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+ byteOffset += TYPE_LENGTH;
+ final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+ byteOffset += LENGTH_SIZE;
+ NodeIdentifier remote = null;
+ if (type == 257) {
+ remote = parseNodeDescriptors(ByteArray.subByte(bytes, byteOffset, length));
+ byteOffset += length;
+ }
+
+ return parseLinkDescriptors(local, remote, ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset));
+ }
+
+ /**
+ * Parse Link Descriptors.
+ *
+ * @param topology
+ * @param localAnchor
+ * @param remoteAnchor
+ * @param bytes
+ * @return
+ * @throws BGPParsingException
+ */
+ private static LinkIdentifier parseLinkDescriptors(final NodeIdentifier local, final NodeIdentifier remote, final byte[] bytes)
+ throws BGPParsingException {
+ int byteOffset = 0;
+ final List<InterfaceIdentifier> localIdentifiers = Lists.newArrayList();
+ final List<InterfaceIdentifier> remoteIdentifiers = Lists.newArrayList();
+ TopologyIdentifier topId = null;
+ while (byteOffset != bytes.length) {
+ final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+ byteOffset += TYPE_LENGTH;
+ final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+ byteOffset += LENGTH_SIZE;
+ final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
+ logger.debug("Parsing Link Descriptor: {}", Arrays.toString(value));
+ switch (type) {
+ case 258:
+ final UnnumberedLinkIdentifier l = new UnnumberedLinkIdentifier(ByteArray.bytesToLong(ByteArray.subByte(value, 0, 4)));
+ final UnnumberedLinkIdentifier r = new UnnumberedLinkIdentifier(ByteArray.bytesToLong(ByteArray.subByte(value, 4, 4)));
+ localIdentifiers.add(l);
+ remoteIdentifiers.add(r);
+ logger.trace("Parsed link local {} remote {} Identifiers.", local, remote);
+ break;
+ case 259:
+ final IPv4InterfaceIdentifier lipv4 = new IPv4InterfaceIdentifier(new IPv4Address(value));
+ localIdentifiers.add(lipv4);
+ logger.trace("Parsed IPv4 interface address {}.", lipv4);
+ break;
+ case 260:
+ final IPv4InterfaceIdentifier ripv4 = new IPv4InterfaceIdentifier(new IPv4Address(value));
+ remoteIdentifiers.add(ripv4);
+ logger.trace("Parsed IPv4 neighbor address {}.", ripv4);
+ break;
+ case 261:
+ final IPv6InterfaceIdentifier lipv6 = new IPv6InterfaceIdentifier(new IPv6Address(value));
+ localIdentifiers.add(lipv6);
+ logger.trace("Parsed IPv6 interface address {}.", lipv6);
+ break;
+ case 262:
+ final IPv6InterfaceIdentifier ripv6 = new IPv6InterfaceIdentifier(new IPv6Address(value));
+ remoteIdentifiers.add(ripv6);
+ logger.trace("Parsed IPv6 neighbor address {}.", ripv6);
+ break;
+ case 263:
+ topId = new TopologyIdentifier(ByteArray.bytesToLong(value) & 0x3fff);
+ logger.trace("Parsed topology identifier {}.", topId);
+ break;
+ default:
+ throw new BGPParsingException("Link Descriptor not recognized, type: " + type);
+ }
+ byteOffset += length;
+ }
+ logger.debug("Finished parsing Link descriptors.");
+ if (localIdentifiers.size() != 1)
+ throw new BGPParsingException("Invalid number of local interface identifiers.");
+ final LinkAnchor localAnchor = new LinkAnchor(local, localIdentifiers.get(0));
+ LinkAnchor remoteAnchor = null;
+ if (remoteIdentifiers.size() > 0) {
+ remoteAnchor = new LinkAnchor(remote, remoteIdentifiers.get(0));
+ } else
+ remoteAnchor = new LinkAnchor(remote, null);
+ return new LinkIdentifier(topId, localAnchor, remoteAnchor);
+ }
+
+ /**
+ * Parse Node Descriptors. There can be only one TLV present from each type.
+ *
+ * @param spi
+ * @param bytes
+ * @return
+ * @throws BGPParsingException
+ */
+ private static NodeIdentifier parseNodeDescriptors(final byte[] bytes) throws BGPParsingException {
+ int byteOffset = 0;
+ ASNumber asnumber = null;
+ DomainIdentifier bgpId = null;
+ AreaIdentifier ai = null;
+ RouterIdentifier routerId = null;
+ while (byteOffset != bytes.length) {
+ final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+ byteOffset += TYPE_LENGTH;
+ final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+ byteOffset += LENGTH_SIZE;
+ final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
+ logger.debug("Parsing Node Descriptor: {}", Arrays.toString(value));
+ switch (type) {
+ case 512:
+ asnumber = new ASNumber(ByteArray.bytesToLong(value));
+ logger.trace("Parsed AS number {}", asnumber);
+ break;
+ case 513:
+ bgpId = new DomainIdentifier(value);
+ logger.trace("Parsed bgpId {}", bgpId);
+ break;
+ case 514:
+ ai = new AreaIdentifier(value);
+ logger.trace("Parsed area identifier {}", ai);
+ break;
+ case 515:
+ if (value.length == 6) {
+ routerId = new ISISRouterIdentifier(new ISOSystemIdentifier(ByteArray.subByte(value, 0, 6)));
+ } else if (value.length == 7) {
+ if (value[6] == 0) {
+ logger.warn("PSN octet is 0. Ignoring System ID.");
+ routerId = new ISISRouterIdentifier(new ISOSystemIdentifier(ByteArray.subByte(value, 0, 6)));
+ break;
+ } else
+ routerId = new ISISLANIdentifier(new ISOSystemIdentifier(ByteArray.subByte(value, 0, 6)), value[6]);
+ } else if (value.length == 4) {
+ routerId = new OSPFRouterIdentifier(ByteArray.subByte(value, 0, 4));
+ } else if (value.length == 8) {
+ final byte[] o = ByteArray.subByte(value, 0, 4); // FIXME: OSPFv3 vs OSPFv2
+ final OSPFInterfaceIdentifier a = new OSPFInterfaceIdentifier(ByteArray.subByte(value, 4, 4));
+ routerId = new OSPFv3LANIdentifier(new OSPFRouterIdentifier(o), a);
+ }
+ logger.trace("Parsed Router Identifier {}", routerId);
+ break;
+ default:
+ throw new BGPParsingException("Node Descriptor not recognized, type: " + type);
+ }
+ byteOffset += length;
+ }
+ logger.debug("Finished parsing Node descriptors.");
+ return new NodeIdentifier(asnumber, bgpId, ai, routerId);
+ }
+
+ private static PrefixIdentifier<?> parsePrefixDescriptors(final NodeIdentifier localDescriptor, final byte[] bytes)
+ throws BGPParsingException {
+ int byteOffset = 0;
+ TopologyIdentifier topologyId = null;
+ OSPFRouteType routeType = null;
+ Prefix<?> prefix = null;
+ while (byteOffset != bytes.length) {
+ final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, TYPE_LENGTH));
+ byteOffset += TYPE_LENGTH;
+ final int length = ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, LENGTH_SIZE));
+ byteOffset += LENGTH_SIZE;
+ final byte[] value = ByteArray.subByte(bytes, byteOffset, length);
+ logger.trace("Parsing Prefix Descriptor: {}", Arrays.toString(value));
+ switch (type) {
+ case 263:
+ topologyId = new TopologyIdentifier(ByteArray.bytesToLong(value) & 0x3fff);
+ logger.trace("Parsed Topology Identifier: {}", topologyId);
+ break;
+ case 264:
+ final int rt = ByteArray.bytesToInt(value);
+ routeType = parseRouteType(rt);
+ logger.trace("Parser RouteType: {}", routeType);
+ break;
+ case 265:
+ final int prefixLength = UnsignedBytes.toInt(value[0]);
+ final int size = prefixLength / 8 + ((prefixLength % 8 == 0) ? 0 : 1);
+ if (size != value.length - 1) {
+ logger.debug("Expected length {}, actual length {}.", size, value.length - 1);
+ throw new BGPParsingException("Illegal length of IP reachability TLV: " + (value.length - 1));
+ }
+ prefix = IPv6.FAMILY.prefixForBytes(ByteArray.subByte(value, 1, size), prefixLength);
+ logger.trace("Parsed IP reachability info: {}", prefix);
+ break;
+ default:
+ throw new BGPParsingException("Prefix Descriptor not recognized, type: " + type);
+ }
+ byteOffset += length;
+ }
+ logger.debug("Finished parsing Prefix descriptors.");
+ if (routeType != null) {
+ if (prefix instanceof IPv4Prefix) {
+ return new OSPFPrefixIdentifier<IPv4Address>(localDescriptor, (IPv4Prefix) prefix, routeType);
+ } else {
+ return new OSPFPrefixIdentifier<IPv6Address>(localDescriptor, (IPv6Prefix) prefix, routeType);
+ }
+ }
+ return (prefix instanceof IPv4Prefix) ? new IPv4PrefixIdentifier(localDescriptor, (IPv4Prefix) prefix)
+ : new IPv6PrefixIdentifier(localDescriptor, (IPv6Prefix) prefix);
+ }
+
+ /**
+ * Parse Link Attributes.
+ *
+ * @param descriptors
+ * @param bytes
+ * @return
+ * @throws BGPParsingException
+ */
+ public static NetworkLinkImpl parseLinkAttributes(final LinkIdentifier linkId, final Map<Integer, ByteList> attributes)
+ throws BGPParsingException {
+
+ final Set<SharedRiskLinkGroup> sharedRiskLinkGroups = Sets.newHashSet();
+ final Set<MPLSProtocol> enabledMPLSProtocols = Sets.newHashSet();
+ final NetworkLinkImpl link = new NetworkLinkImpl(linkId);
+
+ // FIXME: we should put these somewhere
+ final Set<RouterIdentifier> localIds = Sets.newHashSet();
+ final Set<RouterIdentifier> remoteIds = Sets.newHashSet();
+
+ String name = null;
+ for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
+ logger.debug("Link attribute TLV {}", entry.getKey());
+
+ for (final byte[] value : entry.getValue().getBytes()) {
+
+ switch (entry.getKey()) {
+ case 1028:
+ final IPv4RouterIdentifier lipv4 = new IPv4RouterIdentifier(new IPv4Address(value));
+ localIds.add(lipv4);
+ logger.trace("Parsed IPv4 Router-ID of local node: {}", lipv4);
+ break;
+ case 1029:
+ final IPv6RouterIdentifier lipv6 = new IPv6RouterIdentifier(new IPv6Address(value));
+ localIds.add(lipv6);
+ logger.trace("Parsed IPv6 Router-ID of local node: {}", lipv6);
+ break;
+ case 1030:
+ final IPv4RouterIdentifier ripv4 = new IPv4RouterIdentifier(new IPv4Address(value));
+ remoteIds.add(ripv4);
+ logger.trace("Parsed IPv4 Router-ID of remote node: {}", ripv4);
+ break;
+ case 1031:
+ final IPv6RouterIdentifier ripv6 = new IPv6RouterIdentifier(new IPv6Address(value));
+ remoteIds.add(ripv6);
+ logger.trace("Parsed IPv6 Router-ID of remote node: {}", ripv6);
+ break;
+ case 1088:
+ link.setAdministrativeGroup(new AdministrativeGroup(ByteArray.bytesToLong(value)));
+ logger.trace("Parsed Administrative Group {}", link.currentState().getAdministrativeGroup());
+ break;
+ case 1089:
+ link.setMaximumBandwidth(new Bandwidth(ByteArray.bytesToFloat(value)));
+ logger.trace("Parsed Max Bandwidth {}", link.currentState().getMaximumBandwidth());
+ break;
+ case 1090:
+ link.setMaximumReservableBandwidth(new Bandwidth(ByteArray.bytesToFloat(value)));
+ logger.trace("Parsed Max Reservable Bandwidth {}", link.currentState().getMaximumReservableBandwidth());
+ break;
+ case 1091:
+ int index = 0;
+ final Bandwidth[] unreservedBandwidth = new Bandwidth[8];
+ for (int i = 0; i < 8; i++) {
+ unreservedBandwidth[i] = new Bandwidth(ByteArray.bytesToFloat(ByteArray.subByte(value, index, 4)));
+ index += 4;
+ }
+ link.setUnreservedBandwidth(unreservedBandwidth);
+ logger.trace("Parsed Unreserved Bandwidth {}", Arrays.toString(link.currentState().getUnreservedBandwidth()));
+ break;
+ case 1092:
+ link.setMetric(TEMetric.class, new TEMetric(ByteArray.bytesToInt(value)));
+ logger.trace("Parsed Metric {}", link.currentState().getMetric(TEMetric.class));
+ break;
+ case 1093:
+ link.setProtectionType(parseLinkProtectionType(UnsignedBytes.toInt(value[0])));
+ logger.trace("Parsed Link Protection Type {}", link.currentState().getProtectionType());
+ break;
+ case 1094:
+ final boolean[] bits = ByteArray.parseBits(value[0]);
+ if (bits[0] == true) {
+ enabledMPLSProtocols.add(MPLSProtocol.LDP);
+ }
+ if (bits[1] == true) {
+ enabledMPLSProtocols.add(MPLSProtocol.RSVPTE);
+ }
+ logger.trace("Parsed MPLS Protocols: {}", Arrays.toString(enabledMPLSProtocols.toArray()));
+ break;
+ case 1095:
+ link.setDefaultMetric(new IGPMetric(ByteArray.bytesToLong(value)));
+ logger.trace("Parsed Metric {}", link.currentState().getDefaultMetric());
+ break;
+ case 1096:
+ int i = 0;
+ while (i != value.length) {
+ sharedRiskLinkGroups.add(new SharedRiskLinkGroup(ByteArray.bytesToLong(ByteArray.subByte(value, i, 4))));
+ i += 4;
+ }
+ logger.trace("Parsed Shared Risk Link Groups {}", Arrays.toString(sharedRiskLinkGroups.toArray()));
+ break;
+ case 1097:
+ final byte[] opaque = value;
+ logger.trace("Parsed Opaque value : {}", Arrays.toString(opaque));
+ break;
+ case 1098:
+ name = new String(value, Charsets.US_ASCII);
+ logger.trace("Parsed Link Name : ", name);
+ break;
+ default:
+ throw new BGPParsingException("Link Attribute not recognized, type: " + entry.getKey());
+ }
+ }
+ }
+ link.setEnabledMPLSProtocols(enabledMPLSProtocols);
+ link.setSharedRiskLinkGroups(sharedRiskLinkGroups);
+ link.currentState().withSymbolicName(name);
+ logger.debug("Finished parsing Link Attributes.");
+ return link;
+ }
+
+ /**
+ * Parse Node Attributes.
+ *
+ * @param descriptors
+ * @param bytes
+ * @return
+ * @throws BGPParsingException
+ */
+ public static NetworkNodeImpl parseNodeAttributes(final NodeIdentifier nodeId, final Map<Integer, ByteList> attributes)
+ throws BGPParsingException {
+ final Map<TopologyIdentifier, TopologyNodeInformation> topologyMembership = Maps.newHashMap();
+ final Set<ISISAreaIdentifier> areaMembership = Sets.newHashSet();
+ final NetworkNodeImpl node = new NetworkNodeImpl(nodeId);
+ final Set<RouterIdentifier> ids = Sets.newHashSet();
+ for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
+ logger.debug("Node attribute TLV {}", entry.getKey());
+ for (final byte[] value : entry.getValue().getBytes()) {
+ switch (entry.getKey()) {
+ case 263:
+ final boolean[] bits = ByteArray.parseBits(value[0]);
+ final TopologyNodeInformation topNodeInfo = new TopologyNodeInformation(bits[1], bits[0]);
+ final TopologyIdentifier topId = new TopologyIdentifier(ByteArray.bytesToLong(value) & 0x3fff);
+ topologyMembership.put(topId, topNodeInfo);
+ logger.trace("Parsed Topology Identifier: {} and Topology Node Information: {}", topId, topNodeInfo);
+ break;
+ case 1024:
+ final boolean[] flags = ByteArray.parseBits(value[0]);
+ node.setExternal(flags[2]);
+ node.setAreaBorderRouter(flags[3]);
+ logger.trace("Parsed External bit {}, area border router {}.", flags[2], flags[3]);
+ break;
+ case 1025:
+ logger.debug("Ignoring opaque value: {}.", Arrays.toString(value));
+ break;
+ case 1026:
+ node.setDynamicHostname(new String(value, Charsets.US_ASCII));
+ logger.trace("Parsed Node Name {}", node.currentState().getDynamicHostname());
+ break;
+ case 1027:
+ final ISISAreaIdentifier ai = new ISISAreaIdentifier(value);
+ areaMembership.add(ai);
+ logger.trace("Parsed AreaIdentifier {}", ai);
+ break;
+ case 1028:
+ final IPv4RouterIdentifier ip4 = new IPv4RouterIdentifier(new IPv4Address(value));
+ ids.add(ip4);
+ logger.trace("Parsed IPv4 Router Identifier {}", ip4);
+ break;
+ case 1029:
+ final IPv6RouterIdentifier ip6 = new IPv6RouterIdentifier(new IPv6Address(value));
+ ids.add(ip6);
+ logger.trace("Parsed IPv6 Router Identifier {}", ip6);
+ break;
+ default:
+ throw new BGPParsingException("Node Attribute not recognized, type: " + entry.getKey());
+ }
+ }
+ }
+
+ node.setAreaMembership(areaMembership);
+ node.setAlternativeIdentifiers(ids);
+ node.setTopologyMembership(topologyMembership);
+ logger.debug("Finished parsing Node Attributes.");
+ return node;
+ }
+
+ public static NetworkPrefixState parsePrefixAttributes(final SourceProtocol src, final NetworkObjectState nos,
+ final Map<Integer, ByteList> attributes) throws BGPParsingException {
+
+ boolean upDownBit = false;
+ final SortedSet<RouteTag> routeTags = Sets.newTreeSet();
+ final SortedSet<ExtendedRouteTag> exRouteTags = Sets.newTreeSet();
+ Metric<?> metric = null;
+ IPv4Address fwdAddress4 = null;
+ IPv6Address fwdAddress6 = null;
+ for (final Entry<Integer, ByteList> entry : attributes.entrySet()) {
+ logger.debug("Prefix attribute TLV {}", entry.getKey());
+ for (final byte[] value : entry.getValue().getBytes()) {
+ switch (entry.getKey()) {
+ case 1152:
+ final boolean[] flags = ByteArray.parseBits(value[0]);
+ upDownBit = flags[2];
+ logger.trace("Parsed IGP flag (up/down bit) : {}", upDownBit);
+ break;
+ case 1153:
+ int offset = 0;
+ while (offset != value.length) {
+ final RouteTag routeTag = new RouteTag(ByteArray.subByte(value, offset, 4));
+ routeTags.add(routeTag);
+ logger.trace("Parsed Route Tag: {}", routeTag);
+ offset += 4;
+ }
+ break;
+ case 1154:
+ offset = 0;
+ while (offset != value.length) {
+ final ExtendedRouteTag exRouteTag = new ExtendedRouteTag(value);
+ exRouteTags.add(exRouteTag);
+ logger.trace("Parsed Extended Route Tag: {}", exRouteTag);
+ offset += 4;
+ }
+ break;
+ case 1155:
+ metric = new IGPMetric(ByteArray.bytesToLong(value));
+ logger.trace("Parsed Metric: {}", metric);
+ break;
+ case 1156:
+ switch (value.length) {
+ case 4:
+ fwdAddress4 = new IPv4Address(value);
+ logger.trace("Parsed FWD Address: {}", fwdAddress4);
+ break;
+ case 16:
+ fwdAddress6 = new IPv6Address(value);
+ logger.trace("Parsed FWD Address: {}", fwdAddress6);
+ break;
+ default:
+ logger.debug("Ignoring unsupported forwarding address length {}", value.length);
+ }
+
+ break;
+ case 1157:
+ final byte[] opaque = value;
+ logger.trace("Parsed Opaque value: {}", Arrays.toString(opaque));
+ break;
+ default:
+ throw new BGPParsingException("Prefix Attribute not recognized, type: " + entry.getKey());
+ }
+ }
+ }
+
+ logger.debug("Finished parsing Prefix Attributes.");
+
+ final NetworkPrefixState nps = new NetworkPrefixState(nos, routeTags, metric);
+ switch (src) {
+ case ISISLevel1:
+ case ISISLevel2:
+ return new ISISNetworkPrefixState(nps, exRouteTags, upDownBit);
+ case OSPF:
+ if (fwdAddress4 != null)
+ return new OSPFNetworkPrefixState<IPv4Address>(nps, fwdAddress4);
+ if (fwdAddress6 != null)
+ return new OSPFNetworkPrefixState<IPv6Address>(nps, fwdAddress6);
+ logger.debug("OSPF-sourced has no forwarding address");
+ return nps;
+ default:
+ return nps;
+ }
+ }
+
+ /**
+ * Parse Link Protection Type from int to enum
+ *
+ * @param type int parsed from byte array
+ * @return enum LinkProtectionType
+ * @throws BGPParsingException if the type is unrecognized
+ */
+ private static LinkProtectionType parseLinkProtectionType(final int type) throws BGPParsingException {
+ switch (type) {
+ case 1:
+ return LinkProtectionType.EXTRA_TRAFFIC;
+ case 2:
+ return LinkProtectionType.UNPROTECTED;
+ case 4:
+ return LinkProtectionType.SHARED;
+ case 8:
+ return LinkProtectionType.DEDICATED_ONE_TO_ONE;
+ case 16:
+ return LinkProtectionType.DEDICATED_ONE_PLUS_ONE;
+ default:
+ throw new BGPParsingException("Link Protection Type not recognized: " + type);
+ }
+ }
+
+ /**
+ * Parse NLRI Type from int to enum
+ *
+ * @param type int parsed from byte array
+ * @return enum NlriType
+ * @throws BGPParsingException if the type is unrecognized
+ */
+ private static NlriType parseNLRItype(final int type) throws BGPParsingException {
+ switch (type) {
+ case 1:
+ return NlriType.NodeNLRI;
+ case 2:
+ return NlriType.LinkNLRI;
+ case 3:
+ return NlriType.IPv4Prefixes;
+ case 4:
+ return NlriType.IPv6Prefixes;
+ default:
+ throw new BGPParsingException("NLRI Type not recognized: " + type);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message.update;
+
+import java.util.Set;
+
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.IPv4MP;
+import org.opendaylight.protocol.bgp.parser.impl.IPv6MP;
+import org.opendaylight.protocol.bgp.parser.impl.MPReach;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for MP_REACH or MP_UNREACH fields.
+ */
+public class MPReachParser {
+
+ private static final int ADDRESS_FAMILY_IDENTIFIER_SIZE = 2;
+
+ private static final int SUBSEQUENT_ADDRESS_FAMILY_IDENTIFIER_SIZE = 1;
+
+ private static final int NEXT_HOP_LENGTH_SIZE = 1;
+
+ private static final int RESERVED_SIZE = 1;
+
+ public static final int LS_AFI = 16388;
+
+ public static final int LS_SAFI = 71;
+
+ private MPReachParser() {
+
+ }
+
+ static MPReach<?> parseMPUnreach(final byte[] bytes) throws BGPParsingException {
+ int byteOffset = 0;
+ final BGPAddressFamily afi = parseAfi(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, ADDRESS_FAMILY_IDENTIFIER_SIZE)));
+ byteOffset += ADDRESS_FAMILY_IDENTIFIER_SIZE;
+ final BGPSubsequentAddressFamily safi = parseSafi(UnsignedBytes.toInt(bytes[byteOffset]));
+ byteOffset += SUBSEQUENT_ADDRESS_FAMILY_IDENTIFIER_SIZE;
+ return chooseUnreachParser(afi, safi, ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset));
+ }
+
+ static MPReach<?> parseMPReach(final byte[] bytes) throws BGPParsingException {
+ int byteOffset = 0;
+ final BGPAddressFamily afi = parseAfi(ByteArray.bytesToInt(ByteArray.subByte(bytes, byteOffset, ADDRESS_FAMILY_IDENTIFIER_SIZE)));
+ byteOffset += ADDRESS_FAMILY_IDENTIFIER_SIZE;
+ final BGPSubsequentAddressFamily safi = parseSafi(UnsignedBytes.toInt(bytes[byteOffset]));
+ byteOffset += SUBSEQUENT_ADDRESS_FAMILY_IDENTIFIER_SIZE;
+ final int nextHopLength = UnsignedBytes.toInt(bytes[byteOffset]);
+ byteOffset += NEXT_HOP_LENGTH_SIZE;
+ final NextHop<?> nextHop = parseNextHop(ByteArray.subByte(bytes, byteOffset, nextHopLength));
+ byteOffset += nextHopLength + RESERVED_SIZE;
+ return chooseReachParser(afi, safi, nextHop, ByteArray.subByte(bytes, byteOffset, bytes.length - (byteOffset)));
+ }
+
+ public static BGPSubsequentAddressFamily parseSafi(final int type) throws BGPParsingException {
+ switch (type) {
+ case 1:
+ return BGPSubsequentAddressFamily.Unicast;
+ case LS_SAFI:
+ return BGPSubsequentAddressFamily.Linkstate;
+ case 128:
+ return BGPSubsequentAddressFamily.MPLSLabeledVPN;
+ default:
+ throw new BGPParsingException("Subsequent Address Family Identifier: '" + type + "' not supported.");
+ }
+ }
+
+ public static BGPAddressFamily parseAfi(final int type) throws BGPParsingException {
+ switch (type) {
+ case 1:
+ return BGPAddressFamily.IPv4;
+ case 2:
+ return BGPAddressFamily.IPv6;
+ case LS_AFI:
+ return BGPAddressFamily.LinkState;
+ default:
+ throw new BGPParsingException("Address Family Identifier: '" + type + "' not supported.");
+ }
+ }
+
+ private static MPReach<?> chooseUnreachParser(final BGPAddressFamily afi, final BGPSubsequentAddressFamily safi, final byte[] bytes)
+ throws BGPParsingException {
+ switch (afi) {
+ case IPv4:
+ final Set<Prefix<IPv4Address>> nlri4 = IPv4.FAMILY.prefixListForBytes(bytes);
+ return new IPv4MP(false, null, nlri4);
+ case IPv6:
+ final Set<Prefix<IPv6Address>> nlri6 = IPv6.FAMILY.prefixListForBytes(bytes);
+ return new IPv6MP(false, null, nlri6);
+ case LinkState:
+ return LinkStateParser.parseLSNlri(false, safi, null, bytes);
+ default:
+ return null;
+ }
+ }
+
+ private static MPReach<?> chooseReachParser(final BGPAddressFamily afi, final BGPSubsequentAddressFamily safi,
+ final NextHop<?> nextHop, final byte[] bytes) throws BGPParsingException {
+ switch (afi) {
+ case IPv4:
+ final Set<Prefix<IPv4Address>> nlri4 = IPv4.FAMILY.prefixListForBytes(bytes);
+ return new IPv4MP(true, (IPv4NextHop) nextHop, nlri4);
+ case IPv6:
+ final Set<Prefix<IPv6Address>> nlri6 = IPv6.FAMILY.prefixListForBytes(bytes);
+ return new IPv6MP(true, (IPv6NextHop) nextHop, nlri6);
+ case LinkState:
+ return LinkStateParser.parseLSNlri(true, safi, nextHop, bytes);
+ default:
+ return null;
+ }
+ }
+
+ private static NextHop<?> parseNextHop(final byte[] bytes) throws BGPParsingException {
+ final NextHop<?> addr;
+ switch (bytes.length) {
+ case 4:
+ addr = new IPv4NextHop(IPv4.FAMILY.addressForBytes(bytes));
+ break;
+ case 16:
+ addr = new IPv6NextHop(IPv6.FAMILY.addressForBytes(bytes));
+ break;
+ case 32:
+ addr = new IPv6NextHop(IPv6.FAMILY.addressForBytes(ByteArray.subByte(bytes, 0, 16)), IPv6.FAMILY.addressForBytes(ByteArray.subByte(bytes, 16, 16)));
+ break;
+ default:
+ throw new BGPParsingException("Cannot parse NEXT_HOP attribute. Wrong bytes length: " + bytes.length);
+ }
+ return addr;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl.message.update;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.ClusterIdentifier;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.BGPAggregatorImpl;
+import org.opendaylight.protocol.bgp.parser.impl.ByteList;
+import org.opendaylight.protocol.bgp.parser.impl.MPReach;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute.TypeCode;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.AsPathSegmentParser.SegmentType;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ *
+ * Parser for different Path Attributes. Each attributes has its own method for parsing.
+ *
+ */
+public class PathAttributeParser {
+
+ private static final int FLAGS_LENGTH = 1;
+
+ private static final int TYPE_LENGTH = 1;
+
+ private PathAttributeParser() {
+
+ }
+
+ /**
+ * Parse path attribute header (the same for all path attributes) and set type, length and value fields.
+ *
+ * @param bytes byte array to be parsed.
+ * @return generic Path Attribute
+ * @throws BGPParsingException
+ * @throws BGPDocumentedException
+ */
+ public static PathAttribute parseAttribute(final byte[] bytes) throws BGPDocumentedException, BGPParsingException {
+ if (bytes == null || bytes.length == 0)
+ throw new BGPParsingException("Insufficient length of byte array: " + bytes.length);
+ final boolean[] bits = ByteArray.parseBits(bytes[0]);
+ final PathAttribute attribute = new PathAttribute(bits[0], bits[1], bits[2], bits[3]);
+
+ final int attrLength = (attribute.getAttrLengthSize() == 1) ? UnsignedBytes.toInt(bytes[2])
+ : ByteArray.bytesToInt(ByteArray.subByte(bytes, 2, 2));
+ attribute.setType(TypeCode.parseType(UnsignedBytes.toInt(bytes[1])));
+
+ if (attribute.getType() == null && !attribute.isOptional())
+ throw new BGPDocumentedException("Well known attribute not recognized.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED);
+
+ attribute.setLength(attrLength);
+ attribute.setValue(chooseParser(attribute.getType(),
+ ByteArray.subByte(bytes, FLAGS_LENGTH + TYPE_LENGTH + attribute.getAttrLengthSize(), attrLength)));
+ return attribute;
+ }
+
+ /**
+ * Choose corresponding parser to the typecode, that was already parsed.
+ *
+ * @param type typecode of the path attribute
+ * @param bytes byte array to be parsed
+ * @return Object, because there are various Path Attributes and there is no superclass or interface common for all
+ * of them.
+ * @throws BGPDocumentedException
+ * @throws BGPParsingException
+ */
+ private static Object chooseParser(final TypeCode type, final byte[] bytes) throws BGPDocumentedException, BGPParsingException {
+ switch (type) {
+ case ORIGIN:
+ return parseOrigin(bytes);
+ case AS_PATH:
+ return parseAsPath(bytes);
+ case NEXT_HOP:
+ return parseNextHop(bytes);
+ case MULTI_EXIT_DISC:
+ return parseMultiExitDisc(bytes);
+ case LOCAL_PREF:
+ return parseLocalPref(bytes);
+ case ATOMIC_AGGREGATE:
+ return null;
+ case AGGREGATOR:
+ return parseAggregator(bytes);
+ case COMMUNITIES:
+ return parseCommunities(bytes);
+ case ORIGINATOR_ID:
+ return parseOriginatorId(bytes);
+ case CLUSTER_LIST:
+ return parseClusterList(bytes);
+ case MP_REACH_NLRI:
+ return parseMPReach(bytes);
+ case MP_UNREACH_NLRI:
+ return parseMPUnreach(bytes);
+ case EXTENDED_COMMUNITIES:
+ return parseExtendedCommunities(bytes);
+ case LINK_STATE:
+ return parseLinkState(bytes);
+ /**
+ * Recognize, but ignore.
+ */
+ case AS4_AGGREGATOR:
+ /**
+ * Recognize, but ignore.
+ */
+ case AS4_PATH:
+ return null;
+ }
+ return null;
+ }
+
+ /**
+ * Parses ORIGIN from bytes.
+ *
+ * @param bytes byte array to be parsed
+ * @return BGPOrigin enum
+ * @throws BGPParsingException if the Origin value is unknown
+ * @throws BGPDocumentedException
+ */
+ private static BGPOrigin parseOrigin(final byte[] bytes) throws BGPDocumentedException {
+ final int value = UnsignedBytes.toInt(bytes[0]);
+ BGPOrigin origin;
+ switch (value) {
+ case 0:
+ origin = BGPOrigin.IGP;
+ break;
+ case 1:
+ origin = BGPOrigin.EGP;
+ break;
+ case 2:
+ origin = BGPOrigin.INCOMPLETE;
+ break;
+ default:
+ throw new BGPDocumentedException("Unknown Origin type.", BGPError.ORIGIN_ATTR_NOT_VALID, new byte[] { (byte) 0x01, (byte) 0x01,
+ bytes[0] });
+ }
+ return origin;
+ }
+
+ /**
+ * Parses AS_PATH from bytes.
+ *
+ * @param bytes byte array to be parsed
+ * @return new ASPath object
+ * @throws BGPDocumentedException if there is no AS_SEQUENCE present (mandatory)
+ * @throws BGPParsingException
+ */
+ private static ASPath parseAsPath(final byte[] bytes) throws BGPDocumentedException, BGPParsingException {
+ int byteOffset = 0;
+ List<ASNumber> list = null;
+ Set<ASNumber> set = null;
+ while (byteOffset < bytes.length) {
+ final int type = UnsignedBytes.toInt(bytes[byteOffset]);
+ final SegmentType segmentType = AsPathSegmentParser.parseType(type);
+ if (segmentType == null)
+ throw new BGPParsingException("AS Path segment type unknown : " + type);
+ byteOffset += AsPathSegmentParser.TYPE_LENGTH;
+
+ final int count = UnsignedBytes.toInt(bytes[byteOffset]);
+ byteOffset += AsPathSegmentParser.LENGTH_SIZE;
+
+ if (segmentType == SegmentType.AS_SEQUENCE) {
+ list = (List<ASNumber>) AsPathSegmentParser.parseAsPathSegment(segmentType, count,
+ ByteArray.subByte(bytes, byteOffset, count * AsPathSegmentParser.AS_NUMBER_LENGTH));
+ } else {
+ set = (Set<ASNumber>) AsPathSegmentParser.parseAsPathSegment(segmentType, count,
+ ByteArray.subByte(bytes, byteOffset, count * AsPathSegmentParser.AS_NUMBER_LENGTH));
+ }
+ byteOffset += count * AsPathSegmentParser.AS_NUMBER_LENGTH;
+ }
+
+ if (list == null && bytes.length != 0)
+ throw new BGPDocumentedException("AS_SEQUENCE must be present in AS_PATH attribute.", BGPError.AS_PATH_MALFORMED);
+ return (set != null) ? new ASPath(list, set) : (list == null) ? ASPath.EMPTY : new ASPath(list);
+ }
+
+ /**
+ * Parse NEXT_HOP from bytes
+ *
+ * @param bytes byte array to be parsed
+ * @return new NextHop object, it's always IPv4 (basic BGP-4)
+ */
+ private static NextHop<IPv4Address> parseNextHop(final byte[] bytes) {
+ return new IPv4NextHop(new IPv4Address(bytes));
+ }
+
+ /**
+ * Parse MULTI_EXIT_DISC (integer) from bytes
+ *
+ * @param bytes byte array to be parsed
+ * @return integer representing MULTI_EXIT_DISC path attribute
+ */
+ private static int parseMultiExitDisc(final byte[] bytes) {
+ return ByteArray.bytesToInt(bytes);
+ }
+
+ /**
+ * Parse LOCAL_PREF (integer) from bytes
+ *
+ * @param bytes byte array to be parsed
+ * @return integer representing LOCAL_PREF path attribute
+ */
+ private static int parseLocalPref(final byte[] bytes) {
+ return ByteArray.bytesToInt(bytes);
+ }
+
+ /**
+ * Parse AGGREGATOR from bytes
+ *
+ * @param bytes byte array to be parsed
+ * @return new BGPAggregator object
+ */
+ private static BGPAggregator parseAggregator(final byte[] bytes) {
+ final ASNumber asNumber = new ASNumber(ByteArray.bytesToLong(ByteArray.subByte(bytes, 0, AsPathSegmentParser.AS_NUMBER_LENGTH)));
+ final IPv4Address address = new IPv4Address(ByteArray.subByte(bytes, AsPathSegmentParser.AS_NUMBER_LENGTH, 4));
+ return new BGPAggregatorImpl<IPv4Address>(asNumber, address);
+ }
+
+ /**
+ * Parse MP_REACH_NLRI from bytes
+ *
+ * @param bytes byte array to be parsed
+ * @return new specific MPReach object with reachable flag set to true
+ * @throws BGPDocumentedException
+ */
+ private static MPReach<?> parseMPReach(final byte[] bytes) throws BGPDocumentedException {
+ try {
+ return MPReachParser.parseMPReach(bytes);
+ } catch (final BGPParsingException e) {
+ throw new BGPDocumentedException("Could not parse MP_REACH_NLRI: " + e.getMessage(), BGPError.OPT_ATTR_ERROR);
+ }
+ }
+
+ /**
+ * Parse MP_UNREACH_NLRI from bytes
+ *
+ * @param bytes byte array to be parsed
+ * @return new specific MPReach object with reachable flag set to false
+ * @throws BGPDocumentedException
+ */
+ private static MPReach<?> parseMPUnreach(final byte[] bytes) throws BGPDocumentedException {
+ try {
+ return MPReachParser.parseMPUnreach(bytes);
+ } catch (final BGPParsingException e) {
+ throw new BGPDocumentedException("Could not parse MP_UNREACH_NLRI: " + e.getMessage(), BGPError.OPT_ATTR_ERROR);
+ }
+ }
+
+ /**
+ * Parse set of EXTENDED_COMMUNITIES from bytes
+ *
+ * @param bytes byte array to be parsed
+ * @return new specific Extended Community object
+ * @throws BGPDocumentedException l
+ */
+ private static Set<ExtendedCommunity> parseExtendedCommunities(final byte[] bytes) throws BGPDocumentedException {
+ final Set<ExtendedCommunity> set = Sets.newHashSet();
+ int i = 0;
+ while (i < bytes.length) {
+ set.add(CommunitiesParser.parseExtendedCommunity(ByteArray.subByte(bytes, i, CommunitiesParser.EXTENDED_COMMUNITY_LENGTH)));
+ i += CommunitiesParser.EXTENDED_COMMUNITY_LENGTH;
+ }
+ return set;
+ }
+
+ /**
+ * Parse set of COMMUNITIES from bytes
+ *
+ * @param bytes byte array to be parsed
+ * @return new specific Community object
+ * @throws BGPDocumentedException
+ */
+ private static Set<Community> parseCommunities(final byte[] bytes) throws BGPDocumentedException {
+ final Set<Community> set = Sets.newHashSet();
+ int i = 0;
+ while (i < bytes.length) {
+ set.add(CommunitiesParser.parseCommunity(ByteArray.subByte(bytes, i, CommunitiesParser.COMMUNITY_LENGTH)));
+ i += CommunitiesParser.COMMUNITY_LENGTH;
+ }
+ return set;
+ }
+
+ /**
+ * Parse list of Cluster Identifiers.
+ *
+ * @param bytes byte array to be parsed
+ * @return new List of Cluster Identifiers
+ */
+ private static List<ClusterIdentifier> parseClusterList(final byte[] bytes) {
+ final List<ClusterIdentifier> list = Lists.newArrayList();
+ int i = 0;
+ while (i < bytes.length) {
+ list.add(new ClusterIdentifier(ByteArray.subByte(bytes, i, ClusterIdentifier.SIZE)));
+ i += ClusterIdentifier.SIZE;
+ }
+ return list;
+ }
+
+ /**
+ * Parses ORIGINATOR_ID, which is BGP Identifier, which is IP address of the speaker.
+ *
+ * @param bytes byte array to be parsed
+ * @return IP address of the speaker
+ */
+ private static NetworkAddress<?> parseOriginatorId(final byte[] bytes) {
+ if (bytes.length != 4)
+ throw new IllegalArgumentException("Length of byte array for ORIGINATOR_ID should be 4, but is " + bytes.length);
+ return new IPv4Address(bytes);
+ }
+
+ /**
+ * Parse LINK_STATE from bytes
+ *
+ * @param bytes byte array to be parsed
+ * @return Map, where the key is the type of a tlv and the value is the value of the tlv
+ */
+ private static Map<Integer, ByteList> parseLinkState(final byte[] bytes) {
+ return LinkStateParser.parseLinkState(bytes);
+ }
+}
--- /dev/null
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+ <body>
+ <head>${project.artifactId}</head>
+ <links>
+ <item name="${project.artifactId}" href="index.html"/>
+ </links>
+
+ <menu ref="parent"/>
+
+ <menu ref="reports"/>
+
+
+ </body>
+</project>
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.concepts.Inet4SpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateEvent;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+import org.opendaylight.protocol.bgp.parser.impl.BGPAggregatorImpl;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateMessageImpl;
+import org.opendaylight.protocol.bgp.parser.impl.IPv4MP;
+import org.opendaylight.protocol.bgp.parser.impl.IPv6MP;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute;
+import org.opendaylight.protocol.bgp.parser.impl.PathAttribute.TypeCode;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPLinkImpl;
+import org.opendaylight.protocol.bgp.util.BGPNodeImpl;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.util.DefaultingTypesafeContainer;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.bgp.linkstate.AreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.DomainIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv4InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISAreaIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkAnchor;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifierFactory;
+import org.opendaylight.protocol.bgp.linkstate.OSPFInterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFv3LANIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.TopologyNodeInformation;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class BGPParserTest {
+
+ /**
+ * Used by other tests as well
+ */
+ static final List<byte[]> inputBytes = new ArrayList<byte[]>();
+
+ private static int COUNTER = 17;
+
+ private static int MAX_SIZE = 300;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+
+ for (int i = 1; i <= COUNTER; i++) {
+ final String name = "/up" + i + ".bin";
+ final InputStream is = BGPParserTest.class.getResourceAsStream(name);
+ if (is == null)
+ throw new IOException("Failed to get resource " + name);
+
+ final ByteArrayOutputStream bis = new ByteArrayOutputStream();
+ final byte[] data = new byte[MAX_SIZE];
+ int nRead = 0;
+ while ((nRead = is.read(data, 0, data.length)) != -1) {
+ bis.write(data, 0, nRead);
+ }
+ bis.flush();
+
+ inputBytes.add(bis.toByteArray());
+ }
+ }
+
+ @Test
+ public void testResource() {
+ assertNotNull(inputBytes);
+ }
+
+ /*
+ * Tests IPv4 NEXT_HOP, ATOMIC_AGGREGATE, COMMUNITY, NLRI
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 54 <- length (84) - including header
+ * 02 <- message type
+ * 00 00 <- withdrawn routes length
+ * 00 31 <- total path attribute length (49)
+ * 40 <- attribute flags
+ * 01 <- attribute type code (origin)
+ * 01 <- attribute length
+ * 00 <- Origin value (IGP)
+ * 40 <- attribute flags
+ * 02 <- attribute type code (as path)
+ * 06 <- attribute length
+ * 02 <- AS_SEQUENCE
+ * 01 <- path segment count
+ * 00 00 fd ea <- path segment value (65002)
+ * 40 <- attribute flags
+ * 03 <- attribute type code (Next Hop)
+ * 04 <- attribute length
+ * 10 00 00 02 <- value (10.0.0.2)
+ * 80 <- attribute flags
+ * 04 <- attribute type code (multi exit disc)
+ * 04 <- attribute length
+ * 00 00 00 00 <- value
+ * 64 <- attribute flags
+ * 06 <- attribute type code (atomic aggregate)
+ * 00 <- attribute length
+ * 64 <- attribute flags
+ * 08 <- attribute type code (community)
+ * 10 <- attribute length FF FF FF
+ * 01 <- value (NO_EXPORT)
+ * FF FF FF 02 <- value (NO_ADVERTISE)
+ * FF FF FF 03 <- value (NO_EXPORT_SUBCONFED)
+ * FF FF FF 10 <- unknown Community
+ *
+ * //NLRI
+ * 18 ac 11 02 <- IPv4 Prefix (172.17.2.0 / 24)
+ * 18 ac 11 01 <- IPv4 Prefix (172.17.1.0 / 24)
+ * 18 ac 11 00 <- IPv4 Prefix (172.17.0.0 / 24)
+ */
+ @Test
+ public void testGetUpdateMessage1() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(0), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(0), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateMessage);
+ final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+ // check fields
+
+ assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+ // attributes
+
+ final ASPath asPath = new ASPath(Lists.newArrayList(new ASNumber(65002)));
+
+ final IPv4NextHop nextHop = IPv4NextHop.forString("10.0.0.2");
+
+ final Set<Community> comms = Sets.newHashSet(Community.NO_EXPORT, Community.NO_ADVERTISE, Community.NO_EXPORT_SUBCONFED,
+ new Community(new ASNumber(0xFFFF), 0xFF10));
+
+ // check path attributes
+
+ // final PathAttribute originAttr = new PathAttribute(TypeCode.ORIGIN, false,
+ // true, false, false, BGPOrigin.IGP);
+ // assertEquals(originAttr, attrs.get(0));
+ //
+ // final PathAttribute asPathAttr = new PathAttribute(TypeCode.AS_PATH, false,
+ // true, false, false, asPath);
+ // assertEquals(asPathAttr, attrs.get(1));
+ //
+ // final PathAttribute nextHopAttr = new PathAttribute(TypeCode.NEXT_HOP, false,
+ // true, false, false, nextHop);
+ // assertEquals(nextHopAttr, attrs.get(2));
+ //
+ // final PathAttribute multiExitDisc = new PathAttribute(
+ // TypeCode.MULTI_EXIT_DISC, true, false, false, false, 0);
+ // assertEquals(multiExitDisc, attrs.get(3));
+ //
+ // final PathAttribute atomic = new PathAttribute(TypeCode.ATOMIC_AGGREGATE, false,
+ // true, true, false, null);
+ // assertEquals(atomic, attrs.get(4));
+ //
+ // final PathAttribute comm = new PathAttribute(TypeCode.COMMUNITIES, false,
+ // true, true, false, comms);
+ // assertEquals(comm, attrs.get(5));
+
+ // check nlri
+
+ // final Set<IPv4Prefix> nlri = Sets.newHashSet(pref1, pref2, pref3);
+ // assertEquals(nlri, ret.getBgpUpdateMessageBuilder().getNlri());
+
+ final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+ final NetworkRouteState<IPv4Address> routeState = new NetworkRouteState<>(new NetworkObjectState(asPath, comms, Collections.<ExtendedCommunity> emptySet()), nextHop);
+
+ // check API message
+
+ final Set<BGPObject> addedObjects = Sets.newHashSet();
+
+ final BGPRoute<IPv4Address> route1 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.17.2.0/24"), state, routeState);
+
+ addedObjects.add(route1);
+
+ final BGPRoute<IPv4Address> route2 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.17.1.0/24"), state, routeState);
+
+ addedObjects.add(route2);
+
+ final BGPRoute<IPv4Address> route3 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.17.0.0/24"), state, routeState);
+
+ addedObjects.add(route3);
+
+ final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+
+ assertEquals(expectedMessage, message);
+
+ }
+
+ /*
+ * Tests IPv6 NEXT_HOP, NLRI, ORIGIN.IGP, MULTI_EXIT_DISC, ORIGINATOR-ID, CLUSTER_LIST.
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 80 <- length (128) - including header
+ * 02 <- message type
+ * 00 00 <- withdrawn routes length
+ * 00 69 <- total path attribute length (105)
+ * 40 <- attribute flags
+ * 01 <- attribute type code (origin)
+ * 01 <- attribute length
+ * 00 <- Origin value (IGP)
+ * 40 <- attribute flags
+ * 02 <- attribute type code (as path)
+ * 06 <- attribute length
+ * 02 <- AS_SEQUENCE
+ * 01 <- path segment count
+ * 00 00 fd e9 <- path segment value (65001)
+ * 80 <- attribute flags
+ * 04 <- attribute type code (multi exit disc)
+ * 04 <- attribute length
+ * 00 00 00 00 <- value
+ * 80 <- attribute flags
+ * 09 <- attribute type code (originator id)
+ * 04 <- attribute length
+ * 7f 00 00 01 <- value (localhost ip)
+ * 80 <- attribute flags
+ * 0a <- attribute type code (cluster list)
+ * 08 <- attribute length
+ * 01 02 03 04 <- value
+ * 05 06 07 08 <- value
+ * 80 <- attribute flags
+ * 0e <- attribute type code (mp reach nlri)
+ * 40 <- attribute length
+ * 00 02 <- AFI (Ipv6)
+ * 01 <- SAFI (Unicast)
+ * 20 <- length of next hop
+ * 20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 01 <- global
+ * fe 80 00 00 00 00 00 00 c0 01 0b ff fe 7e 00 <- link local
+ * 00 <- reserved
+ *
+ * //NLRI
+ * 40 20 01 0d b8 00 01 00 02 <- IPv6 Prefix (2001:db8:1:2:: / 64)
+ * 40 20 01 0d b8 00 01 00 01 <- IPv6 Prefix (2001:db8:1:1:: / 64)
+ * 40 20 01 0d b8 00 01 00 00 <- IPv6 Prefix (2001:db8:1:: / 64)
+ *
+ */
+ @Test
+ public void testGetUpdateMessage2() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(1), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(1), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateMessage);
+ final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+ // check fields
+
+ assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+ // attributes
+
+ final ASPath asPath = new ASPath(Lists.newArrayList(new ASNumber(65001)));
+
+ final IPv6NextHop nextHop = IPv6NextHop.forString("2001:db8::1", "fe80::c001:bff:fe7e:0");
+
+ // final List<ClusterIdentifier> clusters = Lists.newArrayList(
+ // new ClusterIdentifier(new byte[] { 1, 2, 3, 4}),
+ // new ClusterIdentifier(new byte[] { 5, 6, 7, 8}));
+
+ // check path attributes
+
+ // final PathAttribute originAttr = new PathAttribute(TypeCode.ORIGIN, false,
+ // true, false, false, BGPOrigin.IGP);
+ // assertEquals(originAttr, attrs.get(0));
+ //
+ // final PathAttribute asPathAttr = new PathAttribute(TypeCode.AS_PATH, false,
+ // true, false, false, asPath);
+ // assertEquals(asPathAttr, attrs.get(1));
+ //
+ // final PathAttribute multiExitDisc = new PathAttribute(
+ // TypeCode.MULTI_EXIT_DISC, true, false, false, false, 0);
+ // assertEquals(multiExitDisc, attrs.get(2));
+ //
+ // final PathAttribute originatorAttr = new PathAttribute(
+ // TypeCode.ORIGINATOR_ID, true, false, false, false, IPv4.FAMILY.addressForString("127.0.0.1"));
+ // assertEquals(originatorAttr, attrs.get(3));
+ //
+ // final PathAttribute clusterAttr = new PathAttribute(
+ // TypeCode.CLUSTER_LIST, true, false, false, false, clusters);
+ // assertEquals(clusterAttr, attrs.get(4));
+
+ final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+ final NetworkRouteState<IPv6Address> routeState = new NetworkRouteState<>(new NetworkObjectState(asPath, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet()), nextHop);
+
+ // check API message
+
+ final Set<BGPObject> addedObjects = Sets.newHashSet();
+
+ final BGPRoute<IPv6Address> route1 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001:db8:1:2::/64"), state, routeState);
+
+ addedObjects.add(route1);
+
+ final BGPRoute<IPv6Address> route2 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001:db8:1:1::/64"), state, routeState);
+
+ addedObjects.add(route2);
+
+ final BGPRoute<IPv6Address> route3 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001:db8:1::/64"), state, routeState);
+
+ addedObjects.add(route3);
+
+ final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+
+ assertEquals(expectedMessage, message);
+ }
+
+ /*
+ * Tests more AS Numbers in AS_PATH, AGGREGATOR, ORIGIN.INCOMPLETE
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 4b <- length (75) - including header
+ * 02 <- message type
+ * 00 00 <- withdrawn routes length
+ * 00 30 <- total path attribute length (48)
+ * 40 <- attribute flags
+ * 01 <- attribute type code (origin)
+ * 01 <- attribute length
+ * 02 <- Origin value (Incomplete)
+ * 40 <- attribute flags
+ * 02 <- attribute type code (as path)
+ * 10 <- attribute length
+ * 02 <- AS_SEQUENCE
+ * 01 <- path segment count
+ * 00 00 00 1e <- path segment value (30)
+ * 01 <- AS_SET
+ * 02 <- path segment count
+ * 00 00 00 0a <- path segment value (10)
+ * 00 00 00 14 <- path segment value (20)
+ * 40 <- attribute flags
+ * 03 <- attribute type (Next hop)
+ * 04 <- attribute length
+ * 0a 00 00 09 <- value (10.0.0.9)
+ * 80 <- attribute flags
+ * 04 <- attribute type code (multi exit disc)
+ * 04 <- attribute length
+ * 00 00 00 00 <- value
+ * c0 <- attribute flags
+ * 07 <- attribute type (Aggregator)
+ * 08 <- attribute length
+ * 00 00 00 1e <- value (AS number = 30)
+ * 0a 00 00 09 <- value (IP address = 10.0.0.9)
+ *
+ * //NLRI
+ * 15 ac 10 00 <- IPv4 Prefix (172.16.0.0 / 21)
+ */
+ @Test
+ public void testGetUpdateMessage3() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(2), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(2), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateMessage);
+ final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+ // check fields
+ assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+ // attributes
+
+ final ASPath asPath = new ASPath(Lists.newArrayList(new ASNumber(30)), Sets.newHashSet(new ASNumber(10), new ASNumber(20)));
+
+ final BGPAggregator aggregator = new BGPAggregatorImpl<IPv4Address>(new ASNumber(30), IPv4.FAMILY.addressForString("10.0.0.9"));
+ final IPv4NextHop nextHop = IPv4NextHop.forString("10.0.0.9");
+
+ final IPv4Prefix pref1 = IPv4.FAMILY.prefixForString("172.16.0.0/21");
+
+ // check path attributes
+
+ // final PathAttribute originAttr = new PathAttribute(TypeCode.ORIGIN, false,
+ // true, false, false, BGPOrigin.INCOMPLETE);
+ // assertEquals(originAttr, attrs.get(0));
+ //
+ // final PathAttribute asPathAttr = new PathAttribute(TypeCode.AS_PATH, false,
+ // true, false, false, asPath);
+ // assertEquals(asPathAttr, attrs.get(1));
+ //
+ // final PathAttribute nextHopAttr = new PathAttribute(TypeCode.NEXT_HOP, false,
+ // true, false, false, nextHop);
+ // assertEquals(nextHopAttr, attrs.get(2));
+ //
+ // final PathAttribute multiExitDisc = new PathAttribute(
+ // TypeCode.MULTI_EXIT_DISC, true, false, false, false, 0);
+ // assertEquals(multiExitDisc, attrs.get(3));
+ //
+ // final PathAttribute agg = new PathAttribute(TypeCode.AGGREGATOR, true, true,
+ // false, false, aggregator);
+ // assertEquals(agg, attrs.get(4));
+ //
+ // // check nlri
+ //
+ // final Set<IPv4Prefix> nlri = Sets.newHashSet(pref1);
+ // assertEquals(nlri, ret.getBgpUpdateMessageBuilder().getNlri());
+
+ final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.INCOMPLETE, aggregator);
+ final NetworkRouteState<IPv4Address> routeState = new NetworkRouteState<>(new NetworkObjectState(asPath, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet()), nextHop);
+
+ // check API message
+
+ final Set<BGPObject> addedObjects = Sets.newHashSet();
+
+ final BGPRoute<IPv4Address> route1 = new BGPIPv4RouteImpl(pref1, state, routeState);
+
+ addedObjects.add(route1);
+
+ final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+
+ assertEquals(expectedMessage, message);
+
+ }
+
+ /*
+ * Tests empty AS_PATH, ORIGIN.EGP, LOCAL_PREF, EXTENDED_COMMUNITIES (Ipv4 Addr specific)
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 4A <- length (73) - including header
+ * 02 <- message type
+ * 00 00 <- withdrawn routes length
+ * 00 27 <- total path attribute length (39)
+ * 40 <- attribute flags
+ * 01 <- attribute type code (Origin)
+ * 01 <- attribute length
+ * 01 <- Origin value (EGP)
+ * 40 <- attribute flags
+ * 02 <- attribute type code (As path)
+ * 00 <- attribute length
+ * 40 <- attribute flags
+ * 03 <- attribute type (Next hop)
+ * 04 <- attribute length
+ * 03 03 03 03 <- value (3.3.3.3)
+ * 80 <- attribute flags
+ * 04 <- attribute type code (Multi exit disc)
+ * 04 <- attribute length
+ * 00 00 00 00 <- value
+ * 40 <- attribute flags
+ * 05 <- attribute type (Local Pref)
+ * 04 <- attribute length
+ * 00 00 00 64 <- value (100)
+ * 80 <- attribute flags
+ * 10 <- attribute type (extended community)
+ * 08 <- attribute length
+ * 01 04 <- value (type - Ipv4 Address Specific Extended Community)
+ * c0 a8 01 00 <- value (global adm. 198.162.1.0)
+ * 12 34 <- value (local adm. 4660)
+ *
+ * //NLRI
+ * 18 0a 1e 03 <- IPv4 Prefix (10.30.3.0 / 24)
+ * 18 0a 1e 02 <- IPv4 Prefix (10.30.2.0 / 24)
+ * 18 0a 1e 01 <- IPv4 Prefix (10.30.1.0 / 24)
+ */
+ @Test
+ public void testGetUpdateMessage4() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(3), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(3), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateMessage);
+ final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+ // check fields
+
+ assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+ // attributes
+
+ final IPv4NextHop nextHop = IPv4NextHop.forString("3.3.3.3");
+
+ final Set<ExtendedCommunity> comms = Sets.newHashSet((ExtendedCommunity) new Inet4SpecificExtendedCommunity(false, 4, IPv4.FAMILY.addressForString("192.168.1.0"), new byte[] {
+ 0x12, 0x34 }));
+
+ // check path attributes
+
+ // final PathAttribute originAttr = new PathAttribute(TypeCode.ORIGIN, false,
+ // true, false, false, BGPOrigin.EGP);
+ // assertEquals(originAttr, attrs.get(0));
+ //
+ // final PathAttribute asPathAttr = new PathAttribute(TypeCode.AS_PATH, false,
+ // true, false, false, asPath);
+ // assertEquals(asPathAttr, attrs.get(1));
+ //
+ // final PathAttribute nextHopAttr = new PathAttribute(TypeCode.NEXT_HOP, false,
+ // true, false, false, nextHop);
+ // assertEquals(nextHopAttr, attrs.get(2));
+ //
+ // final PathAttribute multiExitDisc = new PathAttribute(
+ // TypeCode.MULTI_EXIT_DISC, true, false, false, false, 0);
+ // assertEquals(multiExitDisc, attrs.get(3));
+ //
+ // final PathAttribute localPref = new PathAttribute(TypeCode.LOCAL_PREF, false,
+ // true, false, false, 100);
+ // assertEquals(localPref, attrs.get(4));
+
+ // check nlri
+ //
+ // final Set<IPv4Prefix> nlri = Sets.newHashSet(pref1, pref2, pref3);
+ // assertEquals(nlri, ret.getBgpUpdateMessageBuilder().getNlri());
+
+ final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.EGP, null);
+ final NetworkRouteState<IPv4Address> routeState = new NetworkRouteState<>(new NetworkObjectState(ASPath.EMPTY, Collections.<Community> emptySet(), comms), nextHop);
+
+ // check API message
+
+ final Set<BGPObject> addedObjects = Sets.newHashSet();
+
+ final BGPRoute<IPv4Address> route1 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("10.30.3.0/24"), state, routeState);
+
+ addedObjects.add(route1);
+
+ final BGPRoute<IPv4Address> route2 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("10.30.2.0/24"), state, routeState);
+
+ addedObjects.add(route2);
+
+ final BGPRoute<IPv4Address> route3 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("10.30.1.0/24"), state, routeState);
+
+ addedObjects.add(route3);
+
+ final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+
+ assertEquals(expectedMessage, message);
+ }
+
+ /*
+ * Tests withdrawn routes.
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 1c <- length (28) - including header
+ * 02 <- message type
+ * 00 05 <- withdrawn routes length (5)
+ * 1e ac 10 00 04 <- route (172.16.0.4)
+ * 00 00 <- total path attribute length
+ */
+ @Test
+ public void testGetUpdateMessage5() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(4), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(4), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateMessage);
+ final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+ // attributes
+
+ final IPv4Prefix pref1 = IPv4.FAMILY.prefixForString("172.16.0.4/30");
+
+ // check API message
+
+ final BGPUpdateEvent expectedMessage = new BGPUpdateMessageImpl(Collections.<BGPObject> emptySet(), Sets.newHashSet((Identifier) pref1));
+
+ assertEquals(expectedMessage, message);
+ }
+
+ /*
+ * Test EOR for IPv4.
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 17 <- length (23) - including header
+ * 02 <- message type
+ * 00 00 <- withdrawn routes length
+ * 00 00 <- total path attribute length
+ */
+ @Test
+ public void testEORIpv4() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(5), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(5), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateSynchronized);
+ final BGPUpdateSynchronized message = (BGPUpdateSynchronized) ret;
+
+ final BGPUpdateSynchronized expectedMessage = new BGPUpdateSynchronized() {
+
+ private static final long serialVersionUID = -5128220996581568885L;
+
+ @Override
+ public BGPTableType getTableType() {
+ return new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+ }
+ };
+ assertEquals(expectedMessage.getTableType(), message.getTableType());
+ }
+
+ /*
+ * End of Rib for Ipv6 consists of empty MP_UNREACH_NLRI, with AFI 2 and SAFI 1
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 1d <- length (29) - including header
+ * 02 <- message type
+ * 00 00 <- withdrawn routes length
+ * 00 06 <- total path attribute length
+ * 80 <- attribute flags
+ * 0f <- attribute type (15 - MP_UNREACH_NLRI)
+ * 03 <- attribute length
+ * 00 02 <- value (AFI 2: IPv6)
+ * 01 <- value (SAFI 1)
+ */
+ @Test
+ public void testEORIpv6() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(6), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(6), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateSynchronized);
+ final BGPUpdateSynchronized message = (BGPUpdateSynchronized) ret;
+
+ // check fields
+
+ final BGPUpdateSynchronized expectedMessage = new BGPUpdateSynchronized() {
+
+ private static final long serialVersionUID = -4811827044855997014L;
+
+ @Override
+ public BGPTableType getTableType() {
+ return new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast);
+ }
+ };
+ assertEquals(expectedMessage.getTableType(), message.getTableType());
+ }
+
+ /*
+ * End of Rib for LS consists of empty MP_UNREACH_NLRI, with AFI 16388 and SAFI 71
+ *
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 1d <- length (29) - including header
+ * 02 <- message type
+ * 00 00 <- withdrawn routes length
+ * 00 06 <- total path attribute length
+ * 80 <- attribute flags
+ * 0f <- attribute type (15 - MP_UNREACH_NLRI)
+ * 03 <- attribute length
+ * 40 04 <- value (AFI 16388: LS)
+ * 47 <- value (SAFI 71)
+ */
+ @Test
+ public void testEORLS() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(7), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(7), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateSynchronized);
+ final BGPUpdateSynchronized message = (BGPUpdateSynchronized) ret;
+
+ // check fields
+
+ final BGPUpdateSynchronized expectedMessage = new BGPUpdateSynchronized() {
+
+ private static final long serialVersionUID = 3677704232769769042L;
+
+ @Override
+ public BGPTableType getTableType() {
+ return new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Unicast);
+ }
+ };
+
+ assertEquals(expectedMessage.getTableType(), message.getTableType());
+ }
+
+ /*
+ * Tests BGP Link Ipv4
+ *
+ 00 00 <- withdrawn routes length
+ 01 48 <- total path attribute length (328)
+ 90 <- attribute flags
+ 0e <- attribute type code (MP reach)
+ 01 2c <- attribute extended length (300)
+ 40 04 <- AFI (16388 - Linkstate)
+ 47 <- SAFI (71 - Linkstate)
+ 04 <- next hop length
+ 19 19 19 01 <- nexthop (25.25.25.1)
+ 00 <- reserved
+
+ 00 02 <- NLRI type (2 - linkNLRI)
+ 00 5d <- NLRI length (93)
+ 03 <- ProtocolID - OSPF
+ 00 00 00 00 00 00 00 01 <- identifier
+
+ 01 00 <- local node descriptor type (256)
+ 00 24 <- length (36)
+ 02 00 <- node descriptor type (member AS - 512)
+ 00 04 <- length
+ 00 00 00 64 <- value (100)
+ 02 01 <- node descriptor type (bgpId - 513)
+ 00 04 <- length
+ 19 19 19 01 <- bgpId (25.25.25.1)
+ 02 02 <- node descriptor type (areaId - 514)
+ 00 04 <- length
+ 00 00 00 00 <- value
+ 02 03 <- node descriptor type (routeId - 515)
+ 00 08 <- length
+ 03 03 03 04 0b 0b 0b 03 <- OSPF Router Id
+
+ 01 01 <- remote node descriptor type (257)
+ 00 20 <- length (32)
+ 02 00 <- node descriptor type (member AS - 512)
+ 00 04 <- length
+ 00 00 00 64 <- value (100)
+ 02 01 <- node descriptor type (bgpId - 513)
+ 00 04 <- length
+ 19 19 19 01 <- bgpId (25.25.25.1)
+ 02 02 <- node descriptor type (areaId - 514)
+ 00 04 <- length
+ 00 00 00 00 <- value
+ 02 03 <- node descriptor type (routeId - 515)
+ 00 04 <- length
+ 03 03 03 04 <- OSPF Router Id
+
+ 01 03 <- link descriptor type (IPv4 interface address - 259)
+ 00 04 <- length (4)
+ 0b 0b 0b 03 <- value (11.11.11.3)
+
+ 00 02 <- NLRI type (2 - linkNLRI)
+ 00 5d <- NLRI length (93)
+ 03 <- ProtocolID - OSPF
+ 00 00 00 00 00 00 00 01 <- identifier
+
+ 01 00 <- local node descriptor type (256)
+ 00 24 <- length (36)
+ 02 00 <- node descriptor type (member AS - 512)
+ 00 04 <- length
+ 00 00 00 64 <- value (100)
+ 02 01 <- node descriptor type (bgpId - 513)
+ 00 04 <- length
+ 19 19 19 01 <- bgpId (25.25.25.1)
+ 02 02 <- node descriptor type (areaId - 514)
+ 00 04 <- length
+ 00 00 00 00 <- value
+ 02 03 <- node descriptor type (routeId - 515)
+ 00 08 <- length
+ 03 03 03 04 0b 0b 0b 03 <- OSPF Router Id
+
+ 01 01 <- remote node descriptor type (257)
+ 00 20 <- length (32)
+ 02 00 <- node descriptor type (member AS - 512)
+ 00 04 <- length
+ 00 00 00 64 <- value (100)
+ 02 01 <- node descriptor type (bgpId - 513)
+ 00 04 <- length
+ 19 19 19 01 <- bgpId (25.25.25.1)
+ 02 02 <- node descriptor type (areaId - 514)
+ 00 04 <- length
+ 00 00 00 00 <- value
+ 02 03 <- node descriptor type (routeId - 515)
+ 00 04 <- length
+ 01 01 01 02 <- OSPF Router Id
+
+ 01 03 <- link descriptor type (IPv4 interface address - 259)
+ 00 04 <- length
+ 0b 0b 0b 01 <- value (11.11.11.1)
+
+ 00 02 <- NLRI type (2 - linkNLRI)
+ 00 5d <- NLRI length (93)
+ 03 <- ProtocolID - OSPF
+ 00 00 00 00 00 00 00 01 <- identifier
+
+ 01 00 <- local node descriptor type (256)
+ 00 20 <- length (32)
+ 02 00 <- node descriptor type (member AS - 512)
+ 00 04 <- length
+ 00 00 00 64 <- value (100)
+ 02 01 <- node descriptor type (bgpId - 513)
+ 00 04 <- length
+ 19 19 19 01 <- bgpId (25.25.25.1)
+ 02 02 <- node descriptor type (areaId - 514)
+ 00 04 <- length
+ 00 00 00 00 <- value
+ 02 03 <- node descriptor type (routeId - 515)
+ 00 04 <- length
+ 01 01 01 02 <- OSPF Router Id
+
+ 01 01 <- remote node descriptor type (257)
+ 00 24 <- length (36)
+ 02 00 <- node descriptor type (member AS - 512)
+ 00 04 <- length
+ 00 00 00 64 <- value (100)
+ 02 01 <- node descriptor type (bgpId - 513)
+ 00 04 <- length
+ 19 19 19 01 <- bgpId (25.25.25.1)
+ 02 02 <- node descriptor type (areaId - 514)
+ 00 04 <- length
+ 00 00 00 00 <- value
+ 02 03 <- node descriptor type (routeId - 515)
+ 00 08 <- length
+ 03 03 03 04 0b 0b 0b 03 <- OSPF Router Id
+
+ 01 03 <- link descriptor type (IPv4 interface address - 259)
+ 00 04 <- length
+ 0b 0b 0b 01 <- value (11.11.11.1)
+
+ 40 <- attribute flags
+ 01 <- attribute type (Origin)
+ 01 <- attribute length
+ 00 <- value (IGP)
+ 40 <- attribute flags
+ 02 <- attribute type (AS Path)
+ 00 <- length
+ 40 <- attribute flags
+ 05 <- attribute type (local pref)
+ 04 <- length
+ 00 00 00 64 <- value
+ c0 <- attribute flags
+ 63 <- attribute type (Link STATE - 99)
+ 07 <- length
+ 04 47 <- link attribute (1095 - Metric)
+ 00 03 <- length
+ 00 00 01 <- value
+ */
+ @Test
+ public void testBGPLink() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(8), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(8), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateMessage);
+ final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+ // check fields
+
+ assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+ // network object state
+ final NetworkObjectState objState = new NetworkObjectState(ASPath.EMPTY, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+ final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+
+ // network link state
+ final DefaultingTypesafeContainer<Metric<?>> container = new DefaultingTypesafeContainer<Metric<?>>();
+ container.setDefaultEntry(new IGPMetric(1));
+ final NetworkLinkState linkState = new NetworkLinkState(objState, container, null, LinkProtectionType.UNPROTECTED, null, null, null);
+
+ final NodeIdentifierFactory f100 = new NodeIdentifierFactory(new ASNumber(100), new DomainIdentifier(new byte[] { 25, 25, 25, 1 }), new AreaIdentifier(new byte[] {
+ 0, 0, 0, 0 }));
+
+ final NodeIdentifier nodeid1 = f100.identifierForRouter(new OSPFv3LANIdentifier(new OSPFRouterIdentifier(new byte[] { 3, 3, 3, 4 }), new OSPFInterfaceIdentifier(new byte[] {
+ 0x0b, 0x0b, 0x0b, 0x03 })));
+ final NodeIdentifier nodeid2 = f100.identifierForRouter(new OSPFRouterIdentifier(new byte[] { 3, 3, 3, 4 }));
+
+ final NodeIdentifier nodeid3 = f100.identifierForRouter(new OSPFRouterIdentifier(new byte[] { 1, 1, 1, 2 }));
+
+ // check API message
+
+ final LinkIdentifier linkId1 = new LinkIdentifier(null, new LinkAnchor(nodeid1, new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString("11.11.11.3"))), new LinkAnchor(nodeid2, null));
+ final LinkIdentifier linkId2 = new LinkIdentifier(null, new LinkAnchor(nodeid1, new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString("11.11.11.1"))), new LinkAnchor(nodeid3, null));
+ final LinkIdentifier linkId3 = new LinkIdentifier(null, new LinkAnchor(nodeid3, new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString("11.11.11.1"))), new LinkAnchor(nodeid1, null));
+
+ final BGPLink link1 = new BGPLinkImpl(state, linkId1, linkState);
+ final BGPLink link2 = new BGPLinkImpl(state, linkId2, linkState);
+ final BGPLink link3 = new BGPLinkImpl(state, linkId3, linkState);
+
+ final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(Sets.newHashSet((BGPObject) link1, (BGPObject) link2,
+ (BGPObject) link3), Collections.<Identifier> emptySet());
+
+ assertEquals(expectedMessage, message);
+ }
+
+ /*
+ * TEST BGP Node
+ *
+ * 00 00 <- withdrawn routes length
+ 00 b2 <- total path attribute length (178)
+ 90 <- attribute flags
+ 0e <- attribute type code (MP reach)
+ 00 a0 <- attribute extended length (160)
+ 40 04 <- AFI (16388 - Linkstate)
+ 47 <- SAFI (71 - Linkstate)
+ 04 <- next hop length
+ 19 19 19 01 - nexthop (25.25.25.1)
+ 00 <- reserved
+ 00 01 <- NLRI type (1 - nodeNLRI)
+ 00 31 <- NLRI length (49)
+ 03 <- ProtocolID - OSPF
+ 00 00 00 00 00 00 00 01 <- identifier
+
+ 01 00 <- local node descriptor type (256)
+ 00 24 <- length (36)
+ 02 00 <- node descriptor type (member AS - 512)
+ 00 04 <- length
+ 00 00 00 64 <- value (100)
+ 02 01 <- node descriptor type (bgpId - 513)
+ 00 04 <- length
+ 19 19 19 01 <- bgpId (25.25.25.1)
+ 02 02 <- node descriptor type (areaId - 514)
+ 00 04 <- length
+ 00 00 00 00 <- value
+ 02 03 <- node descriptor type (routeId - 515)
+ 00 08 <- length
+ 03 03 03 04 0b 0b 0b 03 <- OSPF Router Id
+
+ 00 01 <- NLRI type (1 - nodeNLRI)
+ 00 2d <- NLRI length (45)
+ 03 <- ProtocolID - OSPF
+ 00 00 00 00 00 00 00 01 <- identifier
+
+ 01 00 <- local node descriptor type (256)
+ 00 20 <- length (32)
+ 02 00 <- node descriptor type (member AS - 512)
+ 00 04 <- length
+ 00 00 00 64 <- value (100)
+ 02 01 <- node descriptor type (bgpId - 513)
+ 00 04 <- length
+ 19 19 19 01 <- bgpId (25.25.25.1)
+ 02 02 <- node descriptor type (areaId - 514)
+ 00 04 <- length
+ 00 00 00 00 <- value
+ 02 03 <- node descriptor type (routeId - 515)
+ 00 04 <- length
+ 03 03 03 04 <- OSPF Router Id
+
+ 00 01 <- NLRI type (1 - nodeNLRI)
+ 00 2d <- NLRI length (45)
+ 03 <- ProtocolID - OSPF
+ 00 00 00 00 00 00 00 01 <- identifier
+ 01 00 <- local node descriptor type (256)
+ 00 20 <- length (32)
+ 02 00 <- node descriptor type (member AS - 512)
+ 00 04 <- length
+ 00 00 00 64 <- value (100)
+ 02 01 <- node descriptor type (bgpId - 513)
+ 00 04 <- length
+ 19 19 19 01 <- bgpId (25.25.25.1)
+ 02 02 <- node descriptor type (areaId - 514)
+ 00 04 <- length
+ 00 00 00 00 <- value
+ 02 03 <- node descriptor type (routeId - 515)
+ 00 04 <- length
+ 01 01 01 02 <- OSPF Router Id
+
+ 40 <- attribute flags
+ 01 <- attribute type (Origin)
+ 01 <- attribute length
+ 00 <- value (IGP)
+ 40 <- attribute flags
+ 02 <- attribute type (AS Path)
+ 00 <- length
+ 40 <- attribute flags
+ 05 <- attribute type (local pref)
+ 04 <- length
+ 00 00 00 64 <- value
+ */
+ @Test
+ public void testBGPNode() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(9), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(9), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent ret = BGPUpdateMessageParser.parse(body, header.getLength());
+
+ assertTrue(ret instanceof BGPUpdateMessage);
+ final BGPUpdateMessage message = (BGPUpdateMessage) ret;
+
+ // check fields
+
+ assertEquals(Collections.EMPTY_SET, message.getRemovedObjects());
+
+ // network object state
+ final NetworkObjectState objState = new NetworkObjectState(ASPath.EMPTY, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+ final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+ final NetworkNodeState nstate = new NetworkNodeState(objState, Collections.<TopologyIdentifier, TopologyNodeInformation> emptyMap(), Collections.<ISISAreaIdentifier> emptySet(), false, false, Collections.<RouterIdentifier> emptySet(), null);
+
+ // network link state
+
+ final NodeIdentifierFactory f100 = new NodeIdentifierFactory(new ASNumber(100), new DomainIdentifier(new byte[] { 25, 25, 25, 1 }), new AreaIdentifier(new byte[] {
+ 0, 0, 0, 0 }));
+
+ final NodeIdentifier nodeid1 = f100.identifierForRouter(new OSPFv3LANIdentifier(new OSPFRouterIdentifier(new byte[] { 3, 3, 3, 4 }), new OSPFInterfaceIdentifier(new byte[] {
+ 0x0b, 0x0b, 0x0b, 0x03 })));
+ final NodeIdentifier nodeid2 = f100.identifierForRouter(new OSPFRouterIdentifier(new byte[] { 3, 3, 3, 4 }));
+
+ final NodeIdentifier nodeid3 = f100.identifierForRouter(new OSPFRouterIdentifier(new byte[] { 1, 1, 1, 2 }));
+
+ // check API message
+
+ final BGPNode node1 = new BGPNodeImpl(state, nodeid1, nstate);
+ final BGPNode node2 = new BGPNodeImpl(state, nodeid2, nstate);
+ final BGPNode node3 = new BGPNodeImpl(state, nodeid3, nstate);
+
+ final BGPUpdateMessage expectedMessage = new BGPUpdateMessageImpl(Sets.newHashSet((BGPObject) node1, (BGPObject) node2,
+ (BGPObject) node3), Collections.<Identifier> emptySet());
+
+ assertEquals(expectedMessage, message);
+ }
+
+ /*
+ * ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <- marker
+ * 00 98 <- length (69) - including header
+ * 01 <- message type
+ * 04 <- BGP version
+ * 00 64 <- My AS Number (AS TRANS in this case)
+ * 00 b4 <- Hold Time
+ * 00 00 00 00 <- BGP Identifier
+ * 28 <- Optional Parameters Length
+ * 02 <- opt. param. type (capabilities)
+ * 06 <- length
+ * 01 <- capability code (MP Extensions for BGP4)
+ * 04 <- length
+ * 00 01 00 01 <- AFI 1, SAFI 1
+ * 02 <- opt. param. type (capabilities)
+ * 06 <- length
+ * 01 <- capability code (MP Extensions for BGP4)
+ * 04 <- length
+ * 00 02 00 01 <- AFI 2, SAFI 1
+ * 02 <- opt. param. type (capabilities)
+ * 06 <- length
+ * 01 <- capability code (MP Extensions for BGP4)
+ * 04 <- length
+ * 40 04 00 47 <- AFI 16388, SAFI 71
+ * 02 <- opt. param. type (capabilities)
+ * 02 <- length
+ * 80 <- capability code (private)
+ * 00 <- length
+ * 02 <- opt. param. type (capabilities)
+ * 02 <- length
+ * 02 <- capability code (Route refresh)
+ * 00 <- length
+ * 02 <- opt. param. type (capabilities)
+ * 06 <- length
+ * 41 <- capability code (AS4 octet support)
+ * 04 <- length
+ * 00 00 00 64 <- AS number
+ */
+ @Test
+ public void testOpenMessage() throws Exception {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(inputBytes.get(13), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(inputBytes.get(13), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPMessageFactory msgFactory = new BGPMessageFactory();
+ final BGPOpenMessage open = (BGPOpenMessage) msgFactory.parse(body, header);
+ final Set<BGPTableType> types = Sets.newHashSet();
+ for (final BGPParameter param : open.getOptParams()) {
+ if (param instanceof MultiprotocolCapability) {
+ types.add(((MultiprotocolCapability) param).getTableType());
+ }
+ }
+ final Set<BGPTableType> expected = Sets.newHashSet(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast),
+ new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast),
+ new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Linkstate));
+ msgFactory.close();
+ assertEquals(expected, types);
+ }
+
+ @Test
+ public void testHashCodeEquals() throws UnknownHostException {
+ final BGPAggregator agg1 = new BGPAggregatorImpl<IPv4Address>(new ASNumber(6), IPv4.FAMILY.addressForString("10.0.0.9"));
+
+ final BGPAggregator agg2 = new BGPAggregatorImpl<IPv4Address>(new ASNumber(6), IPv4.FAMILY.addressForString("10.0.0.9"));
+
+ assertEquals(agg1, agg2);
+ assertEquals("HashCodes should be equal", agg1.hashCode(), agg2.hashCode());
+ assertEquals("toString should be equal", agg1.toString(), agg2.toString());
+
+ final IPv4MP mp41 = new IPv4MP(false, new IPv4NextHop(IPv4.FAMILY.addressForString("10.0.0.9")), null);
+
+ final IPv4MP mp42 = new IPv4MP(false, new IPv4NextHop(IPv4.FAMILY.addressForString("10.0.0.9")), null);
+
+ assertEquals(mp41, mp42);
+ assertEquals("HashCodes should be equal", mp41.hashCode(), mp42.hashCode());
+ assertEquals("toString should be equal", mp41.toString(), mp42.toString());
+
+ final IPv6MP mp61 = new IPv6MP(false, new IPv6NextHop(IPv6.FAMILY.addressForString("fe80::c001:bff:fe7e:0")), null);
+
+ final IPv6MP mp62 = new IPv6MP(false, new IPv6NextHop(IPv6.FAMILY.addressForString("fe80::c001:bff:fe7e:0")), null);
+
+ assertEquals(mp61, mp62);
+ assertEquals("HashCodes should be equal", mp61.hashCode(), mp62.hashCode());
+ assertEquals("toString should be equal", mp61.toString(), mp62.toString());
+
+ final PathAttribute localPref1 = new PathAttribute(TypeCode.LOCAL_PREF, false, true, false, false, 100);
+
+ final PathAttribute localPref2 = new PathAttribute(TypeCode.LOCAL_PREF, false, true, false, false, 100);
+
+ assertEquals(localPref1, localPref2);
+ assertEquals("HashCodes should be equal", localPref1.hashCode(), localPref2.hashCode());
+ assertEquals("toString should be equal", localPref1.toString(), localPref2.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateEvent;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.util.HexDumpBGPFileParser;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class BGPUpdateMessageParserTest {
+
+ @Test
+ @Ignore
+ public void testNodeParsing() throws Exception {
+ final List<byte[]> result = HexDumpBGPFileParser.parseMessages(new File(this.getClass().getResource("/bgp-update-nodes.txt").getFile()));
+ assertEquals(1, result.size());
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(result.get(0), 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(result.get(0), BGPMessageHeader.COMMON_HEADER_LENGTH);
+ final BGPUpdateEvent event = BGPUpdateMessageParser.parse(body, header.getLength());
+ final BGPUpdateMessage updateMessage = (BGPUpdateMessage) event;
+ final Set<BGPObject> addedObjects = updateMessage.getAddedObjects();
+ assertEquals(14, addedObjects.size());
+ assertEquals(0, updateMessage.getRemovedObjects().size());
+ for (final BGPObject bgpObject : addedObjects) {
+ assertTrue(bgpObject instanceof BGPNode);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASSpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.Inet4SpecificExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.OpaqueExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteOriginCommunity;
+import org.opendaylight.protocol.bgp.concepts.RouteTargetCommunity;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.BGPAggregatorImpl;
+import org.opendaylight.protocol.bgp.parser.impl.BGPLinkMP;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateMessageImpl;
+import org.opendaylight.protocol.bgp.parser.impl.ByteList;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.CommunitiesParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.MPReachParser;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.ISOSystemIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv4InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISLANIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.ISISRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.InterfaceIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkAnchor;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifierFactory;
+import org.opendaylight.protocol.bgp.linkstate.SourceProtocol;
+import com.google.common.collect.Sets;
+
+public class ComplementaryTest {
+
+ @Test
+ public void testBGPAggregatorImpl() {
+ final BGPAggregatorImpl<IPv4Address> ipv4 = new BGPAggregatorImpl<IPv4Address>(new ASNumber(5524), IPv4.FAMILY.addressForString("124.55.42.1"));
+ final BGPAggregatorImpl<IPv4Address> ipv4i = new BGPAggregatorImpl<IPv4Address>(new ASNumber(5525), IPv4.FAMILY.addressForString("124.55.42.1"));
+
+ assertNotSame(ipv4.hashCode(), ipv4i.hashCode());
+
+ assertEquals(ipv4, new BGPAggregatorImpl<IPv4Address>(new ASNumber(5524), IPv4.FAMILY.addressForString("124.55.42.1")));
+
+ assertNotSame(ipv4.getASNumber(), ipv4i.getASNumber());
+
+ assertEquals(ipv4.getNetworkAddress(), ipv4i.getNetworkAddress());
+ }
+
+ @Test
+ public void testBGPLinkMP() {
+ final NodeIdentifier localnodeid = new NodeIdentifier(new ASNumber(25600, 0), null, null, new ISISRouterIdentifier(new ISOSystemIdentifier(new byte[] {
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 })));
+ final NodeIdentifier remotenodeid = NodeIdentifierFactory.localIdentifier(new ISISLANIdentifier(new ISOSystemIdentifier(new byte[] {
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }), (short) 1));
+
+ final InterfaceIdentifier ifaceid = new IPv4InterfaceIdentifier(IPv4.FAMILY.addressForString("10.1.1.1"));
+
+ final LinkIdentifier l = new LinkIdentifier(null, new LinkAnchor(localnodeid, ifaceid), new LinkAnchor(remotenodeid, ifaceid));
+
+ final Set<LinkIdentifier> links = Sets.newHashSet(l);
+
+ final BGPLinkMP link = new BGPLinkMP(0, SourceProtocol.Direct, true, links);
+
+ final BGPLinkMP link1 = new BGPLinkMP(0, SourceProtocol.Direct, true, Collections.<LinkIdentifier> emptySet());
+
+ assertNotSame(link.hashCode(), link1.hashCode());
+
+ assertEquals(link, new BGPLinkMP(0, SourceProtocol.Direct, true, links));
+
+ assertEquals(link.hashCode(), (new BGPLinkMP(0, SourceProtocol.Direct, true, links)).hashCode());
+
+ assertNotSame(link.toString(), link1.toString());
+ }
+
+ @Test
+ public void testBGPUpdateMessageImpl() {
+ final BGPUpdateMessageImpl msg = new BGPUpdateMessageImpl(null, null);
+ final BGPUpdateMessageImpl msg1 = new BGPUpdateMessageImpl(null, null);
+
+ assertEquals(msg, msg1);
+
+ assertEquals(msg.hashCode(), msg1.hashCode());
+
+ assertNotNull(msg.toString());
+
+ assertNull(msg.getAddedObjects());
+ assertNull(msg.getRemovedObjects());
+
+ assertNotSame(msg1, null);
+ }
+
+ @Test
+ public void testCommunitiesParser() {
+ ASSpecificExtendedCommunity as = null;
+ try {
+ as = (ASSpecificExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 0, 5, 0, 54, 0, 0, 1, 76 });
+ } catch (final BGPDocumentedException e1) {
+ fail("Not expected exception: " + e1);
+ }
+ assertEquals(as, new ASSpecificExtendedCommunity(false, 5, new ASNumber(54), new byte[] { 0, 0, 1, 76 }));
+
+ try {
+ as = (ASSpecificExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 40, 5, 0, 54, 0, 0, 1, 76 });
+ } catch (final BGPDocumentedException e1) {
+ fail("Not expected exception: " + e1);
+ }
+ assertEquals(as, new ASSpecificExtendedCommunity(true, 5, new ASNumber(54), new byte[] { 0, 0, 1, 76 }));
+
+ RouteTargetCommunity rtc = null;
+ try {
+ rtc = (RouteTargetCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 1, 2, 0, 35, 4, 2, 8, 7 });
+ } catch (final BGPDocumentedException e1) {
+ fail("Not expected exception: " + e1);
+ }
+ assertEquals(rtc, new RouteTargetCommunity(new ASNumber(35), new byte[] { 4, 2, 8, 7 }));
+
+ RouteOriginCommunity roc = null;
+ try {
+ roc = (RouteOriginCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 0, 3, 0, 24, 4, 2, 8, 7 });
+ } catch (final BGPDocumentedException e1) {
+ fail("Not expected exception: " + e1);
+ }
+ assertEquals(roc, new RouteOriginCommunity(new ASNumber(24), new byte[] { 4, 2, 8, 7 }));
+
+ Inet4SpecificExtendedCommunity sec = null;
+ try {
+ sec = (Inet4SpecificExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 41, 6, 12, 51, 2, 5, 21, 45 });
+ } catch (final BGPDocumentedException e1) {
+ fail("Not expected exception: " + e1);
+ }
+ assertEquals(sec, new Inet4SpecificExtendedCommunity(true, 6, IPv4.FAMILY.addressForString("12.51.2.5"), new byte[] { 21, 45 }));
+
+ OpaqueExtendedCommunity oec = null;
+ try {
+ oec = (OpaqueExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 3, 6, 21, 45, 5, 4, 3, 1 });
+ } catch (final BGPDocumentedException e1) {
+ fail("Not expected exception: " + e1);
+ }
+ assertEquals(oec, new OpaqueExtendedCommunity(false, 6, new byte[] { 21, 45, 5, 4, 3, 1 }));
+
+ try {
+ oec = (OpaqueExtendedCommunity) CommunitiesParser.parseExtendedCommunity(new byte[] { 43, 6, 21, 45, 5, 4, 3, 1 });
+ } catch (final BGPDocumentedException e1) {
+ fail("Not expected exception: " + e1);
+ }
+ assertEquals(oec, new OpaqueExtendedCommunity(true, 6, new byte[] { 21, 45, 5, 4, 3, 1 }));
+
+ try {
+ CommunitiesParser.parseExtendedCommunity(new byte[] { 11, 11, 21, 45, 5, 4, 3, 1 });
+ fail("Exception should have occured.");
+ } catch (final BGPDocumentedException e) {
+ assertEquals("Could not parse Extended Community type: 11", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testMPReachParser() {
+ String msg = "";
+ try {
+ MPReachParser.parseSafi(5);
+ fail("Exception shoul have occured.");
+ } catch (final BGPParsingException e) {
+ msg = e.getMessage();
+ }
+ assertEquals("Subsequent Address Family Identifier: '5' not supported.", msg);
+
+ try {
+ MPReachParser.parseAfi(6);
+ fail("Exception should have occured.");
+ } catch (final BGPParsingException e) {
+ msg = e.getMessage();
+ }
+ assertEquals("Address Family Identifier: '6' not supported.", msg);
+ }
+
+ @Test
+ public void testByteList() {
+ final ByteList b1 = new ByteList();
+ b1.add(new byte[] { 3, 4, 8 });
+ b1.add(new byte[] { 3, 4, 9 });
+
+ final ByteList b2 = new ByteList();
+ b2.add(new byte[] { 3, 4, 8 });
+ b2.add(new byte[] { 3, 4, 9 });
+
+ assertEquals(b1, b2);
+ assertEquals(b1.toString(), b2.toString());
+ }
+
+ @Test
+ public void testMessageParser() throws IOException {
+ final BGPMessageFactory parser = new BGPMessageFactory();
+ String ex = "";
+ try {
+ parser.put(null);
+ } catch (final IllegalArgumentException e) {
+ ex = e.getMessage();
+ }
+ parser.close();
+ assertEquals("BGPMessage is mandatory.", ex);
+ }
+}
--- /dev/null
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+01 f2 02 00 00 01 db 90 0e 01 bb 00 1b 01 04 0a
+01 01 0a 00 00 02 00 1b 01 00 00 00 01 00 00 13
+01 02 00 04 00 00 00 64 01 06 00 07 00 00 00 00
+00 01 00 00 02 00 1b 01 00 00 00 01 00 00 13 01
+02 00 04 00 00 00 64 01 06 00 07 00 00 00 00 00
+01 03 00 02 00 1b 01 00 00 00 01 00 00 13 01 02
+00 04 00 00 00 64 01 06 00 07 00 00 00 00 00 02
+00 00 02 00 1b 01 00 00 00 01 00 00 13 01 02 00
+04 00 00 00 64 01 06 00 07 00 00 00 00 00 02 05
+00 02 00 1b 01 00 00 00 01 00 00 13 01 02 00 04
+00 00 00 64 01 06 00 07 00 00 00 00 00 10 00 00
+02 00 1b 01 00 00 00 01 00 00 13 01 02 00 04 00
+00 00 64 01 06 00 07 00 00 00 00 00 10 01 00 02
+00 1b 01 00 00 00 01 00 00 13 01 02 00 04 00 00
+00 64 01 06 00 07 00 00 00 00 00 10 05 00 02 00
+1b 01 00 00 00 01 00 00 13 01 02 00 04 00 00 00
+64 01 06 00 07 00 00 00 00 00 10 07 00 02 00 1b
+01 00 00 00 01 00 00 13 01 02 00 04 00 00 00 64
+01 06 00 07 00 00 00 00 00 30 00 00 02 00 1b 01
+00 00 00 01 00 00 13 01 02 00 04 00 00 00 64 01
+06 00 07 00 00 00 00 00 30 01 00 02 00 1b 01 00
+00 00 01 00 00 13 01 02 00 04 00 00 00 64 01 06
+00 07 00 00 00 00 00 40 00 00 02 00 1b 01 00 00
+00 01 00 00 13 01 02 00 04 00 00 00 64 01 06 00
+07 00 00 00 00 00 40 01 00 02 00 1b 01 00 00 00
+01 00 00 13 01 02 00 04 00 00 00 64 01 06 00 07
+00 00 00 00 00 40 03 00 02 00 1b 01 00 00 00 01
+00 00 13 01 02 00 04 00 00 00 64 01 06 00 07 00
+00 02 05 00 03 00 40 01 01 00 40 02 00 40 05 04
+00 00 00 64 80 0a 04 14 14 14 14 80 09 04 64 64
+64 0a
\ No newline at end of file
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-parser-mock</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-parser-mock</artifactId>
+ <description>BGP Parser Mock Implementation</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-impl</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.parser.mock
+ </Export-Package>
+ <Import-Package>
+ org.opendaylight.protocol.bgp.parser,
+ org.opendaylight.protocol.framework,
+ org.opendaylight.protocol.concepts
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-PARSER-MOCK Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.mock;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+
+/**
+ * Mock implementation of {@link BGPMessageParser}. It implements the required interface by having two internal maps,
+ * each used in one of the methods. It looks up the key provided to the method and returns whatever value is stored in
+ * the map.
+ */
+public class BGPMessageParserMock implements BGPMessageParser {
+ private final Map<byte[], BGPMessage> messages;
+
+ /**
+ * @param updateMessages Map<byte[], BGPUpdateEvent>
+ */
+ public BGPMessageParserMock(final Map<byte[], BGPMessage> messages) {
+ this.messages = messages;
+ }
+
+ @Override
+ public void close() throws IOException {
+ // nothing
+ }
+
+ @Override
+ public BGPMessage parse(final byte[] bytes, final ProtocolMessageHeader msgHeader) throws DeserializerException, DocumentedException {
+ final BGPMessage ret = this.messages.get(bytes);
+ if (ret == null)
+ throw new IllegalArgumentException("Undefined message encountered");
+ return ret;
+ }
+
+ @Override
+ public byte[] put(final ProtocolMessage msg) {
+ // nothing
+ return null;
+ }
+}
--- /dev/null
+\14\13\12\11\10\ f\ e\r\f\v
+ \b\a\ 6\ 5\ 4\ 3\ 2\ 1
\ No newline at end of file
--- /dev/null
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+ <body>
+ <head>${project.artifactId}</head>
+ <links>
+ <item name="${project.artifactId}" href="index.html"/>
+ </links>
+
+ <menu ref="parent"/>
+
+ <menu ref="reports"/>
+
+
+ </body>
+</project>
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.parser.mock;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.concepts.NextHop;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateMessageImpl;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.mock.BGPMessageParserMock;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class BGPMessageParserMockTest {
+
+ private final byte[][] inputBytes = new byte[11][];
+ private final List<BGPUpdateMessage> messages = new ArrayList<BGPUpdateMessage>();
+
+ @Before
+ public void init() throws Exception {
+ // Creating input bytes and update messages
+ for (int i = 0; i < this.inputBytes.length; i++) {
+ this.inputBytes[i] = this.fillInputBytes(i);
+ this.messages.add(this.fillMessages(i));
+ }
+ }
+
+ /**
+ * Test if mock implementation of parser returns correct message
+ *
+ * @throws DocumentedException
+ * @throws DeserializerException
+ * @throws IOException
+ */
+ @Test
+ public void testGetUpdateMessage() throws DeserializerException, DocumentedException, IOException {
+ final Map<byte[], BGPMessage> updateMap = Maps.newHashMap();
+ for (int i = 0; i < this.inputBytes.length; i++) {
+ updateMap.put(this.inputBytes[i], this.messages.get(i));
+ }
+
+ final BGPMessageParserMock mockParser = new BGPMessageParserMock(updateMap);
+
+ for (int i = 0; i < this.inputBytes.length; i++) {
+ assertEquals(this.messages.get(i), mockParser.parse(this.inputBytes[i], null));
+ }
+ assertThat(this.messages.get(3), not(mockParser.parse(this.inputBytes[8], null)));
+
+ mockParser.close();
+ }
+
+ /**
+ * Test if method throws IllegalArgumentException after finding no BGPUpdateMessage associated with given byte[] key
+ *
+ * @throws DocumentedException
+ * @throws DeserializerException
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetUpdateMessageException() throws DeserializerException, DocumentedException, IOException {
+ final Map<byte[], BGPMessage> updateMap = Maps.newHashMap();
+ for (int i = 0; i < this.inputBytes.length; i++) {
+ updateMap.put(this.inputBytes[i], this.messages.get(i));
+ }
+
+ final BGPMessageParserMock mockParser = new BGPMessageParserMock(updateMap);
+ mockParser.parse(new byte[] { 7, 4, 6 }, new BGPMessageHeader());
+
+ mockParser.close();
+ }
+
+ /**
+ * Helper method to fill inputBytes variable
+ *
+ * @param fileNumber parameter to distinguish between files from which bytes are read
+ */
+ private byte[] fillInputBytes(final int fileNumber) throws Exception {
+
+ final InputStream is = this.getClass().getResourceAsStream("/up" + fileNumber + ".bin");
+ final ByteArrayOutputStream bis = new ByteArrayOutputStream();
+ final byte[] data = new byte[60];
+ int nRead = 0;
+
+ while ((nRead = is.read(data, 0, data.length)) != -1) {
+ bis.write(data, 0, nRead);
+ }
+ bis.flush();
+ return bis.toByteArray();
+ }
+
+ /**
+ * Helper method to fill messages variable
+ *
+ * @param asn this parameter is passed to ASNumber constructor
+ */
+ private BGPUpdateMessage fillMessages(final int asn) throws UnknownHostException {
+
+ final List<ASNumber> asnums = new ArrayList<ASNumber>();
+ asnums.add(new ASNumber(asn));
+ final ASPath asPath = new ASPath(asnums);
+ final NextHop<IPv6Address> nextHop = new IPv6NextHop(new IPv6Address(InetAddress.getByName("2001:db8::1")), new IPv6Address(InetAddress.getByName("fe80::c001:bff:fe7e:0")));
+
+ final Prefix<IPv6Address> pref1 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:1:2::")), 64);
+ final Prefix<IPv6Address> pref2 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:1:1::")), 64);
+ final Prefix<IPv6Address> pref3 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:1::")), 64);
+
+ final Set<BGPObject> addedObjects = new HashSet<BGPObject>();
+
+ final NetworkRouteState<IPv6Address> nstate = new NetworkRouteState<>(new NetworkObjectState(asPath, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet()), nextHop);
+ final BaseBGPObjectState state = new BaseBGPObjectState(BGPOrigin.IGP, null);
+
+ final BGPRoute<IPv6Address> route1 = new BGPIPv6RouteImpl(pref1, state, nstate);
+ final BGPRoute<IPv6Address> route2 = new BGPIPv6RouteImpl(pref2, state, nstate);
+ final BGPRoute<IPv6Address> route3 = new BGPIPv6RouteImpl(pref3, state, nstate);
+ addedObjects.add(route1);
+ addedObjects.add(route2);
+ addedObjects.add(route3);
+
+ return new BGPUpdateMessageImpl(addedObjects, Collections.<Identifier> emptySet());
+ }
+
+ @Test
+ public void testGetOpenMessage() throws DeserializerException, DocumentedException, IOException {
+ final Map<byte[], BGPMessage> openMap = Maps.newHashMap();
+
+ final Set<BGPTableType> type = Sets.newHashSet();
+ type.add(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.MPLSLabeledVPN));
+
+ final List<BGPParameter> params = Lists.newArrayList();
+ params.add(new MultiprotocolCapability(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.MPLSLabeledVPN)));
+
+ final byte[] input = new byte[] { 5, 8, 13, 21 };
+
+ openMap.put(input, new BGPOpenMessage(new ASNumber(30), (short) 30, null, params));
+
+ final BGPMessageParserMock mockParser = new BGPMessageParserMock(openMap);
+
+ final Set<BGPTableType> result = Sets.newHashSet();
+ for (final BGPParameter p : ((BGPOpenMessage) mockParser.parse(input, null)).getOptParams()) {
+ if (p instanceof MultiprotocolCapability) {
+ result.add(((MultiprotocolCapability) p).getTableType());
+ }
+ }
+
+ assertEquals(type, result);
+
+ mockParser.close();
+ }
+}
--- /dev/null
+\14\13\12\11\10\ f\ e\r\f\v
+ \b\a\ 6\ 5\ 4\ 3\ 2\ 1
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>protocol-parent</artifactId>
+ <version>0.1</version>
+ </parent>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-parent</artifactId>
+ <description>BGP-related components</description>
+ <packaging>pom</packaging>
+ <version>1.0</version>
+ <name>${project.artifactId}</name>
+
+ <modules>
+ <module>concepts</module>
+ <module>linkstate</module>
+ <module>parser-api</module>
+ <module>parser-impl</module>
+ <module>parser-mock</module>
+ <module>rib-api</module>
+ <module>rib-impl</module>
+ <module>testtool</module>
+ <module>rib-mock</module>
+ <module>util</module>
+ </modules>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-rib-api</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-rib-api</artifactId>
+ <description>BGP RIB API</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-linkstate</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Import-Package>
+ org.opendaylight.protocol.bgp.concepts,
+ org.opendaylight.protocol.bgp.linkstate,
+ org.opendaylight.protocol.bgp.parser,
+ org.opendaylight.protocol.concepts,
+ com.google.common.base,
+ com.google.guava,
+ org.slf4j,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.rib,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.version}</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-RIB-API Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.concepts.InitialListenerEvents;
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+
+@ThreadSafe
+public abstract class AbstractRIBChangeListener implements RIBEventListener {
+ @Override
+ synchronized public final void onRIBEvent(final RIBEvent event) {
+ onRIBEventImpl(event);
+ }
+
+ abstract protected void onRIBEventImpl(final RIBEvent event);
+
+ synchronized public final ListenerRegistration<RIBEventListener> register(final RIB rib) {
+ InitialListenerEvents<RIBEventListener, RIBEvent> ile = rib.registerListener(this);
+ for (RIBEvent e : ile.getEvents())
+ onRIBEvent(e);
+
+ return ile.getRegistration();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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;
+
+import org.opendaylight.protocol.concepts.InitialListenerEvents;
+
+public interface RIB {
+
+ public InitialListenerEvents<RIBEventListener, RIBEvent> registerListener(RIBEventListener listener);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.opendaylight.protocol.bgp.parser.BGPLinkState;
+import org.opendaylight.protocol.bgp.parser.BGPNodeState;
+import org.opendaylight.protocol.bgp.parser.BGPPrefixState;
+import org.opendaylight.protocol.bgp.parser.BGPRouteState;
+
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import com.google.common.base.Preconditions;
+
+public final class RIBChangedEvent extends RIBEvent {
+ private final Map<LinkIdentifier, BGPLinkState> links;
+ private final Map<NodeIdentifier, BGPNodeState> nodes;
+ private final Map<PrefixIdentifier<?>, BGPPrefixState> prefixes;
+ private final Map<Prefix<?>, BGPRouteState<?>> routes;
+
+ public RIBChangedEvent(final Map<LinkIdentifier, BGPLinkState> links, final Map<NodeIdentifier, BGPNodeState> nodes,
+ final Map<PrefixIdentifier<?>, BGPPrefixState> prefixes, final Map<Prefix<?>, BGPRouteState<?>> routes) {
+ super();
+ this.links = Collections.unmodifiableMap(Preconditions.checkNotNull(links));
+ this.nodes = Collections.unmodifiableMap(Preconditions.checkNotNull(nodes));
+ this.prefixes = Collections.unmodifiableMap(Preconditions.checkNotNull(prefixes));
+ this.routes = Collections.unmodifiableMap(Preconditions.checkNotNull(routes));
+ }
+
+ public RIBChangedEvent(final Map<Prefix<?>, BGPRouteState<?>> routes) {
+ this(Collections.<LinkIdentifier, BGPLinkState> emptyMap(), Collections.<NodeIdentifier, BGPNodeState> emptyMap(), Collections.<PrefixIdentifier<?>, BGPPrefixState> emptyMap(), routes);
+ }
+
+ public RIBChangedEvent(final Map<LinkIdentifier, BGPLinkState> links, final Map<NodeIdentifier, BGPNodeState> nodes,
+ final Map<PrefixIdentifier<?>, BGPPrefixState> prefixes) {
+ this(links, nodes, prefixes, Collections.<Prefix<?>, BGPRouteState<?>> emptyMap());
+ }
+
+ /**
+ * @return the links
+ */
+ public final Map<LinkIdentifier, BGPLinkState> getLinks() {
+ return this.links;
+ }
+
+ /**
+ * @return the nodes
+ */
+ public final Map<NodeIdentifier, BGPNodeState> getNodes() {
+ return this.nodes;
+ }
+
+ /**
+ * @return the prefixes
+ */
+ public final Map<PrefixIdentifier<?>, BGPPrefixState> getPrefixes() {
+ return this.prefixes;
+ }
+
+ /**
+ * @return the routes
+ */
+ public final Map<Prefix<?>, BGPRouteState<?>> getRoutes() {
+ return this.routes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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;
+
+public abstract class RIBEvent {
+ protected RIBEvent() {
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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;
+
+import java.util.EventListener;
+
+public interface RIBEventListener extends EventListener {
+ void onRIBEvent(RIBEvent event);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+
+public final class RIBSynchronizedEvent extends RIBEvent {
+ private final BGPTableType table;
+
+ public RIBSynchronizedEvent(final BGPTableType table) {
+ this.table = table;
+ }
+
+ public BGPTableType getTable() {
+ return table;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-rib-impl</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-rib-impl</artifactId>
+ <description>BGP RIB implementation</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-linkstate</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-rib-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-util</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-impl</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Import-Package>
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.framework,
+ com.google.common.base,
+ com.google.common.collect,
+ com.google.common.eventbus,
+ javax.annotation,
+ javax.management,
+ org.opendaylight.protocol.bgp.concepts,
+ org.opendaylight.protocol.bgp.linkstate,
+ org.opendaylight.protocol.bgp.parser,
+ org.opendaylight.protocol.bgp.parser.impl,
+ org.opendaylight.protocol.bgp.parser.message,
+ org.opendaylight.protocol.bgp.parser.parameter,
+ org.opendaylight.protocol.bgp.rib,
+ org.opendaylight.protocol.bgp.util,
+ org.opendaylight.protocol.util,
+ org.slf4j,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.rib.impl
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.version}</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-RIB-IMPL Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.IOException;
+
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+
+/**
+ * BGP interface. At this time it only supports listening to changes seen by the backing device, typically a network
+ * element. Abstracts away connection issues - listener starts getting notifications once connection is established.
+ * Implementation of this interface is required to send all previous messages.
+ */
+public interface BGP {
+ /**
+ * Register for BGP update feed. Specified listener will have the BGP information synchronized. The registration
+ * needs to be explicitly closed in order to stop receiving the updates.
+ *
+ * @param listener {@link BGPSessionListener}
+ * @throws IllegalStateException if there is already a listener registered
+ * @throws IOException if some IO error occurred
+ * @return ListenerRegistration
+ */
+ public ListenerRegistration<BGPSessionListener> registerUpdateListener(BGPSessionListener listener) throws IOException;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+
+
+/**
+ * Implementation of {@link BGPConnection}.
+ */
+public class BGPConnectionImpl implements BGPConnection {
+
+ private final InetSocketAddress address;
+
+ private final BGPSessionListener listener;
+
+ private final BGPSessionPreferences proposal;
+
+ private final BGPSessionProposalChecker checker;
+
+ /**
+ * Merges together BGP specific connection attributes.
+ *
+ * @param address inet socket address
+ * @param listener bgp session listener
+ * @param proposal bgp session preferences
+ * @param checker bgp session proposal checker
+ */
+ public BGPConnectionImpl(final InetSocketAddress address, final BGPSessionListener listener, final BGPSessionPreferences proposal,
+ final BGPSessionProposalChecker checker) {
+ super();
+ this.address = address;
+ this.listener = listener;
+ this.proposal = proposal;
+ this.checker = checker;
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return this.address;
+ }
+
+ @Override
+ public BGPSessionListener getListener() {
+ return this.listener;
+ }
+
+ @Override
+ public BGPSessionPreferences getProposal() {
+ return this.proposal;
+ }
+
+ @Override
+ public BGPSessionProposalChecker getProposalChecker() {
+ return this.checker;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
+
+import org.opendaylight.protocol.framework.Dispatcher;
+
+/**
+ * Implementation of BGPDispatcher.
+ */
+public final class BGPDispatcherImpl implements BGPDispatcher, Closeable {
+
+ private final Dispatcher dispatcher;
+
+ public BGPDispatcherImpl(final Dispatcher dispatcher) throws IOException {
+ this.dispatcher = dispatcher;
+ }
+
+ @Override
+ public BGPSession createClient(final BGPConnection connection, final BGPMessageParser parser) throws IOException {
+ return (BGPSession) this.dispatcher.createClient(connection, new BGPSessionFactory(parser), BGPInputStream.FACTORY);
+ }
+
+ public Dispatcher getDispatcher() {
+ return this.dispatcher;
+ }
+
+ @Override
+ public void close() {
+ // This is only necessary for configuration interaction
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposal;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+
+/**
+ * Implementation of {@link BGP}.
+ */
+public class BGPImpl implements BGP, Closeable {
+ /**
+ * Wrapper class to give listener a close method.
+ */
+ public class BGPListenerRegistration implements ListenerRegistration<BGPSessionListener> {
+
+ private final BGPSessionListener listener;
+
+ private final BGPSession session;
+
+ public BGPListenerRegistration(final BGPSessionListener l, final BGPSession session) {
+ this.listener = l;
+ this.session = session;
+ }
+
+ @Override
+ public void close() {
+ this.session.close();
+ }
+
+ @Override
+ public BGPSessionListener getListener() {
+ return this.listener;
+ }
+ }
+
+ private final BGPDispatcher dispatcher;
+
+ private final BGPMessageParser parser;
+
+ private final InetSocketAddress address;
+
+ private final BGPSessionProposal proposal;
+
+ private final BGPSessionProposalChecker checker;
+
+ public BGPImpl(final BGPDispatcher dispatcher, final BGPMessageParser parser, final InetSocketAddress address,
+ final BGPSessionProposal proposal, final BGPSessionProposalChecker checker) throws IOException {
+ this.dispatcher = dispatcher;
+ this.parser = parser;
+ this.address = address;
+ this.proposal = proposal;
+ this.checker = checker;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ListenerRegistration<BGPSessionListener> registerUpdateListener(final BGPSessionListener listener) throws IOException {
+ final BGPSession session = this.dispatcher.createClient(
+ new BGPConnectionImpl(this.address, listener, this.proposal.getProposal(), this.checker), this.parser);
+ return new BGPListenerRegistration(listener, session);
+ }
+
+ @Override
+ public void close() {
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.util.ByteArray;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolInputStream;
+import org.opendaylight.protocol.framework.ProtocolInputStreamFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Input stream for BGP.
+ */
+public class BGPInputStream implements ProtocolInputStream {
+
+ private final static Logger logger = LoggerFactory.getLogger(BGPInputStream.class);
+
+ /**
+ * BGP implementation for protocol input stream factory.
+ */
+ public static final ProtocolInputStreamFactory FACTORY = new ProtocolInputStreamFactory() {
+ @Override
+ public ProtocolInputStream getProtocolInputStream(final PipedInputStream pis, final ProtocolMessageFactory factory) {
+ return new BGPInputStream(pis, factory);
+ }
+ };
+
+ private final ProtocolMessageFactory factory;
+
+ private final PipedInputStream inputStream;
+
+ @VisibleForTesting
+ protected BGPMessageHeader header;
+
+ private BGPInputStream(final PipedInputStream inputStream, final ProtocolMessageFactory factory) {
+ this.factory = factory;
+ this.inputStream = inputStream;
+ this.header = new BGPMessageHeader();
+ }
+
+ /**
+ * Check availability of a message in underlying input stream. A message is available when there are more or the
+ * same amount of bytes in the stream as the message length is specified in message header. If there are not enough
+ * bytes for the message or even to read a message header, return false.
+ *
+ * @return true if there are enough bytes to read a message false if there are not enough bytes to read a message or
+ * a message header.
+ * @throws IOException
+ */
+ @Override
+ public synchronized boolean isMessageAvailable() throws IOException {
+ if (!this.header.isParsed()) {
+ // No header, try to parse it
+ this.header = (BGPMessageHeader) parseHeaderIfAvailable();
+
+ if (!this.header.isParsed()) {
+ // No luck, we do not have a message
+ return false;
+ }
+ }
+ // message length contains the size of the header too
+ if (this.inputStream.available() < (this.header.getLength() - BGPMessageHeader.COMMON_HEADER_LENGTH)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * If there are enough bytes in the underlying stream, parse the message. Blocking, till there are enough bytes to
+ * read, therefore the call of method isMessageAvailable() is suggested first.
+ *
+ * @return protocol specific message
+ * @throws DeserializerException
+ * @throws IOException
+ * @throws DocumentedException
+ */
+ @Override
+ public synchronized BGPMessage getMessage() throws DeserializerException, IOException, DocumentedException {
+ // isMessageAvailable wasn't called, or there were not enough bytes to form message header
+ // blocking till the header is available
+ while (!this.header.isParsed()) {
+ this.header = (BGPMessageHeader) parseHeaderIfAvailable();
+ }
+ final byte[] bytes = new byte[this.header.getLength() - BGPMessageHeader.COMMON_HEADER_LENGTH]; // message
+ // length
+ // contains the
+ // size of the
+ // header too
+ // blocking till the whole message is available
+ if (this.inputStream.read(bytes) == -1) {
+ throw new IOException("PipedInputStream was closed, before data could be read from it.");
+ }
+
+ final BGPMessage msg = (BGPMessage) this.factory.parse(bytes, this.header);
+ this.header.setParsed(); // if we have all the bytes to send the message for parsing, clear the header, to let
+ // know,
+
+ return msg;
+ }
+
+ /**
+ * Checks if there are enough bytes to parse a header and parses it. Non-blocking: if there are not enough bytes to
+ * parse a message header, returns false.
+ *
+ * @return cleared header if no header is available
+ * @return header object when enough data is available
+ */
+ private ProtocolMessageHeader parseHeaderIfAvailable() throws IOException {
+ final byte[] messageHeader = new byte[BGPMessageHeader.COMMON_HEADER_LENGTH];
+ if (this.inputStream.available() < BGPMessageHeader.COMMON_HEADER_LENGTH || this.inputStream.read(messageHeader) == -1) {
+ this.header.setParsed();
+ return this.header;
+ }
+ logger.debug("Attempt to parse BGP message header from bytes: {}", ByteArray.bytesToHexString(messageHeader));
+ return this.header.fromBytes(messageHeader);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Comparator;
+
+import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
+
+
+/**
+ * This comparator is intended to implement BGP Best Path Selection algorithm, as described at
+ *
+ * @see http://www.cisco.com/en/US/tech/tk365/technologies_tech_note09186a0080094431.shtml
+ *
+ * @param <T> Actual object state reference
+ */
+final class BGPObjectComparator<T extends AbstractBGPObjectState<?>> implements Comparator<T> {
+ @Override
+ public int compare(final T o1, final T o2) {
+ if (o1 == o2)
+ return 0;
+ if (o1 == null)
+ return 1;
+ if (o2 == null)
+ return -1;
+
+ // FIXME: look at ASPath
+ // FIXME: look at everything else :-)
+
+ return 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class representing a peer. We have a single instance for each peer, which provides translation from BGP events into
+ * RIB actions.
+ */
+public final class BGPPeer extends BGPSessionListener {
+ private static final Logger logger = LoggerFactory.getLogger(BGPPeer.class);
+ private Set<BGPTableType> tables;
+ private final String name;
+ private final RIBImpl rib;
+
+ public BGPPeer(final RIBImpl rib, final String name) {
+ this.rib = Preconditions.checkNotNull(rib);
+ this.name = Preconditions.checkNotNull(name);
+ }
+
+ @Override
+ public void onMessage(final BGPMessage message) {
+ if (message instanceof BGPUpdateMessage) {
+ final BGPUpdateMessage m = (BGPUpdateMessage) message;
+ this.rib.updateTables(this, m.getAddedObjects(), m.getRemovedObjects());
+ } else
+ logger.info("Ignoring unhandled message class " + message.getClass());
+ }
+
+ @Override
+ public void onSessionUp(final Set<BGPTableType> remoteParams) {
+ logger.info("Session with peer {} went up with tables: {}", this.name, remoteParams);
+ }
+
+ @Override
+ public void onSessionDown(final BGPSession session, final Exception e) {
+ // FIXME: support graceful restart
+ for (final BGPTableType t : this.tables)
+ this.rib.clearTable(this, t);
+ }
+
+ @Override
+ public void onSessionTerminated(final BGPError cause) {
+ logger.info("Session with peer {} terminated", this.name);
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("name", this.name);
+ toStringHelper.add("tables", this.tables);
+ return toStringHelper;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Timer;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.ProtocolSessionFactory;
+import org.opendaylight.protocol.framework.SessionParent;
+
+/**
+ *
+ */
+public final class BGPSessionFactory implements ProtocolSessionFactory {
+
+ private final BGPMessageParser parser;
+
+ public BGPSessionFactory(final BGPMessageParser parser) {
+ this.parser = parser;
+ }
+
+ @Override
+ public ProtocolSession getProtocolSession(final SessionParent parent, final Timer timer, final ProtocolConnection connection,
+ final int sessionId) {
+ return new BGPSessionImpl(parent, timer, (BGPConnection) connection, sessionId, this.parser);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolOutputStream;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+import com.google.common.collect.Sets;
+
+class BGPSessionImpl implements BGPSession, ProtocolSession {
+
+ private static final Logger logger = LoggerFactory.getLogger(BGPSessionImpl.class);
+
+ /**
+ * KeepAlive Timer is to be scheduled periodically, each time it starts, it sends KeepAlive Message.
+ */
+ private class KeepAliveTimer extends TimerTask {
+ private final BGPSessionImpl parent;
+
+ public KeepAliveTimer(final BGPSessionImpl parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public void run() {
+ this.parent.handleKeepaliveTimer();
+ }
+ }
+
+ /**
+ * HoldTimer is to be scheduled periodically, when it expires, it closes BGP session.
+ */
+ private class HoldTimer extends TimerTask {
+ private final BGPSessionImpl parent;
+
+ public HoldTimer(final BGPSessionImpl parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public void run() {
+ this.parent.handleHoldTimer();
+ }
+ }
+
+ private static final int DEFAULT_HOLD_TIMER_VALUE = 15;
+
+ public static int HOLD_TIMER_VALUE = DEFAULT_HOLD_TIMER_VALUE; // 240
+
+ public int KEEP_ALIVE_TIMER_VALUE;
+
+ /**
+ * Possible states for Finite State Machine
+ */
+ private enum State {
+ IDLE, OPEN_SENT, OPEN_CONFIRM, ESTABLISHED
+ }
+
+ /**
+ * Actual state of the FSM.
+ */
+ private State state;
+
+ /**
+ * System.nanoTime value about when was sent the last message Protected to be updated also in tests.
+ */
+ protected long lastMessageSentAt;
+
+ /**
+ * System.nanoTime value about when was received the last message
+ */
+ private long lastMessageReceivedAt;
+
+ private final int sessionId;
+
+ private final BGPSessionListener listener;
+
+ /**
+ * Open message with session characteristics that were accepted by another BGP (sent from this session).
+ */
+ private BGPSessionPreferences localOpen = null;
+
+ /**
+ * Open Object with session characteristics for this session (sent from another BGP speaker).
+ */
+ private BGPSessionPreferences remoteOpen = null;
+
+ private final ProtocolOutputStream outputStream;
+
+ /**
+ * Timer object grouping FSM Timers
+ */
+ private final Timer stateTimer;
+
+ private final SessionParent parent;
+
+ private final BGPMessageParser parser;
+
+ private final BGPSessionProposalChecker checker;
+
+ private final BGPSynchronization sync;
+
+ private int kaCounter = 0;
+
+ BGPSessionImpl(final SessionParent parent, final Timer timer, final BGPConnection connection, final int sessionId,
+ final BGPMessageParser parser) {
+ this.state = State.IDLE;
+ this.listener = connection.getListener();
+ this.sessionId = sessionId;
+ this.localOpen = connection.getProposal();
+ this.outputStream = new ProtocolOutputStream();
+ this.stateTimer = timer;
+ this.parent = parent;
+ this.parser = parser;
+ this.checker = connection.getProposalChecker();
+ this.sync = new BGPSynchronization(this.listener);
+ }
+
+ @Override
+ public void close() {
+ logger.debug("Closing session: " + this);
+ if (this.state == State.ESTABLISHED) {
+ this.sendMessage(new BGPNotificationMessage(BGPError.CEASE));
+ }
+ this.changeState(State.IDLE);
+ this.parent.onSessionClosed(this);
+ }
+
+ @Override
+ public void startSession() {
+ logger.debug("Session started.");
+ this.sendMessage(new BGPOpenMessage(this.localOpen.getMyAs(), (short) this.localOpen.getHoldTime(), this.localOpen.getBgpId(), this.localOpen.getParams()));
+ this.stateTimer.schedule(new HoldTimer(this), DEFAULT_HOLD_TIMER_VALUE * 1000);
+ this.changeState(State.OPEN_SENT);
+ }
+
+ @Override
+ public ProtocolOutputStream getStream() {
+ return this.outputStream;
+ }
+
+ /**
+ * Handles incoming message based on their type.
+ *
+ * @param msg incoming message
+ */
+ @Override
+ public void handleMessage(final ProtocolMessage msg) {
+ final BGPMessage bgpMsg = (BGPMessage) msg;
+ // Update last reception time
+ this.lastMessageReceivedAt = System.nanoTime();
+
+ // Open messages are handled internally, but are parsed also in bgp-parser, so notify bgp listener
+ if (bgpMsg instanceof BGPOpenMessage) {
+ this.handleOpenMessage((BGPOpenMessage) bgpMsg);
+ }
+ // Keepalives are handled internally
+ else if (bgpMsg instanceof BGPKeepAliveMessage) {
+ this.handleKeepAliveMessage();
+ }
+ // Notifications are handled internally
+ else if (bgpMsg instanceof BGPNotificationMessage) {
+ logger.info("Session closed because Notification message received: {}" + ((BGPNotificationMessage) bgpMsg).getError());
+ this.closeWithoutMessage();
+ this.listener.onSessionTerminated(((BGPNotificationMessage) bgpMsg).getError());
+ } else {
+ this.listener.onMessage(bgpMsg);
+ }
+ }
+
+ @Override
+ public void handleMalformedMessage(final DeserializerException e) {
+ logger.warn("Received malformed message: {}", e.getMessage(), e);
+ this.terminate(BGPError.FSM_ERROR);
+ }
+
+ @Override
+ public void handleMalformedMessage(final DocumentedException e) {
+ logger.warn("Received malformed message: {}", e.getMessage(), e);
+ this.terminate(((BGPDocumentedException) e).getError());
+ }
+
+ @Override
+ public void endOfInput() {
+ if (this.state != State.IDLE) {
+ this.listener.onSessionDown(this, new IOException("End of input detected. Close the session."));
+ }
+ }
+
+ @Override
+ public ProtocolMessageFactory getMessageFactory() {
+ return this.parser;
+ }
+
+ @Override
+ public void onConnectionFailed(final IOException e) {
+ logger.info("Connection failed before finishing: {}", e.getMessage(), e);
+ this.listener.onSessionDown(this, e);
+ }
+
+ @Override
+ public int maximumMessageSize() {
+ return 4096;
+ }
+
+ void sendMessage(final BGPMessage msg) {
+ this.outputStream.putMessage(msg, this.parser);
+ this.lastMessageSentAt = System.nanoTime();
+ logger.debug("Sent message: " + msg);
+ this.parent.checkOutputBuffer(this);
+ }
+
+ private void closeWithoutMessage() {
+ logger.debug("Closing session: " + this);
+ HOLD_TIMER_VALUE = DEFAULT_HOLD_TIMER_VALUE;
+ this.changeState(State.IDLE);
+ this.parent.onSessionClosed(this);
+ }
+
+ /**
+ * Closes PCEP session from the parent with given reason. A message needs to be sent, but parent doesn't have to be
+ * modified, because he initiated the closing. (To prevent concurrent modification exception).
+ *
+ * @param closeObject
+ */
+ private void terminate(final BGPError error) {
+ this.sendMessage(new BGPNotificationMessage(error));
+ this.closeWithoutMessage();
+ this.listener.onSessionTerminated(error);
+ }
+
+ /**
+ * If HoldTimer expires, the session ends. If a message (whichever) was received during this period, the HoldTimer
+ * will be rescheduled by HOLD_TIMER_VALUE + the time that has passed from the start of the HoldTimer to the time at
+ * which the message was received. If the session was closed by the time this method starts to execute (the session
+ * state will become IDLE), then rescheduling won't occur.
+ */
+ private synchronized void handleHoldTimer() {
+ final long ct = System.nanoTime();
+
+ final long nextHold = (long) (this.lastMessageReceivedAt + (HOLD_TIMER_VALUE * 1E9));
+
+ if (this.state != State.IDLE) {
+ if (ct >= nextHold) {
+ logger.debug("HoldTimer expired. " + new Date());
+ this.terminate(BGPError.HOLD_TIMER_EXPIRED);
+ return;
+ }
+ this.stateTimer.schedule(new HoldTimer(this), (long) ((nextHold - ct) / 1E6));
+ }
+ }
+
+ /**
+ * If KeepAlive Timer expires, sends KeepAlive message. If a message (whichever) was send during this period, the
+ * KeepAlive Timer will be rescheduled by KEEP_ALIVE_TIMER_VALUE + the time that has passed from the start of the
+ * KeepAlive timer to the time at which the message was sent. If the session was closed by the time this method
+ * starts to execute (the session state will become IDLE), that rescheduling won't occur.
+ */
+ private synchronized void handleKeepaliveTimer() {
+ final long ct = System.nanoTime();
+
+ long nextKeepalive = (long) (this.lastMessageSentAt + (this.KEEP_ALIVE_TIMER_VALUE * 1E9));
+
+ if (this.state == State.ESTABLISHED) {
+ if (ct >= nextKeepalive) {
+ this.sendMessage(new BGPKeepAliveMessage());
+ nextKeepalive = (long) (this.lastMessageSentAt + (this.KEEP_ALIVE_TIMER_VALUE * 1E9));
+ }
+ this.stateTimer.schedule(new KeepAliveTimer(this), (long) ((nextKeepalive - ct) / 1E6));
+ }
+ }
+
+ private void changeState(final State finalState) {
+ final String desc = "Changed to state: ";
+ switch (finalState) {
+ case IDLE:
+ logger.debug(desc + State.IDLE);
+ this.state = State.IDLE;
+ return;
+ case OPEN_SENT:
+ logger.debug(desc + State.OPEN_SENT);
+ if (this.state != State.IDLE) {
+ throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.OPEN_SENT);
+ }
+ this.state = State.OPEN_SENT;
+ return;
+ case OPEN_CONFIRM:
+ logger.debug(desc + State.OPEN_CONFIRM);
+ if (this.state == State.ESTABLISHED) {
+ throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.OPEN_CONFIRM);
+ }
+ this.state = State.OPEN_CONFIRM;
+ return;
+ case ESTABLISHED:
+ logger.debug(desc + State.ESTABLISHED);
+ if (this.state != State.OPEN_CONFIRM) {
+ throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.ESTABLISHED);
+ }
+ this.state = State.ESTABLISHED;
+ return;
+ }
+ }
+
+ /**
+ * Open message should be handled only if the FSM is in OPEN_SENT or IDLE state. When in IDLE state, the Open
+ * message was received _before_ local Open message was sent. When in OPEN_SENT state, the message was received
+ * _after_ local Open message was sent.
+ *
+ * @param msg received Open Message.
+ */
+ private void handleOpenMessage(final BGPOpenMessage msg) {
+ this.remoteOpen = new BGPSessionPreferences(msg.getMyAS(), msg.getHoldTime(), msg.getBgpId(), msg.getOptParams());
+ logger.debug("Received message: {}", msg.toString());
+ if (this.state != State.IDLE && this.state != State.OPEN_SENT) {
+ this.terminate(BGPError.FSM_ERROR);
+ return;
+ }
+ // if the session characteristics were unacceptable, the session is terminated
+ // with given BGP error
+ try {
+ this.checker.checkSessionCharacteristics(this.remoteOpen);
+ } catch (final BGPDocumentedException e) {
+ this.terminate(e.getError());
+ }
+ // the session characteristics were acceptable
+ HOLD_TIMER_VALUE = this.remoteOpen.getHoldTime();
+ logger.debug("Session chars are acceptable. Overwriting: holdtimer: {}", HOLD_TIMER_VALUE);
+ // when in IDLE state, we haven't send Open Message yet, do it now
+ if (this.state == State.IDLE) {
+ this.sendMessage(new BGPOpenMessage(this.localOpen.getMyAs(), (short) this.localOpen.getHoldTime(), this.localOpen.getBgpId(), this.localOpen.getParams()));
+ }
+ this.sendMessage(new BGPKeepAliveMessage());
+ // if the timer is not disabled
+ if (HOLD_TIMER_VALUE != 0) {
+ this.KEEP_ALIVE_TIMER_VALUE = HOLD_TIMER_VALUE / 3;
+ this.stateTimer.schedule(new KeepAliveTimer(this), this.KEEP_ALIVE_TIMER_VALUE * 1000);
+ this.stateTimer.schedule(new HoldTimer(this), HOLD_TIMER_VALUE * 1000);
+ }
+ this.changeState(State.OPEN_CONFIRM);
+ }
+
+ /**
+ * KeepAlive message should be explicitly parsed in FSM when its state is OPEN_CONFIRM. Otherwise is handled by the
+ * KeepAliveTimer or it's invalid.
+ */
+ private void handleKeepAliveMessage() {
+ logger.debug("Received KeepAlive messsage.");
+ if (this.state == State.OPEN_CONFIRM) {
+ if (HOLD_TIMER_VALUE != 0) {
+ this.stateTimer.schedule(new HoldTimer(this), HOLD_TIMER_VALUE * 1000);
+ this.stateTimer.schedule(new KeepAliveTimer(this), this.KEEP_ALIVE_TIMER_VALUE * 1000);
+ }
+ this.changeState(State.ESTABLISHED);
+ final Set<BGPTableType> tts = Sets.newHashSet();
+ if (this.remoteOpen.getParams() != null) {
+ for (final BGPParameter param : this.remoteOpen.getParams()) {
+ if (param instanceof MultiprotocolCapability) {
+ tts.add(((MultiprotocolCapability) param).getTableType());
+ }
+ }
+ }
+ this.sync.addTableTypes(tts);
+ this.listener.onSessionUp(tts);
+ // check if the KA is EOR for some AFI/SAFI
+ } else if (this.state == State.ESTABLISHED) {
+ this.kaCounter++;
+ if (this.kaCounter >= 2) {
+ this.sync.kaReceived();
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("BGPSessionImpl [state=");
+ builder.append(this.state);
+ builder.append(", sessionId=");
+ builder.append(this.sessionId);
+ builder.append(", localOpen=");
+ builder.append(this.localOpen);
+ builder.append(", remoteOpen=");
+ builder.append(this.remoteOpen);
+ builder.append(", outputStream=");
+ builder.append(this.outputStream);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+
+/**
+ * Basic implementation of BGP Session Proposal Checker. Session characteristics are always acceptable.
+ */
+public final class BGPSessionProposalCheckerImpl extends BGPSessionProposalChecker implements Closeable {
+
+ public BGPSessionProposalCheckerImpl() {
+
+ }
+
+ @Override
+ public SessionPreferences getNewProposal(final SessionPreferences oldOpen) {
+ throw new IllegalStateException("This method shoudln't be called in BGP.");
+ }
+
+ @Override
+ public Boolean checkSessionCharacteristics(final SessionPreferences openObj) throws BGPDocumentedException {
+ return true;
+ }
+
+ @Override
+ public void close() throws IOException {
+ // nothing to close
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.List;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.parameter.AS4BytesCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposal;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.collect.Lists;
+
+/**
+ * Basic implementation of BGP Session Proposal. The values are taken from conf-bgp.
+ */
+public final class BGPSessionProposalImpl extends BGPSessionProposal implements Closeable {
+
+ private final short holdTimer;
+
+ private final ASNumber as;
+
+ private final IPv4Address bgpId;
+
+ private final BGPSessionPreferences prefs;
+
+ public BGPSessionProposalImpl(final short holdTimer, final ASNumber as, final IPv4Address bgpId) {
+ this.holdTimer = holdTimer;
+ this.as = as;
+ this.bgpId = bgpId;
+
+ final BGPTableType ipv4 = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+ final BGPTableType linkstate = new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Linkstate);
+ final List<BGPParameter> tlvs = Lists.newArrayList();
+ tlvs.add(new MultiprotocolCapability(ipv4));
+ tlvs.add(new MultiprotocolCapability(linkstate));
+ // final Map<BGPTableType, Boolean> tableTypes = Maps.newHashMap();
+ // tableTypes.put(ipv4, true);
+ // tableTypes.put(linkstate,true);
+ // tlvs.add(new GracefulCapability(true, 0, tableTypes));
+ tlvs.add(new AS4BytesCapability(as));
+ this.prefs = new BGPSessionPreferences(as, holdTimer, bgpId, tlvs);
+
+ }
+
+ @Override
+ public BGPSessionPreferences getProposal() {
+ return this.prefs;
+ }
+
+ @Override
+ public void close() throws IOException {
+ // nothing to close
+ }
+
+ /**
+ * @return the holdTimer
+ */
+ public short getHoldTimer() {
+ return this.holdTimer;
+ }
+
+ /**
+ * @return the as
+ */
+ public ASNumber getAs() {
+ return this.as;
+ }
+
+ /**
+ * @return the bgpId
+ */
+ public IPv4Address getBgpId() {
+ return this.bgpId;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPPrefix;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+/**
+ * BGP speaker (without Graceful restart capability) sends KeepAlive message after sending all initial Update messages
+ * with certain AFI/SAFI. For each AFI/SAFI, it sends one KA message. As it is undetermined which KA message belongs to
+ * which AFI/SAFI, an algorithm needed to be implemented.
+ */
+public class BGPSynchronization {
+
+ private static final Logger logger = LoggerFactory.getLogger(BGPSynchronization.class);
+
+ private class SyncVariables {
+
+ private boolean upd = false;
+ private boolean eor = false;
+
+ public void setUpd(final boolean upd) {
+ this.upd = upd;
+ }
+
+ public void setEorTrue() {
+ this.eor = true;
+ }
+
+ public boolean getEor() {
+ return this.eor;
+ }
+
+ public boolean getUpd() {
+ return this.upd;
+ }
+ }
+
+ private final Map<BGPTableType, SyncVariables> syncStorage = Maps.newHashMap();
+
+ private final BGPSessionListener listener;
+
+ public BGPSynchronization(final BGPSessionListener listener) {
+ this.listener = listener;
+ }
+
+ /**
+ * Fills in syncStorage map with BGPTableTypes received in speakers Open Message.
+ *
+ * @param types BGPTableTypes from remote Open message
+ */
+ public void addTableTypes(final Set<BGPTableType> types) {
+ for (final BGPTableType type : types) {
+ this.syncStorage.put(type, new SyncVariables());
+ }
+ }
+
+ /**
+ * For each received Update message, the upd sync variable needs to be updated to true, for particular AFI/SAFI
+ * combination. Currently we only assume Unicast SAFI. From the Update message we have to extract the AFI. Each
+ * Update message can contain BGP Object with one type of AFI. If the object is BGP Link, BGP Node or BGPPrefix<?>
+ * the AFI is Linkstate. In case of BGPRoute, the AFI depends on the IP Address of the prefix.
+ *
+ * @param msg received Update message
+ */
+ public void updReceived(final BGPUpdateMessage msg) {
+ BGPTableType type = null;
+ if (!msg.getAddedObjects().isEmpty()) {
+ final BGPObject obj = msg.getAddedObjects().iterator().next();
+ if (obj instanceof BGPRoute<?>) {
+ if (((BGPRoute<?>) obj) instanceof BGPIPv4RouteImpl) {
+ type = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+ } else if (((BGPRoute<?>) obj) instanceof BGPIPv6RouteImpl) {
+ type = new BGPTableType(BGPAddressFamily.IPv6, BGPSubsequentAddressFamily.Unicast);
+ }
+ } else if (obj instanceof BGPLink || obj instanceof BGPNode || obj instanceof BGPPrefix<?>) {
+ type = new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Linkstate);
+ }
+ }
+ final SyncVariables s = this.syncStorage.get(type);
+ if (s == null) {
+ logger.warn("BGPTableType was not present in open message : {}", type);
+ return;
+ }
+ s.setUpd(true);
+ }
+
+ /**
+ * This method is called, when the second KA message is received. It checks each AFI/SAFI sync variables. If they
+ * are all false, which means, that there was at least one update message followed by one KA, the EOR is sent to
+ * session.
+ */
+ public void kaReceived() {
+ for (final Entry<BGPTableType, SyncVariables> entry : this.syncStorage.entrySet()) {
+ final SyncVariables s = entry.getValue();
+ if (!s.getEor()) {
+ if (!s.getUpd()) {
+ s.setEorTrue();
+ final BGPUpdateSynchronized up = generateEOR(entry.getKey());
+ logger.debug("Sending synchronization message: {}", up);
+ this.listener.onMessage(up);
+ }
+ s.setUpd(false);
+ }
+ }
+ }
+
+ private BGPUpdateSynchronized generateEOR(final BGPTableType type) {
+ return new BGPUpdateSynchronizedImpl(type);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+
+
+/**
+ *
+ */
+public class BGPUpdateSynchronizedImpl implements BGPUpdateSynchronized {
+
+ private static final long serialVersionUID = -3574952849467738325L;
+
+ private final BGPTableType tt;
+
+ public BGPUpdateSynchronizedImpl(final BGPTableType tt) {
+ this.tt = tt;
+ }
+
+ @Override
+ public BGPTableType getTableType() {
+ return this.tt;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.NamedObject;
+import com.google.common.base.Preconditions;
+
+/**
+ * A single RIB table entry, which holds multiple versions of the entry's state and elects the authoritative based on
+ * ordering specified by the supplied comparator.
+ *
+ * @param <ID> Identifier type
+ * @param <STATE> State type
+ */
+@ThreadSafe
+final class RIBEntry<ID extends Identifier, STATE extends AbstractBGPObjectState<?>> implements NamedObject<ID> {
+ /*
+ * TODO: we could dramatically optimize performance by using the comparator
+ * to retain the candidate states ordered -- thus selection would occur
+ * automatically through insertion, without the need of a second walk.
+ */
+ private final Map<BGPPeer, STATE> candidates = new HashMap<>();
+ private final Comparator<STATE> comparator;
+ private STATE currentState = null;
+ private final ID name;
+
+ RIBEntry(final ID name, final Comparator<STATE> comparator) {
+ this.name = Preconditions.checkNotNull(name);
+ this.comparator = Preconditions.checkNotNull(comparator);
+ }
+
+ @Override
+ public ID getName() {
+ return this.name;
+ }
+
+ private STATE findCandidate(final STATE initial) {
+ STATE newState = initial;
+ for (final STATE s : this.candidates.values())
+ if (this.comparator.compare(newState, s) > 0)
+ newState = s;
+
+ return newState;
+ }
+
+ private void electCandidate(final Map<ID, STATE> transaction, final STATE candidate) {
+ if (this.currentState == null || !this.currentState.equals(candidate)) {
+ transaction.put(this.name, candidate);
+ this.currentState = candidate;
+ }
+ }
+
+ synchronized boolean removeState(final Map<ID, STATE> transaction, final BGPPeer peer) {
+ this.candidates.remove(peer);
+
+ final STATE candidate = findCandidate(null);
+ if (candidate != null) {
+ electCandidate(transaction, candidate);
+ return true;
+ } else
+ return false;
+ }
+
+ synchronized void setState(final Map<ID, STATE> transaction, final BGPPeer peer, final STATE state) {
+ this.candidates.put(peer, state);
+ electCandidate(transaction, findCandidate(state));
+ }
+
+ synchronized STATE getState() {
+ return this.currentState;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPLinkState;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPNodeState;
+import org.opendaylight.protocol.bgp.parser.BGPPrefix;
+import org.opendaylight.protocol.bgp.parser.BGPPrefixState;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPRouteState;
+import org.opendaylight.protocol.bgp.rib.RIB;
+import org.opendaylight.protocol.bgp.rib.RIBChangedEvent;
+import org.opendaylight.protocol.bgp.rib.RIBEvent;
+import org.opendaylight.protocol.bgp.rib.RIBEventListener;
+
+import org.opendaylight.protocol.concepts.InitialListenerEvents;
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+@ThreadSafe
+public final class RIBImpl implements RIB {
+ private final RIBTable<LinkIdentifier, BGPLinkState> links = new RIBTable<>();
+ private final RIBTable<NodeIdentifier, BGPNodeState> nodes = new RIBTable<>();
+ private final RIBTable<PrefixIdentifier<?>, BGPPrefixState> prefixes = new RIBTable<>();
+ private final RIBTable<Prefix<?>, BGPRouteState<?>> routes = new RIBTable<>();
+ private final EventBus bus;
+ private final String name;
+
+ public RIBImpl(final String name) {
+ this.name = Preconditions.checkNotNull(name);
+ bus = new EventBus(name);
+ }
+
+ synchronized void updateTables(final BGPPeer peer, final Set<BGPObject> addedObjects, final Set<?> removedObjects) {
+ final Map<LinkIdentifier, BGPLinkState> l = new HashMap<>();
+ final Map<NodeIdentifier, BGPNodeState> n = new HashMap<>();
+ final Map<PrefixIdentifier<?>, BGPPrefixState> p = new HashMap<>();
+ final Map<Prefix<?>, BGPRouteState<?>> r = new HashMap<>();
+
+ for (final Object id : removedObjects)
+ if (id instanceof Prefix<?>)
+ routes.remove(r, peer, (Prefix<?>)id);
+ else if (id instanceof LinkIdentifier)
+ links.remove(l, peer, (LinkIdentifier)id);
+ else if (id instanceof NodeIdentifier)
+ nodes.remove(n, peer, (NodeIdentifier) id);
+ else if (id instanceof PrefixIdentifier<?>)
+ prefixes.remove(p, peer, (PrefixIdentifier<?>) id);
+ else
+ throw new IllegalArgumentException("Unsupported identifier " + id.getClass());
+
+ for (final BGPObject o : addedObjects)
+ if (o instanceof BGPLink) {
+ final BGPLink link = (BGPLink)o;
+ links.add(l, peer, link.getLinkIdentifier(), link.currentState());
+ } else if (o instanceof BGPNode) {
+ final BGPNode node = (BGPNode)o;
+ nodes.add(n, peer, node.getNodeIdentifier(), node.currentState());
+ } else if (o instanceof BGPPrefix<?>) {
+ final BGPPrefix<?> prefix = (BGPPrefix<?>)o;
+ prefixes.add(p, peer, prefix.getPrefixIdentifier(), prefix.currentState());
+ } else if (o instanceof BGPRoute<?> ) {
+ final BGPRoute<?> route = (BGPRoute<?>)o;
+ routes.add(r, peer, route.getName(), route.currentState());
+ } else
+ throw new IllegalArgumentException("Unsupported identifier " + o.getClass());
+
+ if (!l.isEmpty() || !n.isEmpty() || !p.isEmpty() || !r.isEmpty())
+ bus.post(new RIBChangedEvent(l, n, p, r));
+ }
+
+ synchronized void clearTable(final BGPPeer peer, final BGPTableType t) {
+ switch (t.getAddressFamily()) {
+ case IPv4:
+ case IPv6:
+ bus.post(new RIBChangedEvent(routes.clear(peer)));
+ break;
+ case LinkState:
+ bus.post(new RIBChangedEvent(links.clear(peer), nodes.clear(peer), prefixes.clear(peer)));
+ break;
+ }
+ }
+
+ @Override
+ synchronized public InitialListenerEvents<RIBEventListener, RIBEvent> registerListener(final RIBEventListener listener) {
+ final List<RIBEvent> events = new ArrayList<>();
+
+ events.add(new RIBChangedEvent(routes.currentState()));
+ events.add(new RIBChangedEvent(links.currentState(), nodes.currentState(), prefixes.currentState()));
+
+ final Object wrapper = new Object() {
+ @Subscribe
+ public void notifyListener(final RIBChangedEvent event) {
+ listener.onRIBEvent(event);
+ }
+ };
+ bus.register(wrapper);
+
+ return new InitialListenerEvents<RIBEventListener, RIBEvent>(new ListenerRegistration<RIBEventListener>() {
+ @Override
+ public void close() {
+ bus.unregister(wrapper);
+ }
+
+ @Override
+ public RIBEventListener getListener() {
+ return listener;
+ }
+ }, events);
+ }
+
+ @Override
+ public final String toString(){
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("name", name);
+ return toStringHelper;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.bgp.parser.AbstractBGPObjectState;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+@ThreadSafe
+class RIBTable<ID extends Identifier, STATE extends AbstractBGPObjectState<?>> {
+ private final Comparator<STATE> comparator = new BGPObjectComparator<>();
+ private final Map<ID, RIBEntry<ID, STATE>> entries = new HashMap<>();
+
+ RIBTable() {
+ }
+
+ synchronized void add(final Map<ID, STATE> transaction, final BGPPeer peer, final ID id, final STATE state) {
+ RIBEntry<ID, STATE> e = this.entries.get(id);
+ if (e == null) {
+ e = new RIBEntry<ID, STATE>(id, this.comparator);
+ this.entries.put(id, e);
+ }
+
+ e.setState(transaction, peer, state);
+ }
+
+ synchronized Map<ID, STATE> clear(final BGPPeer peer) {
+ final Map<ID, STATE> transaction = new HashMap<>();
+
+ final Iterator<Map.Entry<ID, RIBEntry<ID, STATE>>> i = this.entries.entrySet().iterator();
+ while (i.hasNext()) {
+ final Map.Entry<ID, RIBEntry<ID, STATE>> e = i.next();
+
+ if (e.getValue().removeState(transaction, peer))
+ i.remove();
+ }
+
+ return transaction;
+ }
+
+ synchronized void remove(final Map<ID, STATE> transaction, final BGPPeer peer, final ID id) {
+ final RIBEntry<ID, STATE> e = this.entries.get(id);
+ if (e != null && e.removeState(transaction, peer))
+ this.entries.remove(id);
+ }
+
+ synchronized Map<ID, STATE> currentState() {
+ final Map<ID, STATE> ret = new HashMap<>();
+
+ for (final Entry<ID, RIBEntry<ID, STATE>> e : this.entries.entrySet())
+ ret.put(e.getKey(), e.getValue().getState());
+
+ return ret;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+
+/**
+ * BGP specific connection attributes.
+ */
+public interface BGPConnection extends ProtocolConnection {
+
+ @Override
+ public BGPSessionListener getListener();
+
+ @Override
+ public BGPSessionPreferences getProposal();
+
+ @Override
+ public BGPSessionProposalChecker getProposalChecker();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.ProtocolConnectionFactory;
+
+/**
+ * BGP implementation of {@link ProtocolConnectionFactory}
+ */
+public interface BGPConnectionFactory extends ProtocolConnectionFactory {
+ @Override
+ BGPConnection createProtocolConnection(final InetSocketAddress address);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import java.io.IOException;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+
+
+/**
+ * Dispatcher class for creating BGP clients.
+ */
+public interface BGPDispatcher {
+
+ /**
+ * Creates BGP client.
+ *
+ * @param connection attributes required for connection
+ * @param parser BGP message parser
+ * @return client session
+ * @throws IOException
+ */
+ BGPSession createClient(BGPConnection connection, BGPMessageParser parser) throws IOException;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import java.util.List;
+
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * DTO for BGP Session preferences, that contains BGP Open message.
+ */
+public final class BGPSessionPreferences implements SessionPreferences {
+
+ private final ASNumber as;
+
+ private final int hold;
+
+ private final IPv4Address bgpId;
+
+ private final List<BGPParameter> params;
+
+ /**
+ * Creates a new DTO for Open message.
+ *
+ * @param prefs BGP Open message
+ */
+ public BGPSessionPreferences(final ASNumber as, final int hold, final IPv4Address bgpId, final List<BGPParameter> params) {
+ this.as = as;
+ this.hold = hold;
+ this.bgpId = bgpId;
+ this.params = params;
+ }
+
+ /**
+ * Returns my AS number.
+ *
+ * @return AS number
+ */
+ public ASNumber getMyAs() {
+ return this.as;
+ }
+
+ /**
+ * Returns initial value of HoldTimer.
+ *
+ * @return initial value of HoldTimer
+ */
+ public int getHoldTime() {
+ return this.hold;
+ }
+
+ /**
+ * Returns my BGP Identifier.
+ *
+ * @return BGP identifier
+ */
+ public IPv4Address getBgpId() {
+ return this.bgpId;
+ }
+
+ public List<BGPParameter> getParams() {
+ return this.params;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import org.opendaylight.protocol.framework.SessionProposal;
+
+/**
+ * Interface that provides the initial acceptable session characteristics with which the session should be started.
+ */
+public abstract class BGPSessionProposal implements SessionProposal {
+ /**
+ * Returns BGPSessionPreferences for this IP address.
+ *
+ * @param address serves as constraint, the implementation can also take time into consideration
+ * @return BGPSessionPreferences with acceptable session characteristics
+ */
+ @Override
+ public abstract BGPSessionPreferences getProposal();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.framework.SessionPreferencesChecker;
+
+/**
+ * Session characteristics initial proposal checker. BGP does not have any negotiation. If the characteristics are not
+ * acceptable, the session ends.
+ */
+public abstract class BGPSessionProposalChecker implements SessionPreferencesChecker {
+
+ @Override
+ public abstract Boolean checkSessionCharacteristics(final SessionPreferences openObj) throws BGPDocumentedException;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.AS4BytesCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.CapabilityParameter;
+import org.opendaylight.protocol.bgp.parser.parameter.GracefulCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.rib.impl.BGPUpdateSynchronizedImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.collect.Maps;
+
+public class ApiTest {
+
+ @Test
+ public void testDocumentedException() {
+ final DocumentedException de = new BGPDocumentedException("Some message", BGPError.BAD_BGP_ID);
+ assertEquals("Some message", de.getMessage());
+ assertEquals(BGPError.BAD_BGP_ID, ((BGPDocumentedException) de).getError());
+ assertNull(((BGPDocumentedException) de).getData());
+ }
+
+ @Test
+ public void testBGPKeepAliveMessage() {
+ final BGPMessage msg = new BGPKeepAliveMessage();
+ assertTrue(msg instanceof BGPKeepAliveMessage);
+ }
+
+ @Test
+ public void testBGPNotificationMessage() {
+ final BGPMessage msg = new BGPNotificationMessage(BGPError.AS_PATH_MALFORMED);
+ assertTrue(msg instanceof BGPNotificationMessage);
+ assertEquals(BGPError.AS_PATH_MALFORMED, ((BGPNotificationMessage) msg).getError());
+ assertNull(((BGPNotificationMessage) msg).getData());
+ }
+
+ @Test
+ public void testBGPOpenMessage() {
+ final BGPMessage msg = new BGPOpenMessage(new ASNumber(58), (short) 5, null, null);
+ assertNull(((BGPOpenMessage) msg).getOptParams());
+ }
+
+ @Test
+ public void testBGPParameter() {
+
+ final BGPTableType t = new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Unicast);
+ final BGPTableType t1 = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+
+ final BGPParameter tlv1 = new MultiprotocolCapability(t);
+
+ final BGPParameter tlv2 = new MultiprotocolCapability(t1);
+
+ final Map<BGPTableType, Boolean> tt = Maps.newHashMap();
+ tt.put(t, true);
+ tt.put(t1, false);
+
+ final BGPParameter tlv3 = new GracefulCapability(false, 0, tt);
+
+ final BGPParameter tlv4 = new AS4BytesCapability(new ASNumber(40));
+
+ assertFalse(((GracefulCapability) tlv3).isRestartFlag());
+
+ assertEquals(0, ((GracefulCapability) tlv3).getRestartTimerValue());
+
+ assertEquals(tlv1.getType(), tlv2.getType());
+
+ assertFalse(tlv1.equals(tlv2));
+
+ assertNotSame(tlv1.hashCode(), tlv3.hashCode());
+
+ assertNotSame(tlv2.toString(), tlv3.toString());
+
+ assertEquals(((GracefulCapability) tlv3).getTableTypes(), tt);
+
+ assertNotSame(((CapabilityParameter) tlv1).getCode(), ((CapabilityParameter) tlv3).getCode());
+
+ assertEquals(((MultiprotocolCapability) tlv1).getSafi(), ((MultiprotocolCapability) tlv2).getSafi());
+
+ assertNotSame(((MultiprotocolCapability) tlv1).getAfi(), ((MultiprotocolCapability) tlv2).getAfi());
+
+ assertEquals(40, ((AS4BytesCapability) tlv4).getASNumber().getAsn());
+
+ assertEquals(new AS4BytesCapability(new ASNumber(40)).toString(), tlv4.toString());
+ }
+
+ @Test
+ public void testToString() {
+ final BGPMessage o = new BGPOpenMessage(new ASNumber(58), (short) 5, null, null);
+ final BGPMessage n = new BGPNotificationMessage(BGPError.ATTR_FLAGS_MISSING);
+ assertNotSame(o.toString(), n.toString());
+ }
+
+ @Test
+ public void testBGPSessionPreferences() {
+ final SessionPreferences sp = new BGPSessionPreferences(new ASNumber(58), (short) 5, null, null);
+ assertNull(((BGPSessionPreferences) sp).getBgpId());
+ assertEquals((short) 5, ((BGPSessionPreferences) sp).getHoldTime());
+ assertEquals(58, ((BGPSessionPreferences) sp).getMyAs().getAsn());
+ }
+
+ @Test
+ public void testBGPUpdateSynchronized() {
+ final BGPTableType tt = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Linkstate);
+ final BGPUpdateSynchronized update = new BGPUpdateSynchronizedImpl(tt);
+ assertEquals(tt, update.getTableType());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.rib.impl.BGPImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPImpl.BGPListenerRegistration;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposal;
+
+
+public class BGPImplTest {
+
+ @Mock
+ private BGPDispatcher disp;
+
+ @Mock
+ private BGPSessionProposal prop;
+
+ @Mock
+ private BGPMessageParser parser;
+
+ private BGPImpl bgp;
+
+ @Before
+ public void setUp() throws IOException {
+ MockitoAnnotations.initMocks(this);
+ doReturn("").when(this.parser).toString();
+ doReturn(null).when(this.disp).createClient(any(BGPConnection.class), any(BGPMessageParser.class));
+ }
+
+ @Test
+ public void testBgpImpl() throws IOException {
+ doReturn(new BGPSessionPreferences(null, 0, null, Collections.<BGPParameter> emptyList())).when(this.prop).getProposal();
+ this.bgp = new BGPImpl(this.disp, this.parser, null, this.prop, null);
+ final BGPListenerRegistration reg = (BGPListenerRegistration) this.bgp.registerUpdateListener(new SimpleSessionListener());
+ assertEquals(SimpleSessionListener.class, reg.getListener().getClass());
+ }
+
+ @After
+ public void tearDown() {
+ this.bgp.close();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class FSMTest {
+
+ private SimpleSessionListener clientListener;
+
+ private final SpeakerSessionListener speakerListener = new SpeakerSessionListener();
+
+ private SpeakerSessionMock speaker;
+
+ @Before
+ public void setUp() {
+ this.clientListener = new SimpleSessionListener();
+ this.speaker = new SpeakerSessionMock(this.speakerListener, this.clientListener);
+ this.clientListener.addSession(this.speaker);
+ }
+
+ @Test
+ public void testAccSessionChar() throws InterruptedException {
+ this.speaker.startSession();
+ assertEquals(1, this.clientListener.getListMsg().size());
+ assertTrue(this.clientListener.getListMsg().get(0) instanceof BGPOpenMessage);
+ final List<BGPParameter> tlvs = Lists.newArrayList();
+ tlvs.add(new MultiprotocolCapability(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast)));
+ this.clientListener.sendMessage(new BGPOpenMessage(new ASNumber(30), (short) 3, null, tlvs));
+ assertEquals(2, this.clientListener.getListMsg().size());
+ assertTrue(this.clientListener.getListMsg().get(1) instanceof BGPKeepAliveMessage);
+ this.clientListener.sendMessage(new BGPKeepAliveMessage());
+ synchronized (this.speakerListener) {
+ while (!this.speakerListener.up)
+ try {
+ this.speakerListener.wait();
+ fail("Exception should have occured.");
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ assertTrue(this.speakerListener.up);
+ assertEquals(this.speakerListener.types,
+ Sets.newHashSet(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast)));
+ Thread.sleep(1 * 1000);
+ assertEquals(3, this.clientListener.getListMsg().size());
+ assertTrue(this.clientListener.getListMsg().get(2) instanceof BGPKeepAliveMessage); // test of keepalive timer
+ this.clientListener.sendMessage(new BGPOpenMessage(new ASNumber(30), (short) 3, null, null));
+ assertEquals(4, this.clientListener.getListMsg().size());
+ assertTrue(this.clientListener.getListMsg().get(3) instanceof BGPNotificationMessage);
+ final BGPMessage m = this.clientListener.getListMsg().get(3);
+ assertEquals(BGPError.FSM_ERROR, ((BGPNotificationMessage) m).getError());
+ }
+
+ @Test
+ public void testNotAccChars() throws InterruptedException {
+ this.speaker.startSession();
+ assertEquals(1, this.clientListener.getListMsg().size());
+ assertTrue(this.clientListener.getListMsg().get(0) instanceof BGPOpenMessage);
+ this.clientListener.sendMessage(new BGPOpenMessage(new ASNumber(30), (short) 1, null, null));
+ assertEquals(2, this.clientListener.getListMsg().size());
+ assertTrue(this.clientListener.getListMsg().get(1) instanceof BGPKeepAliveMessage);
+ assertFalse(this.speakerListener.up);
+ Thread.sleep(BGPSessionImpl.HOLD_TIMER_VALUE * 1000);
+ Thread.sleep(100);
+ final BGPMessage m = this.clientListener.getListMsg().get(this.clientListener.getListMsg().size() - 1);
+ assertEquals(BGPError.HOLD_TIMER_EXPIRED, ((BGPNotificationMessage) m).getError());
+ }
+
+ @Test
+ @Ignore
+ // long duration
+ public void testNoOpen() throws InterruptedException {
+ this.speaker.startSession();
+ assertEquals(1, this.clientListener.getListMsg().size());
+ assertTrue(this.clientListener.getListMsg().get(0) instanceof BGPOpenMessage);
+ Thread.sleep(BGPSessionImpl.HOLD_TIMER_VALUE * 1000);
+ Thread.sleep(100);
+ final BGPMessage m = this.clientListener.getListMsg().get(this.clientListener.getListMsg().size() - 1);
+ assertEquals(BGPError.HOLD_TIMER_EXPIRED, ((BGPNotificationMessage) m).getError());
+ }
+
+ @Test
+ public void sendNotification() {
+ this.speaker.startSession();
+ this.clientListener.sendMessage(new BGPOpenMessage(new ASNumber(30), (short) 3, null, null));
+ this.clientListener.sendMessage(new BGPKeepAliveMessage());
+ synchronized (this.speakerListener) {
+ while (!this.speakerListener.up)
+ try {
+ this.speakerListener.wait();
+ fail("Exception should have occured.");
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ assertTrue(this.speakerListener.up);
+ this.clientListener.sendMessage(new BGPNotificationMessage(BGPError.CEASE));
+ assertFalse(this.speakerListener.up);
+ }
+
+ @Test
+ public void complementaryTests() {
+ assertEquals(4096, this.speaker.maximumMessageSize());
+
+ assertNotNull(this.speaker.getStream());
+ }
+
+ @After
+ public void tearDown() {
+ this.speaker.close();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.rib.impl.BGPInputStream;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+
+public class InputStreamTest {
+
+ @Mock
+ PipedInputStream pis;
+
+ @Mock
+ BGPMessageFactory mf;
+
+ @Mock
+ BGPMessageHeader h;
+
+ BGPInputStream is;
+
+ @Before
+ public void setUp() throws IOException {
+ MockitoAnnotations.initMocks(this);
+ this.is = (BGPInputStream) BGPInputStream.FACTORY.getProtocolInputStream(this.pis, this.mf);
+ }
+
+ @Test
+ public void testHeaderNotAvailable() throws IOException {
+ doReturn(BGPMessageHeader.COMMON_HEADER_LENGTH - 4).when(this.pis).available();
+ doReturn(-1).when(this.pis).read((byte[]) any());
+ assertFalse(this.is.isMessageAvailable());
+ assertFalse(this.is.header.isParsed());
+ }
+
+ @Test
+ public void testHeaderAvailable() throws IOException {
+ doReturn(BGPMessageHeader.COMMON_HEADER_LENGTH).when(this.pis).available();
+ doReturn(5).when(this.pis).read((byte[]) any());
+ assertTrue(this.is.isMessageAvailable());
+ assertTrue(this.is.header.isParsed());
+ }
+
+ @Test
+ public void testGetMessage() throws IOException, DeserializerException, DocumentedException {
+ doReturn(BGPMessageHeader.COMMON_HEADER_LENGTH).when(this.pis).available();
+ doReturn(5).when(this.pis).read((byte[]) any());
+ doReturn("").when(this.h).toString();
+ this.is.header = this.h;
+ doNothing().when(this.h).setParsed();
+ doReturn(true).when(this.h).isParsed();
+ doReturn(100).when(this.h).getLength();
+ doReturn(mock(BGPMessage.class)).when(this.mf).parse((byte[]) any(), any(BGPMessageHeader.class));
+ assertTrue(this.is.getMessage() instanceof BGPMessage);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.io.IOException;
+
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+
+public class MockDispatcher implements SessionParent {
+
+ @Override
+ public void onSessionClosed(final ProtocolSession session) {
+
+ }
+
+ @Override
+ public void checkOutputBuffer(final ProtocolSession session) {
+
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.GracefulCapability;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+import org.opendaylight.protocol.util.ByteArray;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class ParserTest {
+
+ public static final byte[] openBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4,
+ (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
+
+ public static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 };
+
+ public static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 };
+
+ final BGPMessageHeader header = new BGPMessageHeader();
+
+ final BGPMessageParser factory = new BGPMessageFactory();
+
+ @Test
+ public void testHeaderErrors() {
+ final byte[] wrong = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0x00 };
+ try {
+ this.header.fromBytes(wrong);
+ fail("Exception should have occcured.");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= "
+ + BGPMessageHeader.COMMON_HEADER_LENGTH + ".", e.getMessage());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testBadMsgType() throws DeserializerException {
+ byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+ (byte) 0x13, (byte) 0x08 };
+ final BGPMessageHeader h = this.header.fromBytes(bytes);
+ bytes = ByteArray.cutBytes(bytes, 19);
+ try {
+ this.factory.parse(bytes, h);
+ fail("Exception should have occured.");
+ } catch (final DocumentedException e) {
+ assertEquals("Unhandled message type " + h.getType(), e.getMessage());
+ assertEquals(BGPError.BAD_MSG_TYPE, ((BGPDocumentedException) e).getError());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testKeepAliveMsg() throws DeserializerException, DocumentedException {
+ final BGPMessage keepAlive = new BGPKeepAliveMessage();
+ byte[] bytes = this.factory.put(keepAlive);
+ assertArrayEquals(keepAliveBMsg, bytes);
+
+ final BGPMessageHeader h = this.header.fromBytes(keepAliveBMsg);
+ bytes = ByteArray.cutBytes(bytes, 19);
+ final BGPMessage m = this.factory.parse(bytes, h);
+
+ assertTrue(m instanceof BGPKeepAliveMessage);
+ }
+
+ @Test
+ public void testBadKeepAliveMsg() throws DeserializerException {
+ byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+ (byte) 0x14, (byte) 0x04, (byte) 0x05 };
+
+ final BGPMessageHeader h = this.header.fromBytes(bytes);
+ bytes = ByteArray.cutBytes(bytes, 19);
+ try {
+ this.factory.parse(bytes, h);
+ fail("Exception should have occured.");
+ } catch (final DocumentedException e) {
+ assertThat(e.getMessage(), containsString("Message length field not within valid range."));
+ assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testOpenMessage() throws UnknownHostException, DeserializerException, DocumentedException {
+ final BGPMessage open = new BGPOpenMessage(new ASNumber(100), (short) 180, new IPv4Address(InetAddress.getByName("20.20.20.20")), null);
+ byte[] bytes = this.factory.put(open);
+ assertArrayEquals(openBMsg, bytes);
+
+ final BGPMessageHeader h = this.header.fromBytes(openBMsg);
+ bytes = ByteArray.cutBytes(bytes, 19);
+ final BGPMessage m = this.factory.parse(bytes, h);
+
+ assertTrue(m instanceof BGPOpenMessage);
+ assertEquals(new ASNumber(100), ((BGPOpenMessage) m).getMyAS());
+ assertEquals((short) 180, ((BGPOpenMessage) m).getHoldTime());
+ assertEquals(new IPv4Address(InetAddress.getByName("20.20.20.20")), ((BGPOpenMessage) m).getBgpId());
+ assertTrue(((BGPOpenMessage) m).getOptParams().isEmpty());
+ }
+
+ @Test
+ public void testBadHoldTimeError() throws DeserializerException {
+ byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+ (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14, (byte) 0x14,
+ (byte) 0x14, (byte) 0x14, (byte) 0x00 };
+
+ final BGPMessageHeader h = this.header.fromBytes(bMsg);
+ bMsg = ByteArray.cutBytes(bMsg, 19);
+ try {
+ this.factory.parse(bMsg, h);
+ fail("Exception should have occured.");
+ } catch (final DocumentedException e) {
+ assertEquals("Hold time value not acceptable.", e.getMessage());
+ assertEquals(BGPError.HOLD_TIME_NOT_ACC, ((BGPDocumentedException) e).getError());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testBadMsgLength() throws DeserializerException {
+ byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+ (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff };
+
+ final BGPMessageHeader h = this.header.fromBytes(bMsg);
+ bMsg = ByteArray.cutBytes(bMsg, 19);
+ try {
+ this.factory.parse(bMsg, h);
+ fail("Exception should have occured.");
+ } catch (final DocumentedException e) {
+ assertEquals("Open message too small.", e.getMessage());
+ assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
+ }
+ }
+
+ @Test
+ public void testBadVersion() throws DeserializerException {
+ byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+ (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14, (byte) 0x14,
+ (byte) 0x14, (byte) 0x14, (byte) 0x00 };
+
+ final BGPMessageHeader h = this.header.fromBytes(bMsg);
+ bMsg = ByteArray.cutBytes(bMsg, 19);
+ try {
+ this.factory.parse(bMsg, h);
+ fail("Exception should have occured.");
+ } catch (final DocumentedException e) {
+ assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
+ assertEquals(BGPError.VERSION_NOT_SUPPORTED, ((BGPDocumentedException) e).getError());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testNotificationMsg() throws DeserializerException, DocumentedException {
+ BGPMessage notMsg = new BGPNotificationMessage(BGPError.OPT_PARAM_NOT_SUPPORTED, new byte[] { 4, 9 });
+ byte[] bytes = this.factory.put(notMsg);
+ assertArrayEquals(notificationBMsg, bytes);
+
+ BGPMessageHeader h = this.header.fromBytes(notificationBMsg);
+ bytes = ByteArray.cutBytes(bytes, 19);
+ BGPMessage m = this.factory.parse(bytes, h);
+
+ assertTrue(m instanceof BGPNotificationMessage);
+ assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, ((BGPNotificationMessage) m).getError());
+ assertArrayEquals(new byte[] { 4, 9 }, ((BGPNotificationMessage) m).getData());
+
+ notMsg = new BGPNotificationMessage(BGPError.CONNECTION_NOT_SYNC);
+ bytes = this.factory.put(notMsg);
+
+ h = this.header.fromBytes(bytes);
+ bytes = ByteArray.cutBytes(bytes, 19);
+ m = this.factory.parse(bytes, h);
+
+ assertTrue(m instanceof BGPNotificationMessage);
+ assertEquals(BGPError.CONNECTION_NOT_SYNC, ((BGPNotificationMessage) m).getError());
+ assertNull(((BGPNotificationMessage) m).getData());
+ }
+
+ @Test
+ public void testWrongLength() throws DeserializerException {
+ byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+ (byte) 0x14, (byte) 0x03, (byte) 0x02 };
+
+ final BGPMessageHeader h = this.header.fromBytes(bMsg);
+ bMsg = ByteArray.cutBytes(bMsg, 19);
+ try {
+ this.factory.parse(bMsg, h);
+ fail("Exception should have occured.");
+ } catch (final DocumentedException e) {
+ assertEquals("Notification message too small.", e.getMessage());
+ assertEquals(BGPError.BAD_MSG_LENGTH, ((BGPDocumentedException) e).getError());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testUnrecognizedError() throws DeserializerException, DocumentedException {
+ byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00,
+ (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
+
+ final BGPMessageHeader h = this.header.fromBytes(bMsg);
+ bMsg = ByteArray.cutBytes(bMsg, 19);
+ try {
+ this.factory.parse(bMsg, h);
+ fail("Exception should have occured.");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testTLVParser() throws UnknownHostException {
+
+ final BGPTableType t1 = new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast);
+ final BGPTableType t2 = new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Unicast);
+
+ final List<BGPParameter> tlvs = Lists.newArrayList();
+ tlvs.add(new MultiprotocolCapability(t1));
+ tlvs.add(new MultiprotocolCapability(t2));
+ final Map<BGPTableType, Boolean> tableTypes = Maps.newHashMap();
+ tableTypes.put(t1, true);
+ tableTypes.put(t2, true);
+ tlvs.add(new GracefulCapability(true, 0, tableTypes));
+ final BGPOpenMessage open = new BGPOpenMessage(new ASNumber(72), (short) 180, new IPv4Address(InetAddress.getByName("172.20.160.170")), tlvs);
+
+ // System.out.println(Arrays.toString(this.factory.put(open)));
+
+ this.factory.put(open);
+
+ // assertArrayEquals(openWithCpblt, bytes);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Listener for the client.
+ */
+public class SimpleSessionListener extends BGPSessionListener {
+
+ private final List<BGPMessage> listMsg = Lists.newArrayList();
+
+ private BGPSessionImpl session = null;
+
+ public boolean up = false;
+
+ private static final Logger logger = LoggerFactory.getLogger(SimpleSessionListener.class);
+
+ public boolean down = false;
+
+ public SimpleSessionListener() {
+ }
+
+ public void sendMessage(final BGPMessage msg) {
+ this.session.handleMessage(msg);
+ }
+
+ public List<BGPMessage> getListMsg() {
+ return this.listMsg;
+ }
+
+ public void addSession(final BGPSessionImpl l) {
+ this.session = l;
+ }
+
+ @Override
+ public void onMessage(final BGPMessage message) {
+ this.listMsg.add(message);
+ logger.debug("Message received:" + message);
+ }
+
+ @Override
+ public void onSessionUp(final Set<BGPTableType> remote) {
+ logger.debug("Session Up");
+ this.up = true;
+ this.notifyAll();
+ }
+
+ @Override
+ public void onSessionDown(final BGPSession session, final Exception e) {
+ logger.debug("Session Down", e);
+ this.down = true;
+ }
+
+ @Override
+ public void onSessionTerminated(final BGPError cause) {
+ logger.debug("Session terminated. Cause : " + cause.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Listener for the BGP Speaker.
+ */
+public class SpeakerSessionListener extends BGPSessionListener {
+
+ public List<BGPMessage> messages = Lists.newArrayList();
+
+ public boolean up = false;
+
+ public Set<BGPTableType> types;
+
+ private static final Logger logger = LoggerFactory.getLogger(SpeakerSessionListener.class);
+
+ public SpeakerSessionListener() {
+ }
+
+ @Override
+ public void onMessage(final BGPMessage message) {
+ logger.debug("Received message: " + message.getClass() + " " + message);
+ this.messages.add(message);
+ }
+
+ @Override
+ public synchronized void onSessionUp(final Set<BGPTableType> remote) {
+ logger.debug("Session up.");
+ this.up = true;
+ this.types = remote;
+ this.notifyAll();
+ }
+
+ @Override
+ public void onSessionDown(final BGPSession session, final Exception e) {
+ logger.debug("Session down.");
+ this.up = false;
+ }
+
+ @Override
+ public void onSessionTerminated(final BGPError cause) {
+ logger.debug("Session terminated. Cause : " + cause.toString());
+ this.up = false;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import java.util.Timer;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.rib.impl.BGPConnectionImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalCheckerImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * Mock of the BGP speakers session.
+ */
+public class SpeakerSessionMock extends BGPSessionImpl {
+
+ private final BGPSessionListener client;
+
+ SpeakerSessionMock(final BGPSessionListener listener, final BGPSessionListener client) {
+ super(new MockDispatcher(), new Timer(), new BGPConnectionImpl(null, listener, new BGPSessionPreferences(new ASNumber(30), (short) 15, null, null), new BGPSessionProposalCheckerImpl()), 3, null);
+ this.client = client;
+ }
+
+ @Override
+ public void sendMessage(final BGPMessage msg) {
+ this.lastMessageSentAt = System.nanoTime();
+ this.client.onMessage(msg);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.rib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.Collections;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
+import org.opendaylight.protocol.bgp.parser.impl.BGPUpdateMessageImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSynchronization;
+import org.opendaylight.protocol.bgp.rib.impl.BGPUpdateSynchronizedImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv6;
+import com.google.common.collect.Sets;
+
+public class SynchronizationTest {
+
+ private BGPSynchronization bs;
+
+ private SimpleSessionListener listener;
+
+ private BGPUpdateMessage ipv4m;
+
+ private BGPUpdateMessage ipv6m;
+
+ private BGPUpdateMessage lsm;
+
+ @Before
+ public void setUp() {
+ this.listener = new SimpleSessionListener();
+ final BGPIPv4RouteImpl i4 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("1.1.1.1/32"), new BaseBGPObjectState(null, null), null);
+ this.ipv4m = new BGPUpdateMessageImpl(Sets.<BGPObject> newHashSet(i4), Collections.EMPTY_SET);
+ final BGPIPv6RouteImpl i6 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("::1/32"), new BaseBGPObjectState(null, null), null);
+ this.ipv6m = new BGPUpdateMessageImpl(Sets.<BGPObject> newHashSet(i6), Collections.EMPTY_SET);
+ this.lsm = new BGPUpdateMessageImpl(Sets.<BGPObject> newHashSet(mock(BGPLink.class)), Collections.EMPTY_SET);
+ this.bs = new BGPSynchronization(this.listener);
+ this.bs.addTableTypes(Sets.newHashSet(new BGPTableType(BGPAddressFamily.IPv4, BGPSubsequentAddressFamily.Unicast),
+ new BGPTableType(BGPAddressFamily.LinkState, BGPSubsequentAddressFamily.Linkstate)));
+ }
+
+ @Test
+ public void testSynchronize() {
+ // simulate sync
+ this.bs.updReceived(this.ipv6m);
+
+ this.bs.updReceived(this.ipv4m);
+ this.bs.updReceived(this.lsm);
+ this.bs.kaReceived(); // nothing yet
+ this.bs.updReceived(this.ipv4m);
+ this.bs.kaReceived(); // linkstate
+ assertEquals(1, this.listener.getListMsg().size());
+ this.bs.kaReceived(); // ipv4 sync
+ assertEquals(2, this.listener.getListMsg().size());
+ assertEquals(BGPAddressFamily.IPv4,
+ ((BGPUpdateSynchronizedImpl) this.listener.getListMsg().get(1)).getTableType().getAddressFamily());
+ }
+}
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-update-mock</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-rib-mock</artifactId>
+ <description>BGP Update Mock Implementation</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-rib-impl</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>util</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-impl</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.rib.mock,
+ </Export-Package>
+ <Import-Package>
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.framework,
+ org.opendaylight.protocol.bgp.linkstate,
+ com.google.common.*,
+ javax.annotation,
+ javax.management,
+ org.apache.commons.codec,
+ org.apache.commons.codec.binary,
+ org.apache.commons.lang,
+ org.opendaylight.protocol.bgp.concepts,
+ org.opendaylight.protocol.bgp.parser,
+ org.opendaylight.protocol.bgp.parser.impl,
+ org.opendaylight.protocol.bgp.parser.message,
+ org.opendaylight.protocol.bgp.parser.parameter,
+ org.opendaylight.protocol.bgp.rib.impl,
+ org.opendaylight.protocol.util,
+ org.slf4j,
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-UPDATE-MOCK Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.mock;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPMessageHeader;
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
+import org.opendaylight.protocol.bgp.rib.impl.BGP;
+import org.opendaylight.protocol.util.ByteArray;
+
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import com.google.common.collect.Lists;
+import com.google.common.eventbus.EventBus;
+
+/**
+ *
+ * Mock implementation of {@link BGP}.
+ *
+ */
+@ThreadSafe
+public final class BGPMock implements BGP, Closeable {
+ static final BGPMessage connectionLostMagicMessage = new BGPNotificationMessage(BGPError.CEASE);
+
+ @GuardedBy("this")
+ private final List<byte[]> allPreviousByteMessages;
+ private final List<BGPMessage> allPreviousBGPMessages;
+ private final EventBus eventBus;
+ @GuardedBy("this")
+ private final List<EventBusRegistration> openRegistrations = Lists.newLinkedList();
+
+ public BGPMock(final EventBus eventBus, final List<byte[]> bgpMessages) {
+ this.allPreviousByteMessages = Lists.newLinkedList(bgpMessages);
+ this.eventBus = eventBus;
+ this.allPreviousBGPMessages = this.parsePrevious(this.allPreviousByteMessages);
+ }
+
+ private List<BGPMessage> parsePrevious(final List<byte[]> msgs) {
+ final List<BGPMessage> messages = Lists.newArrayList();
+ final BGPMessageParser parser = new BGPMessageFactory();
+ try {
+ for (final byte[] b : msgs) {
+ final BGPMessageHeader header = new BGPMessageHeader();
+ header.fromBytes(ByteArray.subByte(b, 0, BGPMessageHeader.COMMON_HEADER_LENGTH));
+
+ final byte[] body = ByteArray.cutBytes(b, BGPMessageHeader.COMMON_HEADER_LENGTH);
+
+ messages.add(parser.parse(body, header));
+ }
+ parser.close();
+ } catch (final IOException e) {
+ e.printStackTrace();
+ } catch (final DeserializerException e) {
+ e.printStackTrace();
+ } catch (final DocumentedException e) {
+ e.printStackTrace();
+ }
+ return messages;
+ }
+
+ /**
+ * @param listener BGPListener
+ * @return ListenerRegistration
+ */
+ @Override
+ public synchronized ListenerRegistration<BGPSessionListener> registerUpdateListener(final BGPSessionListener listener) {
+ return EventBusRegistration.createAndRegister(this.eventBus, listener, this.allPreviousBGPMessages);
+ }
+
+ public synchronized void insertConnectionLostEvent() {
+ this.insertMessage(connectionLostMagicMessage);
+ }
+
+ public synchronized void insertMessages(final List<BGPMessage> messages) {
+ for (final BGPMessage message : messages)
+ this.insertMessage(message);
+ }
+
+ private synchronized void insertMessage(final BGPMessage message) {
+ this.allPreviousBGPMessages.add(message);
+ this.eventBus.post(message);
+ }
+
+ @Override
+ public synchronized void close() {
+ // unregister all EventBusRegistration instances
+ for (final EventBusRegistration registration : this.openRegistrations) {
+ registration.close();
+ }
+ this.openRegistrations.clear();
+ }
+
+ public boolean isMessageListSame(final List<byte[]> newMessages) {
+ if (this.allPreviousBGPMessages.size() != newMessages.size())
+ return false;
+ final Iterator<byte[]> i1 = this.allPreviousByteMessages.iterator();
+ final Iterator<byte[]> i2 = this.allPreviousByteMessages.iterator();
+ for (int i = 0; i < this.allPreviousBGPMessages.size(); i++) {
+ if (!Arrays.equals(i1.next(), i2.next()))
+ return false;
+ }
+ return true;
+ }
+
+ public EventBus getEventBus() {
+ return this.eventBus;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.mock;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPParameter;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.message.BGPKeepAliveMessage;
+import org.opendaylight.protocol.bgp.parser.message.BGPOpenMessage;
+import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
+
+import org.opendaylight.protocol.concepts.ListenerRegistration;
+import com.google.common.collect.Sets;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+/**
+ * This class has @Subscribe annotated methods which receive events from {@link EventBus} . Events are produced by
+ * {@link BGPMock}, and each instance notifies exactly one {@link BGPSessionListener}.
+ */
+class EventBusRegistration implements ListenerRegistration<BGPSessionListener> {
+ private final EventBus eventBus;
+ private final BGPSessionListener listener;
+ @GuardedBy("this")
+ private boolean closed = false;
+
+ public static EventBusRegistration createAndRegister(final EventBus eventBus, final BGPSessionListener listener,
+ final List<BGPMessage> allPreviousMessages) {
+ final EventBusRegistration instance = new EventBusRegistration(eventBus, listener, allPreviousMessages);
+ eventBus.register(instance);
+ return instance;
+ }
+
+ private EventBusRegistration(final EventBus eventBus, final BGPSessionListener listener, final List<BGPMessage> allPreviousMessages) {
+ this.eventBus = eventBus;
+ this.listener = listener;
+ for (final BGPMessage message : allPreviousMessages)
+ sendMessage(listener, message);
+ }
+
+ @Subscribe
+ public void onMessage(final BGPMessage message) {
+ sendMessage(this.listener, message);
+ }
+
+ @Override
+ public synchronized void close() {
+ if (this.closed)
+ return;
+ this.eventBus.unregister(this);
+ this.closed = true;
+ }
+
+ private static void sendMessage(final BGPSessionListener listener, final BGPMessage message) {
+ if (BGPMock.connectionLostMagicMessage.equals(message)) {
+ listener.onSessionTerminated(null);
+ } else if (message instanceof BGPOpenMessage) {
+ final Set<BGPTableType> tts = Sets.newHashSet();
+ for (final BGPParameter param : ((BGPOpenMessage) message).getOptParams()) {
+ if (param instanceof MultiprotocolCapability) {
+ tts.add(((MultiprotocolCapability) param).getTableType());
+ }
+ }
+ listener.onSessionUp(tts);
+ } else if (message instanceof BGPKeepAliveMessage) {
+ // do nothing
+ } else {
+ listener.onMessage(message);
+ }
+ }
+
+ @Override
+ public BGPSessionListener getListener() {
+ return this.listener;
+ }
+}
--- /dev/null
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+ <body>
+ <head>${project.artifactId}</head>
+ <links>
+ <item name="${project.artifactId}" href="index.html"/>
+ </links>
+
+ <menu ref="parent"/>
+
+ <menu ref="reports"/>
+
+
+ </body>
+</project>
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.mock;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+
+
+/**
+ * Mock implementation of {@link BGPListener} for testing purposes.
+ */
+final class BGPListenerMock extends BGPSessionListener {
+ private final List<BGPMessage> buffer = Collections.synchronizedList(new ArrayList<BGPMessage>());
+ private boolean connected = false;
+
+ protected List<BGPMessage> getBuffer() {
+ return this.buffer;
+ }
+
+ protected boolean isConnected() {
+ return this.connected;
+ }
+
+ @Override
+ public void onMessage(final BGPMessage message) {
+ this.buffer.add(message);
+ }
+
+ @Override
+ public void onSessionUp(final Set<BGPTableType> remoteParams) {
+ this.connected = true;
+ }
+
+ @Override
+ public void onSessionDown(final BGPSession session, final Exception e) {
+ this.connected = false;
+ }
+
+ @Override
+ public void onSessionTerminated(final BGPError cause) {
+ this.connected = false;
+ }
+}
--- /dev/null
+Receive BGP Update message for 0x804b6a0: Length = 61
+
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 3d 01 04 00 14 00 b4 14 14 14 14 20 02 06 01
+04 00 01 00 01 02 06 01 04 00 1b 00 01 02 02 80
+00 02 02 02 00 02 06 41 04 00 00 00 14
+
+Receive BGP Update message for 0x804b6a0: Length = 151
+
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 40 02 00 00 00 1f 40 01 01 00 40 02 0a 02 02
+00 00 00 64 00 00 00 46 40 03 04 0a 01 01 0a 40
+05 04 00 00 00 64 20 46 01 02 02 20 46 01 01 01
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 40 02 00 00 00 1f 40 01 01 00 40 02 0a 02 02
+00 00 00 64 00 00 00 5a 40 03 04 0a 01 01 0a 40
+05 04 00 00 00 64 20 5a 01 02 02 20 5a 01 01 01
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 17 02 00 00 00 00
+
+Receive BGP Update message for 0x804b6a0: Length = 1021
+
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 70 02 00 00 00 59 90 0e 00 37 00 1b 01 04 0a
+01 01 0a 00 00 01 00 2a 01 00 00 00 01 00 00 13
+01 02 00 04 64 00 00 00 01 06 00 07 00 00 00 00
+00 01 00 01 01 00 0b 01 06 00 07 00 00 00 00 00
+02 03 40 01 01 00 40 02 06 02 01 00 00 00 64 40
+05 04 00 00 00 64 80 ff 07 01 13 00 03 15 00 00
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+01 28 02 00 00 01 11 90 0e 00 ef 00 1b 01 04 0a
+01 01 0a 00 00 01 00 2a 01 00 00 00 01 00 00 13
+01 02 00 04 64 00 00 00 01 06 00 07 00 00 00 00
+00 10 00 01 01 00 0b 01 06 00 07 00 00 00 00 00
+10 03 00 01 00 2a 01 00 00 00 01 00 00 13 01 02
+00 04 64 00 00 00 01 06 00 07 00 00 00 00 00 10
+00 01 01 00 0b 01 06 00 07 00 00 00 00 00 10 01
+00 01 00 2a 01 00 00 00 01 00 00 13 01 02 00 04
+64 00 00 00 01 06 00 07 00 00 00 00 00 02 00 01
+01 00 0b 01 06 00 07 00 00 00 00 00 10 01 00 01
+00 2a 01 00 00 00 01 00 00 13 01 02 00 04 64 00
+00 00 01 06 00 07 00 00 00 00 00 02 00 01 01 00
+0b 01 06 00 07 00 00 00 00 00 02 03 00 01 00 2a
+01 00 00 00 01 00 00 13 01 02 00 04 64 00 00 00
+01 06 00 07 00 00 00 00 00 01 00 01 01 00 0b 01
+06 00 07 00 00 00 00 00 10 03 40 01 01 00 40 02
+06 02 01 00 00 00 64 40 05 04 00 00 00 64 80 ff
+07 01 13 00 03 0a 00 00 ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff 01 56 02 00 00 01 3f 90
+0e 01 1d 00 1b 01 04 0a 01 01 0a 00 00 01 00 2a
+01 00 00 00 01 00 00 13 01 02 00 04 64 00 00 00
+01 06 00 07 00 00 00 00 00 10 03 01 01 00 0b 01
+06 00 07 00 00 00 00 00 10 00 00 01 00 2a 01 00
+00 00 01 00 00 13 01 02 00 04 64 00 00 00 01 06
+00 07 00 00 00 00 00 10 03 01 01 00 0b 01 06 00
+07 00 00 00 00 00 01 00 00 01 00 2a 01 00 00 00
+01 00 00 13 01 02 00 04 64 00 00 00 01 06 00 07
+00 00 00 00 00 10 01 01 01 00 0b 01 06 00 07 00
+00 00 00 00 10 00 00 01 00 2a 01 00 00 00 01 00
+00 13 01 02 00 04 64 00 00 00 01 06 00 07 00 00
+00 00 00 10 01 01 01 00 0b 01 06 00 07 00 00 00
+00 00 02 00 00 01 00 2a 01 00 00 00 01 00 00 13
+01 02 00 04 64 00 00 00 01 06 00 07 00 00 00 00
+00 02 03 01 01 00 0b 01 06 00 07 00 00 00 00 00
+02 00 00 01 00 2a 01 00 00 00 01 00 00 13 01 02
+00 04 64 00 00 00 01 06 00 07 00 00 00 00 00 02
+03 01 01 00 0b 01 06 00 07 00 00 00 00 00 01 00
+40 01 01 00 40 02 06 02 01 00 00 00 64 40 05 04
+00 00 00 64 80 ff 07 01 13 00 03 00 00 00 ff ff
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 f2
+02 00 00 00 db 90 0e 00 c3 00 1b 01 04 0a 01 01
+0a 00 00 02 00 1b 01 00 00 00 01 00 00 13 01 02
+00 04 64 00 00 00 01 06 00 07 00 00 00 00 00 10
+03 00 02 00 1b 01 00 00 00 01 00 00 13 01 02 00
+04 64 00 00 00 01 06 00 07 00 00 00 00 00 10 01
+00 02 00 1b 01 00 00 00 01 00 00 13 01 02 00 04
+64 00 00 00 01 06 00 07 00 00 00 00 00 10 00 00
+02 00 1b 01 00 00 00 01 00 00 13 01 02 00 04 64
+00 00 00 01 06 00 07 00 00 00 00 00 02 03 00 02
+00 1b 01 00 00 00 01 00 00 13 01 02 00 04 64 00
+00 00 01 06 00 07 00 00 00 00 00 02 00 00 02 00
+1b 01 00 00 00 01 00 00 13 01 02 00 04 64 00 00
+00 01 06 00 07 00 00 00 00 00 01 00 40 01 01 00
+40 02 06 02 01 00 00 00 64 40 05 04 00 00 00 64
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 1d 02 00 00 00 06 80 0f 03 00 1b 01
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>bgp-testing-tool</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-testtool</artifactId>
+ <description>BGP Interop Testing Tool</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>framework</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-impl</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-rib-impl</artifactId>
+ <version>1.0</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.testtool
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>1.7.1</version>
+ <configuration>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <transformers>
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>org.opendaylight.protocol.bgp.testtool.Main</mainClass>
+ </transformer>
+ </transformers>
+ <shadedArtifactAttached>true</shadedArtifactAttached>
+ <shadedClassifierName>executable</shadedClassifierName>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.testtool;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.rib.impl.BGPConnectionImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPDispatcherImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalCheckerImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionProposalChecker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * Starter class for testing.
+ */
+public class Main {
+
+ private final static Logger logger = LoggerFactory.getLogger(Main.class);
+
+ public static String usage = "DESCRIPTION:\n" + "\tCreates a server with given parameters. As long as it runs, it accepts connections "
+ + "from PCCs.\n" + "USAGE:\n" + "\t-a, --address\n" + "\t\tthe ip address to which is this server bound.\n"
+ + "\t\tFormat: x.x.x.x:y where y is port number.\n\n"
+ + "\t\tThis IP address will appear in BGP Open message as BGP Identifier of the server.\n" +
+
+ "\t-as\n" + "\t\t value of AS in the initial open message\n\n" +
+
+ "\t-h, --holdtimer\n" + "\t\tin seconds, value of the desired holdtimer\n"
+ + "\t\tAccording to RFC4271, recommended value for deadtimer is 90 seconds.\n"
+ + "\t\tIf not set, this will be the default value.\n\n" +
+
+ "\t--help\n" + "\t\tdisplay this help and exits\n\n" +
+
+ "With no parameters, this help is printed.";
+
+ BGPDispatcherImpl dispatcher;
+
+ public Main() throws IOException {
+ this.dispatcher = new BGPDispatcherImpl(new DispatcherImpl(Executors.defaultThreadFactory()));
+ }
+
+ public static void main(final String[] args) throws NumberFormatException, IOException {
+ if (args.length == 0 || (args.length == 1 && args[0].equalsIgnoreCase("--help"))) {
+ System.out.println(Main.usage);
+ return;
+ }
+
+ InetSocketAddress address = null;
+ short holdTimerValue = 90;
+ ASNumber as = null;
+
+ int i = 0;
+ while (i < args.length) {
+ if (args[i].equalsIgnoreCase("-a") || args[i].equalsIgnoreCase("--address")) {
+ final String[] ip = args[i + 1].split(":");
+ address = new InetSocketAddress(InetAddress.getByName(ip[0]), Integer.valueOf(ip[1]));
+ i++;
+ } else if (args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("--holdtimer")) {
+ holdTimerValue = Short.valueOf(args[i + 1]);
+ i++;
+ } else if (args[i].equalsIgnoreCase("-as")) {
+ as = new ASNumber(Long.valueOf(args[i + 1]));
+ i++;
+ } else {
+ System.out.println("WARNING: Unrecognized argument: " + args[i]);
+ }
+ i++;
+ }
+
+ final Main m = new Main();
+
+ final BGPSessionListener sessionListener = new TestingListener((DispatcherImpl) m.dispatcher.getDispatcher());
+
+ final BGPSessionProposalImpl prop = new BGPSessionProposalImpl(holdTimerValue, as, new IPv4Address(InetAddress.getByName("25.25.25.2")));
+
+ final BGPSessionPreferences proposal = prop.getProposal();
+
+ prop.close();
+
+ final BGPSessionProposalChecker checker = new BGPSessionProposalCheckerImpl();
+
+ final BGPMessageParser parser = new BGPMessageFactory();
+
+ logger.debug(address + " " + sessionListener + " " + proposal + " " + checker);
+
+ final InetSocketAddress addr = address;
+ m.dispatcher.createClient(new BGPConnectionImpl(addr, sessionListener, proposal, checker), parser);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.testtool;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+
+/**
+ * Testing BGP Listener.
+ */
+public class TestingListener extends BGPSessionListener {
+ private static final Logger logger = LoggerFactory.getLogger(TestingListener.class);
+
+ DispatcherImpl d;
+
+ TestingListener(final DispatcherImpl d) {
+ this.d = d;
+ }
+
+ @Override
+ public void onMessage(final BGPMessage message) {
+ logger.info("Client Listener: message received: {}", message.toString());
+ }
+
+ @Override
+ public void onSessionUp(final Set<BGPTableType> remoteParams) {
+ logger.info("Client Listener: Session Up.");
+ }
+
+ @Override
+ public void onSessionDown(final BGPSession session, final Exception e) {
+ logger.info("Client Listener: Connection lost.");
+ session.close();
+ this.d.stop();
+ }
+
+ @Override
+ public void onSessionTerminated(final BGPError cause) {
+ logger.info("Client Listener: Connection lost: {}.", cause);
+ this.d.stop();
+ }
+}
--- /dev/null
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>TRACE</level>
+ </filter>
+ <encoder>
+ <pattern>[%d{HH:mm:ss.SSS}] [%thread] %-5level %logger{10} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.opendaylight.protocol" level="TRACE" />
+
+ <root level="TRACE">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.testtool;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+import org.opendaylight.protocol.bgp.parser.BGPMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.BGPMessageFactory;
+import org.opendaylight.protocol.bgp.rib.impl.BGPConnectionImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPInputStream;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionFactory;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalCheckerImpl;
+import org.opendaylight.protocol.bgp.rib.impl.BGPSessionProposalImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnection;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPConnectionFactory;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4;
+
+public class BGPSpeakerMock {
+
+ DispatcherImpl dispatcher;
+
+ BGPSpeakerMock() throws IOException {
+ this.dispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+ }
+
+ public static void main(final String[] args) throws IOException {
+
+ final BGPSpeakerMock m = new BGPSpeakerMock();
+
+ final BGPMessageParser parser = new BGPMessageFactory();
+
+ m.dispatcher.createServer(new InetSocketAddress("127.0.0.2", 12345), new BGPConnectionFactory() {
+ @Override
+ public BGPConnection createProtocolConnection(final InetSocketAddress address) {
+ final BGPSessionProposalImpl prop = new BGPSessionProposalImpl((short) 90, new ASNumber(25), IPv4.FAMILY.addressForString("127.0.0.2"));
+ final BGPSessionPreferences prefs = prop.getProposal();
+ try {
+ prop.close();
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ return new BGPConnectionImpl(address, new SpeakerSessionListener(m.dispatcher), prefs, new BGPSessionProposalCheckerImpl());
+ }
+ }, new BGPSessionFactory(parser), BGPInputStream.FACTORY);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.testtool;
+
+import java.util.Set;
+
+import org.opendaylight.protocol.bgp.concepts.BGPTableType;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.BGPMessage;
+import org.opendaylight.protocol.bgp.parser.BGPSession;
+import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+
+public class SpeakerSessionListener extends BGPSessionListener {
+ private static final Logger logger = LoggerFactory.getLogger(SpeakerSessionListener.class);
+
+ DispatcherImpl d;
+
+ SpeakerSessionListener(final DispatcherImpl d) {
+ this.d = d;
+ }
+
+ @Override
+ public void onSessionUp(final Set<BGPTableType> remote) {
+ logger.info("Server: Session is up.");
+ }
+
+ @Override
+ public void onSessionTerminated(final BGPError cause) {
+ logger.info("Server: Session terminated: {}", cause);
+ }
+
+ @Override
+ public void onSessionDown(final BGPSession session, final Exception e) {
+ logger.info("Server: Session down.");
+ session.close();
+ this.d.stop();
+ }
+
+ @Override
+ public void onMessage(final BGPMessage message) {
+ logger.info("Server: Message received: {}", message);
+ this.d.stop();
+ }
+}
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>util</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>bgp-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bgp-util</artifactId>
+ <description>BGP utilities</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-parser-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-linkstate</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgp-concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.protocol.bgp.util,
+ </Export-Package>
+ <Import-Package>
+ org.opendaylight.protocol.bgp.concepts,
+ org.opendaylight.protocol.bgp.linkstate,
+ org.opendaylight.protocol.bgp.parser,
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.util,
+ com.google.common.*,
+ org.opendaylight.protocol.concepts,
+ org.apache.commons.*,
+ org.slf4j
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>BGP-UTIL Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.bgp.concepts.BGPObject;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Implementation of BGPObject that wraps up BGPNode and BGPLink.
+ */
+public abstract class AbstractBGPObject implements BGPObject {
+ private static final long serialVersionUID = 1L;
+ private final BaseBGPObjectState state;
+
+ protected AbstractBGPObject(final BaseBGPObjectState state) {
+ this.state = state;
+ }
+
+ @Override
+ public BaseBGPObjectState currentState() {
+ return state;
+ }
+
+ @Override
+ public synchronized final String toString(){
+ return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("state", this.state);
+ return toStringHelper;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((state == null) ? 0 : state.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ AbstractBGPObject other = (AbstractBGPObject) obj;
+ if (state == null) {
+ if (other.state != null)
+ return false;
+ } else if (!state.equals(other.state))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPPrefix;
+import org.opendaylight.protocol.bgp.parser.BGPPrefixState;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import com.google.common.base.Preconditions;
+
+/**
+ * Super class for BGPIpvXPrefixImpl.
+ *
+ * @param <T> extends NetworkAddress<T>
+ */
+public abstract class AbstractBGPPrefix<T extends NetworkAddress<T>> extends AbstractBGPObject implements BGPPrefix<T> {
+ private static final long serialVersionUID = 1L;
+ private final PrefixIdentifier<T> descriptor;
+
+ protected AbstractBGPPrefix(final BaseBGPObjectState base, final PrefixIdentifier<T> descriptor, final NetworkPrefixState prefixState) {
+ super(new BGPPrefixState(base, prefixState));
+ Preconditions.checkNotNull(descriptor);
+ this.descriptor = descriptor;
+ }
+
+ @Override
+ public final PrefixIdentifier<T> getPrefixIdentifier() {
+ return this.descriptor;
+ }
+
+ @Override
+ final public BGPPrefixState currentState() {
+ return (BGPPrefixState) super.currentState();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPRoute;
+import org.opendaylight.protocol.bgp.parser.BGPRouteState;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ * Super class for BGPIpvXPrefixImpl.
+ *
+ * @param <T> extends NetworkAddress<T>
+ */
+public abstract class AbstractBGPRoute<T extends NetworkAddress<T>> extends AbstractBGPObject implements BGPRoute<T> {
+ private static final long serialVersionUID = 1L;
+ private final Prefix<T> name;
+
+ protected AbstractBGPRoute(final Prefix<T> name, final BaseBGPObjectState base, final NetworkRouteState<T> routeState) {
+ super(new BGPRouteState<T>(base, routeState));
+ this.name = Preconditions.checkNotNull(name);
+ }
+
+ @Override
+ final public BGPRouteState<T> currentState() {
+ return (BGPRouteState<T>) super.currentState();
+ }
+
+ @Override
+ final public Prefix<T> getName() {
+ return this.name;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final AbstractBGPRoute<?> other = (AbstractBGPRoute<?>) obj;
+ if (this.name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!this.name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("name", this.name);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+
+/**
+ * Implementation of {@link AbstractBGPPrefix}.
+ */
+public final class BGPIPv4PrefixImpl extends AbstractBGPPrefix<IPv4Address> {
+ private static final long serialVersionUID = 1L;
+
+ public BGPIPv4PrefixImpl(final BaseBGPObjectState base, final IPv4PrefixIdentifier identifier, final NetworkPrefixState prefixState) {
+ super(base, identifier, prefixState);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+/**
+ * Implementation of {@link AbstractBGPPrefix}.
+ */
+public final class BGPIPv4RouteImpl extends AbstractBGPRoute<IPv4Address> {
+ private static final long serialVersionUID = 1L;
+
+ public BGPIPv4RouteImpl(final Prefix<IPv4Address> prefix, final BaseBGPObjectState base,
+ final NetworkRouteState<IPv4Address> prefixState) {
+ super(prefix, base, prefixState);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.bgp.linkstate.PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+
+/**
+ * Implementation of {@link AbstractBGPPrefix}
+ */
+public class BGPIPv6PrefixImpl extends AbstractBGPPrefix<IPv6Address> {
+ private static final long serialVersionUID = 1L;
+
+ public BGPIPv6PrefixImpl(final BaseBGPObjectState base, final PrefixIdentifier<IPv6Address> descriptor,
+ final NetworkPrefixState prefixState) {
+ super(base, descriptor, prefixState);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+/**
+ * Implementation of {@link AbstractBGPPrefix}.
+ */
+public final class BGPIPv6RouteImpl extends AbstractBGPRoute<IPv6Address> {
+ private static final long serialVersionUID = 1L;
+
+ public BGPIPv6RouteImpl(final Prefix<IPv6Address> prefix, final BaseBGPObjectState base, final NetworkRouteState<IPv6Address> prefixState) {
+ super(prefix, base, prefixState);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPLink;
+import org.opendaylight.protocol.bgp.parser.BGPLinkState;
+
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Preconditions;
+
+/**
+ *
+ * BGP Link-State Link object is a composition object of BGPObject (so it can be contained in addedObjects in Update
+ * Message) and Network Link, that merges the attributes from Link-State NLRI about Links.
+ *
+ */
+public final class BGPLinkImpl extends AbstractBGPObject implements BGPLink {
+
+ private static final long serialVersionUID = -226135392855622720L;
+
+ private final LinkIdentifier linkIdentifier;
+
+ /**
+ * Creates a new Link with given arguments.
+ *
+ * @param origin BGPOrigin
+ * @param aggregator BGPAggregator
+ * @param linkIdentifier LinkIdentifier
+ * @param linkAttributes NetworkLink
+ */
+ public BGPLinkImpl(final BaseBGPObjectState base, final LinkIdentifier linkIdentifier, final NetworkLinkState linkState) {
+ super(new BGPLinkState(base, linkState));
+ Preconditions.checkNotNull(linkIdentifier);
+ this.linkIdentifier = linkIdentifier;
+ }
+
+ @Override
+ public LinkIdentifier getLinkIdentifier() {
+ return this.linkIdentifier;
+ }
+
+ @Override
+ public BGPLinkState currentState() {
+ return (BGPLinkState) super.currentState();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.linkIdentifier == null) ? 0 : this.linkIdentifier.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (!(obj instanceof BGPLinkImpl))
+ return false;
+ final BGPLinkImpl other = (BGPLinkImpl) obj;
+ if (this.linkIdentifier == null) {
+ if (other.linkIdentifier != null)
+ return false;
+ } else if (!this.linkIdentifier.equals(other.linkIdentifier))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("linkIdentifier", this.linkIdentifier);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.bgp.concepts.BGPAggregator;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.parser.BGPNode;
+import org.opendaylight.protocol.bgp.parser.BGPNodeState;
+
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNode;
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ *
+ * BGP Link-State Node object is a composition object of BGPObject (so it can be contained in addedObjects in Update
+ * Message) and Network Node, that merges the attributes from Link-State NLRI about Nodes.
+ *
+ */
+public final class BGPNodeImpl extends AbstractBGPObject implements BGPNode {
+ private static final long serialVersionUID = 1L;
+
+ private final NodeIdentifier nodeIdentifier;
+
+ /**
+ * Creates this object with given arguments.
+ *
+ * @param origin {@link BGPOrigin}
+ * @param aggregator {@link BGPAggregator}
+ * @param nodeIdentifier {@link NodeIdentifier}
+ * @param nodeAttributes {@link NetworkNode}
+ */
+ public BGPNodeImpl(final BaseBGPObjectState base, final NodeIdentifier nodeIdentifier, final NetworkNodeState nodeState) {
+ super(new BGPNodeState(base, nodeState));
+ this.nodeIdentifier = nodeIdentifier;
+ }
+
+ @Override
+ public BGPNodeState currentState() {
+ return (BGPNodeState) super.currentState();
+ }
+
+ @Override
+ public NodeIdentifier getNodeIdentifier() {
+ return this.nodeIdentifier;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ toStringHelper.add("nodeDescriptor", this.nodeIdentifier);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.nodeIdentifier == null) ? 0 : this.nodeIdentifier.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final BGPNodeImpl other = (BGPNodeImpl) obj;
+ if (this.nodeIdentifier == null) {
+ if (other.nodeIdentifier != null)
+ return false;
+ } else if (!this.nodeIdentifier.equals(other.nodeIdentifier))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * This extracter extracts BGP messages in binary form from a file in MRT format.
+ * (http://www.ripe.net/data-tools/stats/ris/ris-raw-data) The parser detects BGP messages by searching for 16 FF bytes,
+ * everything else before or after is ignored.
+ */
+@Immutable
+public final class BinaryBGPDumpFileParser {
+
+ private static final byte ff = (byte) 255;
+ private static final Logger LOG = LoggerFactory.getLogger(BinaryBGPDumpFileParser.class);
+ private static final int MINIMAL_LENGTH = 19;
+
+ /**
+ * Extract BGP messages from binary file in MRT format.
+ *
+ * @param file file with BGP messages in binary form.
+ * @return list with byte arrays representing extracted messages.
+ * @throws IOException
+ */
+ public static List<byte[]> parseMessages(final byte[] byteArray) {
+
+ final List<byte[]> messages = Lists.newLinkedList();
+ // search for 16 FFs
+ for (int i = 0; i < byteArray.length; i++) {
+ final byte b = byteArray[i];
+
+ // Marker start
+ if (b == ff) {
+ final int start = i;
+ int ffCount = 0;
+ for (int j = i; j < i + (17); j++) {
+ // Check marker
+ if (byteArray[j] == ff) {
+ ffCount++;
+ } else if (ffCount == 16) {
+ if (j == (i + 16)) {
+ // Parse length
+ final int length = UnsignedBytes.toInt(byteArray[j]) * 256 + UnsignedBytes.toInt(byteArray[j + 1]);
+
+ Preconditions.checkArgument(length >= MINIMAL_LENGTH, "Invalid message at index " + start
+ + ", length atribute is lower than " + MINIMAL_LENGTH);
+
+ final byte[] message = Arrays.copyOfRange(byteArray, start, start + length);
+ messages.add(message);
+ j += length - 16;
+ }
+ i = j;
+ break;
+ } else {
+ break;
+ }
+ }
+ }
+
+ }
+ LOG.info("Succesfully extracted " + messages.size() + " messages");
+ return messages;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.concurrent.Immutable;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * Read text file, parse BGP messages. File can contain comments or other data. BGP messages are detected using 16 ff marker.
+ * New lines and spaces are ignored. Use {@link ByteArray#bytesToHexString(byte[])} for serializing bytes to this format.
+ */
+@Immutable
+public class HexDumpBGPFileParser {
+ private static final int MINIMAL_LENGTH = 19;
+ private static final Logger LOG = LoggerFactory.getLogger(HexDumpBGPFileParser.class);
+ private static final String ff_16 = Strings.repeat("FF", 16);
+
+ public static List<byte[]> parseMessages(File file) {
+ Preconditions.checkArgument(file != null, "Filename cannot be null");
+ Preconditions.checkArgument(file.exists() && file.canRead(), "File " + file + " does not exist or is not readable");
+ String content;
+ try {
+ content = Files.toString(file, Charset.defaultCharset());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return parseMessages(content);
+ }
+
+ public static List<byte[]> parseMessages(String content) {
+ content = clearWhiteSpace_toUpper(content);
+ // search for 16 FFs
+
+ List<byte[]> messages = Lists.newLinkedList();
+ int idx = 0;
+ while ((idx = content.indexOf(ff_16, idx)) > -1) {
+ // next 2 bytes are length
+ int lengthIdx = idx + 16 * 2;
+ int messageIdx = lengthIdx + 4;
+ String hexLength = content.substring(lengthIdx, messageIdx);
+ byte[] byteLength = null;
+ try {
+ byteLength = Hex.decodeHex(hexLength.toCharArray());
+ } catch (DecoderException e) {
+ throw new RuntimeException(e);
+ }
+ int length = ByteArray.bytesToInt(byteLength);
+ int messageEndIdx = idx + length * 2;
+
+ // Assert that message is longer than minimum 19(header.length == 19)
+ // If length in BGP message would be 0, loop would never end
+ Preconditions.checkArgument(length >= MINIMAL_LENGTH,
+ "Invalid message at index " + idx
+ + ", length atribute is lower than " + MINIMAL_LENGTH);
+
+ String hexMessage = content.substring(idx, messageEndIdx);
+ byte[] message = null;
+ try {
+ message = Hex.decodeHex(hexMessage.toCharArray());
+ } catch (DecoderException e) {
+ new RuntimeException(e);
+ }
+ messages.add(message);
+ idx = messageEndIdx;
+ }
+ LOG.info("Succesfully extracted " + messages.size() + " messages");
+ return messages;
+ }
+
+ @VisibleForTesting
+ static String clearWhiteSpace_toUpper(String line){
+ return line.replaceAll("\\s", "").toUpperCase();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.junit.Test;
+
+public class BGPBinaryFileParserTest {
+
+ private final byte ff = (byte) 255;
+
+ @Test
+ public void testCorrectExtraction() throws IOException {
+ final List<byte[]> parsedMessages = extractFromFile("/BgpMessages");
+
+ assertThat(parsedMessages.size(), is(43));
+
+ // 1st message
+ assertThat(parsedMessages.get(0).length, is(19));
+ checkMarker(parsedMessages);
+ assertThat(parsedMessages.get(0)[16], is((byte) 0));
+ assertThat(parsedMessages.get(0)[17], is((byte) 19));
+ assertThat(parsedMessages.get(0)[18], is((byte) 4));
+
+ // 39th message
+ assertThat(parsedMessages.get(38).length, is(91));
+ checkMarker(parsedMessages);
+ assertThat(parsedMessages.get(38)[16], is((byte) 0));
+ assertThat(parsedMessages.get(38)[17], is((byte) 91));
+ assertThat(parsedMessages.get(38)[18], is((byte) 2));
+ assertThat(parsedMessages.get(38)[90], is((byte) 236));
+
+ }
+
+ private List<byte[]> extractFromFile(final String fileName) throws IOException {
+ final InputStream is = BGPBinaryFileParserTest.class.getResourceAsStream(fileName);
+ assertNotNull("File not found - " + fileName);
+ if (is == null)
+ throw new IOException("Failed to get resource " + fileName);
+
+ final ByteArrayOutputStream bis = new ByteArrayOutputStream();
+ final byte[] data = new byte[1000];
+ int nRead = 0;
+ while ((nRead = is.read(data, 0, data.length)) != -1) {
+ bis.write(data, 0, nRead);
+ }
+ bis.flush();
+ return BinaryBGPDumpFileParser.parseMessages(bis.toByteArray());
+ }
+
+ private void checkMarker(final List<byte[]> parsedMessages) {
+ for (int i = 0; i < 16; i++) {
+ assertThat(parsedMessages.get(0)[i], is(this.ff));
+ }
+ }
+
+ /**
+ * In BgpMessages_wrong_header file, first FF sequence is corrupted
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testCorruptedHeader() throws IOException {
+ final List<byte[]> parsedMessages = extractFromFile("/BgpMessages_wrong_header");
+ assertEquals(42, parsedMessages.size());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import java.io.File;
+import java.util.List;
+
+import org.junit.Test;
+
+public class BGPHexFileParserTest {
+
+ public static final String hexDumpFileName = "/bgp_hex.txt";
+ private final String fileNameInvalid = "BgpMessage_Hex_InvalidLength";
+ private final int expectedSize = 9;
+
+ @Test
+ public void testCleanWhiteSpace() {
+ final String input = "abc def\r\nghi\nj";
+ assertEquals("ABCDEFGHIJ", HexDumpBGPFileParser.clearWhiteSpace_toUpper(input));
+ }
+
+ @Test
+ public void testParsing() {
+ final List<byte[]> result = HexDumpBGPFileParser.parseMessages(new File(getClass().getResource(BGPHexFileParserTest.hexDumpFileName).getFile()));
+ assertEquals(this.expectedSize, result.size());
+ }
+
+ @Test
+ public void testParsingInvalidMessage() {
+ try {
+ HexDumpBGPFileParser.parseMessages(new File(this.fileNameInvalid));
+ fail("Exception should have occured.");
+ } catch (final IllegalArgumentException e) {
+ assertThat(e.getMessage(), containsString("File BgpMessage_Hex_InvalidLength does not exist or is not readable"));
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collections;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.Metric;
+import org.opendaylight.protocol.bgp.linkstate.LinkIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.LinkProtectionType;
+import org.opendaylight.protocol.bgp.linkstate.TopologyIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.NetworkLinkState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.util.BGPLinkImpl;
+import org.opendaylight.protocol.util.DefaultingTypesafeContainer;
+
+public class LinkTest {
+
+ @Test
+ public void testLinkImpl() {
+
+ final BaseBGPObjectState state1 = new BaseBGPObjectState(BGPOrigin.EGP, null);
+ final NetworkObjectState empty = new NetworkObjectState(null, Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+ final NetworkLinkState nstate1 = new NetworkLinkState(empty, new DefaultingTypesafeContainer<Metric<?>>(), null, LinkProtectionType.UNPROTECTED, null, null, null);
+
+ final BGPLinkImpl link1 = new BGPLinkImpl(state1, new LinkIdentifier(new TopologyIdentifier(512), null, null), nstate1);
+ final BGPLinkImpl link2 = new BGPLinkImpl(state1, new LinkIdentifier(new TopologyIdentifier(512), null, null), nstate1);
+
+ assertEquals(link1, link2);
+ assertEquals(link1.toString(), link2.toString());
+ assertEquals(link1.hashCode(), link2.hashCode());
+ assertEquals(link1.getLinkIdentifier(), link2.getLinkIdentifier());
+ assertEquals(link1.currentState(), link2.currentState());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.util.BGPNodeImpl;
+
+import org.opendaylight.protocol.bgp.linkstate.NetworkNodeState;
+
+public class NodeTest {
+
+ @Test
+ public void testNodeImpl() {
+ final BGPNodeImpl node1 = new BGPNodeImpl(new BaseBGPObjectState(BGPOrigin.INCOMPLETE, null), null, NetworkNodeState.EMPTY);
+ final BGPNodeImpl node2 = new BGPNodeImpl(new BaseBGPObjectState(BGPOrigin.EGP, null), null, NetworkNodeState.EMPTY);
+
+ assertFalse(node1.equals(node2));
+ assertNotSame(node1.hashCode(), node2.hashCode());
+ assertEquals(node1.toString(), node1.toString());
+ assertNull(node1.currentState().getAggregator());
+ assertEquals(node1.currentState().getOrigin(), BGPOrigin.INCOMPLETE);
+ assertEquals(node1.getNodeIdentifier(), node2.getNodeIdentifier());
+ assertEquals(node2, new BGPNodeImpl(new BaseBGPObjectState(BGPOrigin.EGP, null), null, NetworkNodeState.EMPTY));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+import java.util.Collections;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.ASPath;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.Community;
+import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
+import org.opendaylight.protocol.bgp.util.BGPIPv4PrefixImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6PrefixImpl;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.bgp.linkstate.NodeIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.OSPFRouterIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.RouteTag;
+import org.opendaylight.protocol.bgp.linkstate.NetworkObjectState;
+import org.opendaylight.protocol.bgp.linkstate.NetworkPrefixState;
+import org.opendaylight.protocol.bgp.linkstate.IPv4PrefixIdentifier;
+import org.opendaylight.protocol.bgp.linkstate.IPv6PrefixIdentifier;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class PrefixTest {
+ final BaseBGPObjectState base = new BaseBGPObjectState(BGPOrigin.EGP, null);
+ final NetworkObjectState state = new NetworkObjectState(new ASPath(Lists.newArrayList(new ASNumber(10L))), Collections.<Community> emptySet(), Collections.<ExtendedCommunity> emptySet());
+ final NetworkPrefixState prefixState = new NetworkPrefixState(this.state, Sets.<RouteTag> newTreeSet(), null);
+
+ final BGPIPv4PrefixImpl r4 = new BGPIPv4PrefixImpl(this.base, new IPv4PrefixIdentifier(new NodeIdentifier(null, null, null, new OSPFRouterIdentifier(new byte[] {
+ 1, 2, 3, 4 })), IPv4.FAMILY.prefixForString("172.168.4.5/16")), this.prefixState);
+ final BGPIPv6PrefixImpl r6 = new BGPIPv6PrefixImpl(this.base, new IPv6PrefixIdentifier(new NodeIdentifier(null, null, null, new OSPFRouterIdentifier(new byte[] {
+ 1, 2, 3, 4 })), IPv6.FAMILY.prefixForString("2001::4/32")), this.prefixState);
+
+ @Test
+ public void testIPv4Prefix() {
+ final BGPIPv4PrefixImpl r2 = new BGPIPv4PrefixImpl(this.base, new IPv4PrefixIdentifier(new NodeIdentifier(null, null, null, new OSPFRouterIdentifier(new byte[] {
+ 1, 2, 3, 4 })), IPv4.FAMILY.prefixForString("172.168.4.5/16")), this.prefixState);
+
+ assertEquals(this.r4, r2);
+ assertEquals(this.r4.hashCode(), r2.hashCode());
+ assertNotSame(this.r4, this.r6);
+ }
+
+ @Test
+ public void testIPv6Route() {
+ final BGPIPv6PrefixImpl r2 = new BGPIPv6PrefixImpl(this.base, new IPv6PrefixIdentifier(new NodeIdentifier(null, null, null, new OSPFRouterIdentifier(new byte[] {
+ 1, 2, 3, 4 })), IPv6.FAMILY.prefixForString("2001::4/32")), this.prefixState);
+
+ assertEquals(this.r6.currentState(), r2.currentState());
+ assertEquals(this.r6.toString(), r2.toString());
+ assertEquals(this.r6.getPrefixIdentifier(), r2.getPrefixIdentifier());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.concepts.BGPOrigin;
+import org.opendaylight.protocol.bgp.concepts.BaseBGPObjectState;
+import org.opendaylight.protocol.bgp.concepts.IPv4NextHop;
+import org.opendaylight.protocol.bgp.concepts.IPv6NextHop;
+import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
+import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.bgp.linkstate.NetworkRouteState;
+
+public class RouteTest {
+
+ BaseBGPObjectState base = new BaseBGPObjectState(BGPOrigin.EGP, null);
+ final NetworkRouteState<IPv4Address> prefix4State = new NetworkRouteState<>(IPv4NextHop.forString("128.54.8.9"));
+ final NetworkRouteState<IPv6Address> prefix6State = new NetworkRouteState<>(IPv6NextHop.forString("2001::4"));
+ final BGPIPv4RouteImpl r4 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.168.4.6/24"), this.base, this.prefix4State);
+ final BGPIPv6RouteImpl r6 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001::4/32"), this.base, this.prefix6State);
+
+ @Test
+ public void testIPv4Route() {
+ final BGPIPv4RouteImpl r2 = new BGPIPv4RouteImpl(IPv4.FAMILY.prefixForString("172.168.4.6/24"), this.base, this.prefix4State);
+
+ assertEquals(this.r4, r2);
+ assertEquals(this.r4.hashCode(), r2.hashCode());
+ assertNotSame(this.r4, this.r6);
+ }
+
+ @Test
+ public void testIPv6Route() {
+ final BGPIPv6RouteImpl r2 = new BGPIPv6RouteImpl(IPv6.FAMILY.prefixForString("2001::4/32"), this.base, this.prefix6State);
+
+ assertEquals(this.r6.currentState(), r2.currentState());
+ assertEquals(this.r6.toString(), r2.toString());
+ assertEquals(this.r6.getName(), r2.getName());
+ }
+}
--- /dev/null
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff\r
+00 00 02\r
--- /dev/null
+Receive BGP Update message for 0x804b6a0: Length = 61
+
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 3d 01 04 00 14 00 b4 14 14 14 14 20 02 06 01
+04 00 01 00 01 02 06 01 04 00 1b 00 01 02 02 80
+00 02 02 02 00 02 06 41 04 00 00 00 14
+
+Receive BGP Update message for 0x804b6a0: Length = 151
+
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 40 02 00 00 00 1f 40 01 01 00 40 02 0a 02 02
+00 00 00 64 00 00 00 46 40 03 04 0a 01 01 0a 40
+05 04 00 00 00 64 20 46 01 02 02 20 46 01 01 01
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 40 02 00 00 00 1f 40 01 01 00 40 02 0a 02 02
+00 00 00 64 00 00 00 5a 40 03 04 0a 01 01 0a 40
+05 04 00 00 00 64 20 5a 01 02 02 20 5a 01 01 01
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 17 02 00 00 00 00
+
+Receive BGP Update message for 0x804b6a0: Length = 1021
+
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 70 02 00 00 00 59 90 0e 00 37 00 1b 01 04 0a
+01 01 0a 00 00 01 00 2a 01 00 00 00 01 00 00 13
+01 02 00 04 64 00 00 00 01 06 00 07 00 00 00 00
+00 01 00 01 01 00 0b 01 06 00 07 00 00 00 00 00
+02 03 40 01 01 00 40 02 06 02 01 00 00 00 64 40
+05 04 00 00 00 64 80 ff 07 01 13 00 03 15 00 00
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+01 28 02 00 00 01 11 90 0e 00 ef 00 1b 01 04 0a
+01 01 0a 00 00 01 00 2a 01 00 00 00 01 00 00 13
+01 02 00 04 64 00 00 00 01 06 00 07 00 00 00 00
+00 10 00 01 01 00 0b 01 06 00 07 00 00 00 00 00
+10 03 00 01 00 2a 01 00 00 00 01 00 00 13 01 02
+00 04 64 00 00 00 01 06 00 07 00 00 00 00 00 10
+00 01 01 00 0b 01 06 00 07 00 00 00 00 00 10 01
+00 01 00 2a 01 00 00 00 01 00 00 13 01 02 00 04
+64 00 00 00 01 06 00 07 00 00 00 00 00 02 00 01
+01 00 0b 01 06 00 07 00 00 00 00 00 10 01 00 01
+00 2a 01 00 00 00 01 00 00 13 01 02 00 04 64 00
+00 00 01 06 00 07 00 00 00 00 00 02 00 01 01 00
+0b 01 06 00 07 00 00 00 00 00 02 03 00 01 00 2a
+01 00 00 00 01 00 00 13 01 02 00 04 64 00 00 00
+01 06 00 07 00 00 00 00 00 01 00 01 01 00 0b 01
+06 00 07 00 00 00 00 00 10 03 40 01 01 00 40 02
+06 02 01 00 00 00 64 40 05 04 00 00 00 64 80 ff
+07 01 13 00 03 0a 00 00 ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff 01 56 02 00 00 01 3f 90
+0e 01 1d 00 1b 01 04 0a 01 01 0a 00 00 01 00 2a
+01 00 00 00 01 00 00 13 01 02 00 04 64 00 00 00
+01 06 00 07 00 00 00 00 00 10 03 01 01 00 0b 01
+06 00 07 00 00 00 00 00 10 00 00 01 00 2a 01 00
+00 00 01 00 00 13 01 02 00 04 64 00 00 00 01 06
+00 07 00 00 00 00 00 10 03 01 01 00 0b 01 06 00
+07 00 00 00 00 00 01 00 00 01 00 2a 01 00 00 00
+01 00 00 13 01 02 00 04 64 00 00 00 01 06 00 07
+00 00 00 00 00 10 01 01 01 00 0b 01 06 00 07 00
+00 00 00 00 10 00 00 01 00 2a 01 00 00 00 01 00
+00 13 01 02 00 04 64 00 00 00 01 06 00 07 00 00
+00 00 00 10 01 01 01 00 0b 01 06 00 07 00 00 00
+00 00 02 00 00 01 00 2a 01 00 00 00 01 00 00 13
+01 02 00 04 64 00 00 00 01 06 00 07 00 00 00 00
+00 02 03 01 01 00 0b 01 06 00 07 00 00 00 00 00
+02 00 00 01 00 2a 01 00 00 00 01 00 00 13 01 02
+00 04 64 00 00 00 01 06 00 07 00 00 00 00 00 02
+03 01 01 00 0b 01 06 00 07 00 00 00 00 00 01 00
+40 01 01 00 40 02 06 02 01 00 00 00 64 40 05 04
+00 00 00 64 80 ff 07 01 13 00 03 00 00 00 ff ff
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 f2
+02 00 00 00 db 90 0e 00 c3 00 1b 01 04 0a 01 01
+0a 00 00 02 00 1b 01 00 00 00 01 00 00 13 01 02
+00 04 64 00 00 00 01 06 00 07 00 00 00 00 00 10
+03 00 02 00 1b 01 00 00 00 01 00 00 13 01 02 00
+04 64 00 00 00 01 06 00 07 00 00 00 00 00 10 01
+00 02 00 1b 01 00 00 00 01 00 00 13 01 02 00 04
+64 00 00 00 01 06 00 07 00 00 00 00 00 10 00 00
+02 00 1b 01 00 00 00 01 00 00 13 01 02 00 04 64
+00 00 00 01 06 00 07 00 00 00 00 00 02 03 00 02
+00 1b 01 00 00 00 01 00 00 13 01 02 00 04 64 00
+00 00 01 06 00 07 00 00 00 00 00 02 00 00 02 00
+1b 01 00 00 00 01 00 00 13 01 02 00 04 64 00 00
+00 01 06 00 07 00 00 00 00 00 01 00 40 01 01 00
+40 02 06 02 01 00 00 00 64 40 05 04 00 00 00 64
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+00 1d 02 00 00 00 06 80 0f 03 00 1b 01
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+ "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
+ "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+
+<module name="Checker">
+ <module name="TreeWalker">
+ <module name="JavadocType">
+ <property name="scope" value="public" />
+ <property name="allowUnknownTags" value="true" />
+ </module>
+ <module name="JavadocMethod">
+ <property name="scope" value="public" />
+ <property name="allowMissingReturnTag" value="false" />
+ <property name="allowMissingParamTags" value="false" />
+ <property name="allowMissingThrowsTags" value="false" />
+ <property name="allowUndeclaredRTE" value="true"/>
+ </module>
+ </module>
+</module>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+ "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
+ "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+
+<module name="Checker">
+ <module name="TreeWalker">
+ <module name="JavadocType">
+ <property name="scope" value="public" />
+ <property name="allowUnknownTags" value="true" />
+ </module>
+ </module>
+</module>
\ No newline at end of file
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>nps-concepts</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>nps-concepts</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>protocol-parent</artifactId>
+ <version>0.1</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>concepts</artifactId>
+ <description>Basic protocol concepts</description>
+ <packaging>bundle</packaging>
+ <version>1.0</version>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>util</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Import-Package>
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.util,
+ com.google.common.base,
+ com.google.common.collect,
+ com.google.common.net,
+ com.google.common.primitives,
+ com.google.guava;
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.protocol.concepts,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.version}</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>NPS-CONCEPTS Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+ <body>
+ <head>${project.artifactId}</head>
+ <links>
+ <item name="${project.artifactId}" href="index.html"/>
+ </links>
+
+ <menu ref="parent"/>
+
+ <menu ref="reports"/>
+
+
+ </body>
+</project>
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>protocol-parent</artifactId>
+ <version>0.1</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>concepts</artifactId>
+ <description>Basic protocol concepts</description>
+ <packaging>bundle</packaging>
+ <version>1.0</version>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>util</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Import-Package>
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.util,
+ com.google.common.base,
+ com.google.common.collect,
+ com.google.common.net,
+ com.google.common.primitives,
+ com.google.guava;
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.protocol.concepts,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.version}</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>NPS-CONCEPTS Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * Autonomous System (AS) Number. This is an Internet-level concept, where each
+ * AS number identifies an administrative domain.
+ * @see <a href="http://en.wikipedia.org/wiki/Autonomous_System_%28Internet%29">Wikipedia article</a>
+ */
+@Immutable
+public final class ASNumber implements Comparable<ASNumber>, Identifier {
+ /**
+ * AS_TRANS as defined by RFC4893 and RFC6793.
+ */
+ public static final ASNumber TRANS = new ASNumber(23456);
+ private static final long serialVersionUID = 7654204313238963136L;
+ private final int highValue, lowValue;
+
+ /**
+ * Create an AS number representation from a pair of 16bit integers,
+ * representing high/low components, for example as carried in ASDOT+
+ * notation.
+ *
+ * @param highValue Value of high-order 16 bits
+ * @param lowValue Value of low-order 16 bits
+ * @throws
+ * @li IllegalArgumentException when either highValue or lowValue
+ * out of allowed range (0-65535)
+ */
+ public ASNumber(final int highValue, final int lowValue) {
+ if (highValue < 0 || highValue > 65535)
+ throw new IllegalArgumentException("Invalid high-order value");
+ if (lowValue < 0 || lowValue > 65535)
+ throw new IllegalArgumentException("Invalid low-order value");
+
+ this.highValue = highValue;
+ this.lowValue = lowValue;
+ }
+
+ /**
+ * Create an AS number representation from a single integer. The
+ * integer is the 'raw' AS number value, with unsigned 32bit range,
+ * for example as carried in PLAIN notation.
+ *
+ * @param asn Raw AS number
+ * @throws
+ * @li IllegalArgumentException when asn is out of allowed range
+ * (0-4294967295)
+ */
+ public ASNumber(final long asn) {
+ if (asn < 0 || asn > 4294967295L)
+ throw new IllegalArgumentException("Invalid AS number");
+
+ this.highValue = (int) (asn / 65536);
+ this.lowValue = (int) (asn % 65536);
+ }
+
+ /**
+ * Get the AS number as a single integer. For 2-octet AS numbers,
+ * only low 1 bits are used.
+ *
+ * @return Raw AS number
+ */
+ public long getAsn() {
+ return highValue * 65536L + lowValue;
+ }
+
+ /**
+ * Get the high-valued part of the AS number. For 2-octet AS numbers,
+ * this will always be 0.
+ *
+ * @return High-order bits, guaranteed to be in 0-65535 range.
+ */
+ public int getHighValue() {
+ return highValue;
+ }
+
+ /**
+ * Get the low-valued part of the AS number. For 2-octet AS numbers,
+ * this value is equal to the AS number.
+ *
+ * @return Low-order bits, guaranteed to be in 0-65535 range.
+ */
+ public int getLowValue() {
+ return lowValue;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof ASNumber))
+ return false;
+
+ final ASNumber as = (ASNumber)o;
+ return lowValue == as.lowValue && highValue == as.highValue;
+ }
+
+ @Override
+ public int hashCode() {
+ return 7 * lowValue + 13 * highValue;
+ }
+
+ @Override
+ public int compareTo(final ASNumber as) {
+ if (highValue != as.highValue)
+ return highValue - as.highValue;
+ if (lowValue != as.lowValue)
+ return lowValue - as.lowValue;
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Output string is formated according in ASDOT notation.
+ * @see <a href="http://tools.ietf.org/html/rfc5396">RFC5396</a>
+ */
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+
+ if (highValue != 0) {
+ sb.append(highValue);
+ sb.append('.');
+ }
+ sb.append(lowValue);
+ return sb.toString();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.collect.Sets;
+import com.google.common.primitives.UnsignedBytes;
+
+public abstract class AbstractAddressFamily<T extends NetworkAddress<?>> implements AddressFamily<T> {
+ @Override
+ public Set<Prefix<T>> prefixListForBytes(byte[] bytes) {
+ if (bytes.length == 0)
+ return Collections.emptySet();
+
+ final Set<Prefix<T>> list = Sets.newHashSet();
+ int byteOffset = 0;
+ while (byteOffset < bytes.length) {
+ final int bitLength = UnsignedBytes.toInt(ByteArray.subByte(bytes, byteOffset, 1)[0]);
+ byteOffset += 1;
+ final int byteCount = (bitLength % 8 != 0) ? (bitLength / 8) + 1 : bitLength / 8;
+ list.add(prefixForBytes(ByteArray.subByte(bytes, byteOffset, byteCount), bitLength));
+ byteOffset += byteCount;
+ }
+ return list;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Utility class for implementing identifiers. Subclasses need to provide
+ * a byte[] representation of the encapsulated identifier which is unique
+ * in its domain. This class then implements the required interfaces.
+ *
+ * @param <T> template parameter reference to subclass
+ */
+public abstract class AbstractIdentifier<T extends AbstractIdentifier<?>> implements Comparable<T>, Identifier {
+ private static final long serialVersionUID = 7024836009610553163L;
+
+ /**
+ * Get raw identifier bytes. Override this method to provide the base
+ * class with a raw representation of your identifier. This is then
+ * used in calculations.
+ *
+ * @return Bytearray representation of the identifier
+ */
+ abstract protected byte[] getBytes();
+
+ abstract protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper);
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(this.getBytes());
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o)
+ return true;
+ if (o == null)
+ return false;
+
+ if (this.getClass().equals(o.getClass())
+ && o instanceof AbstractIdentifier<?>)
+ return Arrays.equals(this.getBytes(),
+ ((AbstractIdentifier<?>) o).getBytes());
+ return false;
+ }
+
+ @Override
+ public int compareTo(final T id) {
+ boolean assignable = this.getClass().isAssignableFrom(id.getClass());
+ if (assignable == false) {
+ throw new IllegalArgumentException("Object " + id + " is not assignable to " + getClass());
+ }
+
+ final byte[] myb = this.getBytes();
+ final byte[] idb = id.getBytes();
+
+ for (int i = 0; i < idb.length && i < myb.length; ++i) {
+ if (myb[i] != idb[i])
+ return myb[i] - idb[i];
+ }
+
+ if (idb.length != myb.length)
+ return myb.length - idb.length;
+
+ return 0;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+/**
+ * Abstract helper class for metrics which are based on integral values,
+ * with numberically lower numbers being considered better candidates.
+ *
+ * @param <T> template reference to subclass
+ */
+public abstract class AbstractMetric<T extends AbstractMetric<?>> implements Metric<T> {
+ private static final long serialVersionUID = 4404624006216930524L;
+ private final long value;
+
+ protected AbstractMetric(final long value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the metric value.
+ *
+ * @return Metric value
+ */
+ public long getValue() {
+ return value;
+ }
+
+ @Override
+ public int compareTo(final T other) {
+ if (value < other.getValue())
+ return -1;
+ if (value > other.getValue())
+ return 1;
+ return 0;
+ }
+
+ @Override
+ public final int hashCode() {
+ return (int)value;
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (obj.getClass() != this.getClass())
+ return false;
+ return value == ((AbstractMetric<?>)obj).getValue();
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+/**
+ * Abstract base class for implementing Prefix classes. This class correctly
+ * implements all required methods, so to implement a Prefix class, you
+ * only need to subclass it and publish an appropriate contructor.
+ *
+ * @param <T> template parameter reference to subclass
+ */
+public abstract class AbstractPrefix<T extends NetworkAddress<T>> implements Comparable<AbstractPrefix<T>>, Prefix<T> {
+
+ private static final long serialVersionUID = -384546010175152481L;
+
+ private final T address;
+ private final int length;
+
+ /**
+ * Create a new prefix object.
+ *
+ * @param address Base network address
+ * @param length Length of significant part of address, in bits
+ */
+ protected AbstractPrefix(final T address, final int length) {
+ this.address = address.applyMask(length);
+ this.length = length;
+ }
+
+ @Override
+ public T getAddress() {
+ return this.address;
+ }
+
+ @Override
+ public int getLength() {
+ return this.length;
+ }
+
+ @Override
+ public int compareTo(final AbstractPrefix<T> p) {
+ final int i = this.address.compareTo(p.getAddress());
+ if (i != 0)
+ return i;
+ if (this.length < p.getLength())
+ return -1;
+ if (this.length > p.getLength())
+ return 1;
+ return 0;
+ }
+
+ @Override
+ public boolean contains(final NetworkAddress<?> address) {
+ /*
+ * Fastest way of checking this is to apply this prefixe's
+ * mask and check for equality.
+ */
+ final NetworkAddress<?> masked = address.applyMask(this.length);
+ return this.address.equals(masked);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Returned string will be in the CIDR format.
+ */
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder(this.address.toString());
+ sb.append('/');
+ sb.append(this.length);
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final AbstractPrefix<?> other = (AbstractPrefix<?>) obj;
+ if (this.address == null) {
+ if (other.address != null)
+ return false;
+ } else if (!this.address.equals(other.address))
+ return false;
+ if (this.length != other.length)
+ return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.address == null) ? 0 : this.address.hashCode());
+ result = prime * result + this.length;
+ return result;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.util.Set;
+
+/**
+ * Interface marking an Address Family concept. An address family defines
+ * a NetworkAddress type, corresponding Prefix type as well as their textual
+ * representations.
+ *
+ * @param <T> Network Address type
+ */
+public interface AddressFamily<T extends NetworkAddress<?>> {
+ /**
+ * Attempt to parse an address from a string.
+ *
+ * @param string String representation of the address
+ * @return A network address instance
+ * @throws IllegalArgumentException if string is null or does not conform
+ * to address encoding rules.
+ */
+ public T addressForString(String string);
+
+ /**
+ * Attempt to parse a parse from a string.
+ *
+ * @param string String representation of the prefix
+ * @return A prefix instance
+ * @throws IllegalArgumentException if string is null or does not conform
+ * to prefix encoding rules.
+ * @throws NumberFormatException if the prefix length is not a parseable
+ * number.
+ */
+ public Prefix<T> prefixForString(String string);
+
+ /**
+ * Create a network address from a its byte representation.
+ *
+ * @param bytes address as a byte array
+ * @return {@link NetworkAddress}
+ * @throws IllegalArgumentException if the provided byte array
+ * does not conform to address formatting rules
+ */
+ public T addressForBytes(byte[] bytes);
+
+ /**
+ * Parse a byte array into a Prefix of specified length
+ *
+ * @param bytes array to be parsed to a Prefix
+ * @param bitLength
+ * length of the prefix in bits, to be given as parameter when
+ * initializing a Prefix
+ * @return new Prefix
+ */
+ public Prefix<T> prefixForBytes(byte[] bytes, int bitLength);
+
+ /**
+ * Parse given byte array to a list of prefixes.
+ *
+ * @param bytes byte array to be parsed.
+ * @return list of prefixes, if bytes is empty, returns empty list.
+ */
+ public Set<? extends Prefix<T>> prefixListForBytes(byte[] bytes);
+
+ /**
+ * Returns the number of bytes required for successful address
+ * reconstruction via {@link addressForBytes}
+ *
+ * @return number of bytes required
+ */
+ public int requiredBytes();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Bandwidth concept class. It represents network bandwidth in bytes per second.
+ * The precision of this class is limited to single-precision floating-point.
+ */
+@Immutable
+public final class Bandwidth implements Comparable<Bandwidth>, Serializable {
+ public static final Bandwidth ZERO = new Bandwidth(0);
+ private static final long serialVersionUID = 5795612451568505103L;
+ private final double bytesPerSecond;
+
+ /**
+ * Constructor of {@link Bandwidth} object.
+ * @param bytesPerSecond Bandwidth capacity, expressed as bytes per second
+ */
+ public Bandwidth(final double bytesPerSecond) {
+ this.bytesPerSecond = bytesPerSecond;
+ }
+
+ /**
+ * Standard getter for bytesPerSecond attribute of {@link Bandwidth}.
+ * @return bytesPerSecond Bandwidth capacity, expressed as bytes per second
+ */
+ public double getBytesPerSecond() {
+ return bytesPerSecond;
+ }
+
+ /**
+ * Standard getter for bitsPerSecond attribute of {@link Bandwidth}.
+ * @return bitsPerSecond Bandwidth capacity, expressed as bytes per second
+ */
+ public long getBitsPerSecond() {
+ return (long) (8 * bytesPerSecond);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ long temp;
+ temp = Double.doubleToLongBits(bytesPerSecond);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Bandwidth other = (Bandwidth) obj;
+ if (Double.doubleToLongBits(bytesPerSecond) != Double
+ .doubleToLongBits(other.bytesPerSecond))
+ return false;
+ return true;
+ }
+
+ @Override
+ public int compareTo(final Bandwidth b) {
+ if (bytesPerSecond < b.bytesPerSecond)
+ return -1;
+ if (bytesPerSecond > b.bytesPerSecond)
+ return 1;
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("Bandwidth [bytesPerSecond=");
+ sb.append(bytesPerSecond);
+ sb.append(']');
+ return sb.toString();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+/**
+ * Interior Gateway Protocol metric class.
+ */
+public final class IGPMetric extends AbstractMetric<IGPMetric> {
+ private static final long serialVersionUID = -401875021705133799L;
+
+ /**
+ * Construct a new IGP metric object.
+ *
+ * @param value Metric value
+ * @throws IllegalArgumentException ex when value is outside of allowed
+ * range (0-16777215)
+ */
+ public IGPMetric(final long value) {
+ super(value);
+ if (value < 0 || value > 16777215)
+ throw new IllegalArgumentException("Invalid IGP metric value");
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.protocol.concepts.AddressFamily;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.net.InetAddresses;
+
+/**
+ * Utility class for dealing with various IP-based network addresses.
+ */
+public final class IPAddresses {
+ /**
+ * A set containing all IP address families.
+ */
+ public static final Set<AddressFamily<?>> FAMILIES;
+
+ static {
+ FAMILIES = new HashSet<>(2);
+ FAMILIES.add(IPv4.FAMILY);
+ FAMILIES.add(IPv6.FAMILY);
+ }
+
+ private IPAddresses() { }
+
+ /**
+ * Instantiate a network address from its string representation.
+ *
+ * @param string string representation
+ * @return network address parsed from the string
+ * @throws IllegalArgumentException if the string failed to parse
+ * into any of the supported classes.
+ */
+ public static NetworkAddress<?> parseNetworkAddress(final String string) {
+ final InetAddress a = InetAddresses.forString(string);
+ if (a instanceof Inet4Address)
+ return new IPv4Address(a);
+ if (a instanceof Inet6Address)
+ return new IPv6Address(a);
+ throw new IllegalArgumentException("Unsupported network address");
+ }
+
+ public static NetworkAddress<?> createNetworkAddress(InetAddress inetAddress) {
+ checkNotNull(inetAddress);
+ if (inetAddress instanceof Inet4Address) {
+ return new IPv4Address(inetAddress);
+ } else if (inetAddress instanceof Inet6Address) {
+ return new IPv6Address(inetAddress);
+ } else {
+ throw new IllegalStateException("Unknown InetAddress " + inetAddress);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Preconditions;
+import com.google.common.net.InetAddresses;
+
+public final class IPv4 extends AbstractAddressFamily<IPv4Address> {
+ private static final Pattern regex = Pattern.compile("/");
+ public static final Set<AddressFamily<?>> FAMILIES;
+ public static final IPv4 FAMILY;
+
+ static {
+ FAMILY = new IPv4();
+ FAMILIES = new HashSet<>(1);
+ FAMILIES.add(FAMILY);
+ }
+
+ private IPv4() { }
+
+ @Override
+ public IPv4Address addressForString(final String string) {
+ Preconditions.checkNotNull(string, "String may not be null");
+ return new IPv4Address(InetAddresses.forString(string));
+ }
+
+ @Override
+ public IPv4Prefix prefixForString(final String string) {
+ Preconditions.checkNotNull(string, "String may not be null");
+
+ final String[] strs = regex.split(string);
+ Preconditions.checkArgument(strs.length == 2, "Malformed prefix string");
+ final byte len = Byte.valueOf(strs[1]);
+ Preconditions.checkArgument(len >= 0 && len <= 32, "Prefix length has to be in range 0-32");
+ return addressForString(strs[0]).asPrefix(len);
+ }
+
+ @Override
+ public IPv4Address addressForBytes(byte[] bytes) {
+ return new IPv4Address(bytes);
+ }
+
+ @Override
+ public int requiredBytes() {
+ return 4;
+ }
+
+ @Override
+ public IPv4Prefix prefixForBytes(byte[] bytes, int bitLength) {
+ Preconditions.checkArgument(bytes.length <= 4, "Byte array too large");
+ Preconditions.checkArgument(bitLength <= 32, "Bitlength too large");
+
+ if (bytes.length != 4)
+ bytes = Arrays.copyOf(bytes, 4);
+
+ return addressForBytes(bytes).asPrefix(bitLength);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Preconditions;
+
+/**
+ * This class represents an IPv4 address. This is the well-known 4-byte address
+ * used all over the Internet. The difference between this class and the
+ * readily-available Inet4Address is the fact it is derived from a well-known
+ * concept and it is a pure data holder.
+ */
+public class IPv4Address implements NetworkAddress<IPv4Address> {
+ private static final long serialVersionUID = -5856802567090053919L;
+ private final byte[] bytes;
+
+ /**
+ * Instantiate a new IPv4Address based on raw byte representation.
+ *
+ * @param bytes Bytearray holding the byte representation
+ * @throws
+ * @li IllegalArgumentException when length of bytes is not 4
+ */
+ public IPv4Address(final byte[] bytes) {
+ Preconditions.checkNotNull(bytes);
+ Preconditions.checkArgument(bytes.length == 4);
+ this.bytes = bytes;
+ }
+
+ /**
+ * Instantiate a new IPv4Address based on the contents of a Inet4Address.
+ *
+ * @param address
+ * IPv4 address in Inet4Address format
+ * @throws
+ * @li IllegalArgumentException when address is not in Inet4Address format
+ */
+ public IPv4Address(final InetAddress address) {
+ if (!(address instanceof Inet4Address))
+ throw new IllegalArgumentException(
+ "This class can only handle IPv4 addresses");
+ this.bytes = address.getAddress();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ return o instanceof IPv4Address
+ && Arrays.equals(this.bytes, ((IPv4Address) o).bytes);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(this.bytes);
+ }
+
+ @Override
+ public byte[] getAddress() {
+ return this.bytes;
+ }
+
+ @Override
+ public int compareTo(final IPv4Address addr) {
+ for (int i = 0; i < this.bytes.length; ++i) {
+ if (this.bytes[i] != addr.bytes[i]) {
+ int i1 = 0, i2 = 0;
+ i1 = this.bytes[i] < 0 ? this.bytes[i] + 256 : this.bytes[i];
+ i2 = addr.bytes[i] < 0 ? addr.bytes[i] + 256 : addr.bytes[i];
+ return i1 - i2;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Output string is formated according to InetAddress formatting rules.
+ */
+ @Override
+ public String toString() {
+ try {
+ return InetAddress.getByAddress(Arrays.copyOf(this.bytes, 4))
+ .getHostAddress();
+ } catch (final UnknownHostException e) {
+ throw new RuntimeException("Unexpected malformed address", e);
+ }
+ }
+
+ @Override
+ public IPv4Address applyMask(final int bits) {
+ if (bits < 0 || bits > 32)
+ throw new IllegalArgumentException("Bit length has to be in range 0-32");
+ return new IPv4Address(ByteArray.maskBytes(this.bytes, bits));
+ }
+
+ @Override
+ public IPv4Prefix asPrefix(int length) {
+ return new IPv4Prefix(this, length);
+ }
+
+ @Override
+ public IPv4Prefix asHostPrefix() {
+ return asPrefix(32);
+ }
+
+ @Override
+ public IPv4 getAddressFamily() {
+ return IPv4.FAMILY;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+/**
+ * IPv4 Address prefix.
+ */
+public class IPv4Prefix extends AbstractPrefix<IPv4Address> {
+
+ private static final long serialVersionUID = 2206353300109616995L;
+
+ /**
+ * Construct an IPv4 prefix given a base IPv4 address and prefix
+ * length.
+ *
+ * @param address Base address
+ * @param length Prefix length, as to be between 0-32.
+ */
+ public IPv4Prefix(final IPv4Address address, final int length) {
+ super(address, length);
+ }
+
+ @Override
+ public IPv4 getAddressFamily() {
+ return IPv4.FAMILY;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Preconditions;
+import com.google.common.net.InetAddresses;
+
+public final class IPv6 extends AbstractAddressFamily<IPv6Address> {
+ private static final Pattern regex = Pattern.compile("/");
+ public static final Set<AddressFamily<?>> FAMILIES;
+ public static final IPv6 FAMILY;
+
+ static {
+ FAMILY = new IPv6();
+ FAMILIES = new HashSet<>(1);
+ FAMILIES.add(FAMILY);
+ }
+
+ private IPv6() { }
+
+ @Override
+ public IPv6Address addressForString(final String string) {
+ Preconditions.checkNotNull(string, "String may not be null");
+ return new IPv6Address(InetAddresses.forString(string));
+ }
+
+ @Override
+ public IPv6Prefix prefixForString(final String string) {
+ Preconditions.checkNotNull(string, "String may not be null");
+
+ final String[] strs = regex.split(string);
+ final byte len = Byte.valueOf(strs[1]);
+ Preconditions.checkArgument(len >= 0 && len <= 128, "Prefix length has to be in range 0-128");
+ return addressForString(strs[0]).asPrefix(len);
+ }
+
+ @Override
+ public IPv6Address addressForBytes(byte[] bytes) {
+ return new IPv6Address(bytes);
+ }
+
+ @Override
+ public int requiredBytes() {
+ return 16;
+ }
+
+ @Override
+ public IPv6Prefix prefixForBytes(byte[] bytes, int bitLength) {
+ Preconditions.checkArgument(bytes.length <= 16, "Byte array too large");
+ Preconditions.checkArgument(bitLength <= 128, "Bitlength too large");
+
+ if (bytes.length != 16)
+ bytes = Arrays.copyOf(bytes, 16);
+
+ return addressForBytes(bytes).asPrefix(bitLength);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Preconditions;
+
+/**
+ * This class represents an IPv6 address. This is the well-known 16-byte address
+ * used all over the Internet. The difference between this class and the
+ * readily-available Inet6Address is the fact it is derived from a well-known
+ * concept and it is a pure data holder.
+ */
+public class IPv6Address implements NetworkAddress<IPv6Address> {
+ private static final long serialVersionUID = 8627230318476805811L;
+ private final byte[] bytes;
+
+ /**
+ * Instantiate a new IPv6Address based on raw byte representation.
+ *
+ * @param bytes Bytearray holding the byte representation
+ * @throws
+ * @li IllegalArgumentException when length of bytes is not 16
+ */
+ public IPv6Address(final byte[] bytes) {
+ Preconditions.checkNotNull(bytes);
+ Preconditions.checkArgument(bytes.length == 16);
+ this.bytes = bytes;
+ }
+
+ /**
+ * Instantiate a new IPv6Address based on the contents of a Inet6Address.
+ *
+ * @param address
+ * IPv6 address in Inet6Address format
+ * @throws
+ * @li IllegalArgumentException when address is not in Inet6Address format
+ */
+ public IPv6Address(final InetAddress address) {
+ if (!(address instanceof Inet6Address))
+ throw new IllegalArgumentException(
+ "This class can only handle IPv6 addresses");
+ this.bytes = address.getAddress();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ return o instanceof IPv6Address
+ && Arrays.equals(this.bytes, ((IPv6Address) o).bytes);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(this.bytes);
+ }
+
+ @Override
+ public byte[] getAddress() {
+ return this.bytes;
+ }
+
+ @Override
+ public int compareTo(final IPv6Address addr) {
+ for (int i = 0; i < this.bytes.length; ++i) {
+ if (this.bytes[i] != addr.bytes[i]) {
+ int i1 = 0, i2 = 0;
+ i1 = this.bytes[i] < 0 ? this.bytes[i] + 256 : this.bytes[i];
+ i2 = addr.bytes[i] < 0 ? addr.bytes[i] + 256 : addr.bytes[i];
+ return i1 - i2;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Output string is formated according to InetAddress formatting rules.
+ */
+ @Override
+ public String toString() {
+ try {
+ return InetAddress.getByAddress(Arrays.copyOf(this.bytes, 16))
+ .getHostAddress();
+ } catch (final UnknownHostException e) {
+ throw new RuntimeException("Unexpected malformed address", e);
+ }
+ }
+
+ @Override
+ public IPv6Address applyMask(final int bits) {
+ if (bits < 0 || bits > 128)
+ throw new IllegalArgumentException("Bit length has to be in range 0-128");
+ return new IPv6Address(ByteArray.maskBytes(this.bytes, bits));
+ }
+
+ @Override
+ public IPv6Prefix asPrefix(int length) {
+ return new IPv6Prefix(this, length);
+ }
+
+ @Override
+ public IPv6Prefix asHostPrefix() {
+ return asPrefix(128);
+ }
+
+ @Override
+ public IPv6 getAddressFamily() {
+ return IPv6.FAMILY;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * IPv6 Address prefix.
+ */
+@Immutable
+public class IPv6Prefix extends AbstractPrefix<IPv6Address> {
+ private static final long serialVersionUID = 8936908223539148352L;
+
+ /**
+ * Create a new IPv6 prefix using an IPv6 address and prefix
+ * length.
+ *
+ * @param address IPv6 address {@link IPv6Address}
+ * @param length Prefix length
+ */
+ public IPv6Prefix(final IPv6Address address, final int length) {
+ super(address, length);
+ }
+
+ @Override
+ public IPv6 getAddressFamily() {
+ return IPv6.FAMILY;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Object representing an ISO System identifier. It is the 6-byte system ID portion of the IS-IS network service access
+ * point (NSAP).
+ */
+public final class ISOSystemIdentifier extends AbstractIdentifier<ISOSystemIdentifier> {
+ private static final long serialVersionUID = 4493531385611530076L;
+ private final byte[] systemId;
+
+ /**
+ * Initialize a new ISO system identifier.
+ *
+ * @param systemId 6-byte identifier
+ * @throws
+ * @li IllegalArgumentException if the length of supplied systemId is not 6 bytes
+ */
+ public ISOSystemIdentifier(final byte[] systemId) {
+ if (systemId.length != 6)
+ throw new IllegalArgumentException("Invalid ISO System ID");
+ this.systemId = systemId;
+ }
+
+ @Override
+ public byte[] getBytes() {
+ return this.systemId;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("id", ByteArray.toHexString(this.systemId, "."));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+/**
+ * General identifier interface. It is primarily a marker for all things that
+ * identify concepts -- such as names, addresses, classes, etc. We do not
+ * require too much, just that the identifiers are serializable (and this
+ * transferable).
+ */
+public interface Identifier extends Serializable {
+
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+/**
+ * Marker interface for objects which are immutable. This interface should be used directly on objects, preferably
+ * final, which are eligible for the JSR-305 @Immutable annotation and objects implementing this interface are required
+ * to abide to interface contract specified by @Immutable. The reason for the existence of this interface is twofold:
+ * unlike @Immutable, it is visible at runtime and objects can be quickly checked for compliance using a quick
+ * 'instanceof' check. This is useful for code which needs to capture a point-in-time snapshot of otherwise unknown
+ * objects -- a typical example being logging/tracing systems. Such systems would normally have to rely on serializing
+ * the object to get a stable checkpoint. Objects marked with this interface are guaranteed to remain stable, thus
+ * already being a checkpoint for all intents and purposes, so aside from retaining a reference no further action on
+ * them is necessary.
+ */
+public interface Immutable {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.util.EventListener;
+import java.util.List;
+
+public final class InitialListenerEvents<L extends EventListener, E> {
+ private final ListenerRegistration<L> registration;
+ private final List<E> events;
+
+ public InitialListenerEvents(final ListenerRegistration<L> registration, final List<E> events) {
+ super();
+ if (registration == null)
+ throw new NullPointerException("Registration is mandatory!");
+ this.registration = registration;
+ if (events == null)
+ throw new NullPointerException("Events are mandatory!");
+ this.events = events;
+ }
+
+ /**
+ * @return the registration
+ */
+ public ListenerRegistration<L> getRegistration() {
+ return this.registration;
+ }
+
+ /**
+ * @return the events
+ */
+ public List<E> getEvents() {
+ return this.events;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Closeable;
+import java.util.EventListener;
+
+/**
+ * An interface representing a listener registration. Objects offering
+ * the ability to register listener should return an implementation of this
+ * interface upon successful registration. The users are required to call
+ * #close() before losing the reference to that object.
+ *
+ * @param <T> template reference to associated EventListener implementation
+ */
+public interface ListenerRegistration<T extends EventListener> extends Closeable {
+ /**
+ * Access the listener object associated with this registration.
+ *
+ * @return Associated listener.
+ */
+ public T getListener();
+
+ @Override
+ public void close();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+/**
+ * Interface defining the concept of a metric. Metrics are something which
+ * defines preference of an object when used in a certain context. In that
+ * sense we define total ordering of metrics in the same class.
+ *
+ * @param <T> subtype of Metric
+ */
+public interface Metric<T extends Metric<?>> extends Comparable<T>, Serializable {
+ /**
+ * {@inheritDoc}
+ *
+ * Metrics which compare as 'lower' using this method are to be
+ * considered better candidates than the other metric.
+ */
+ @Override
+ public int compareTo(T o);
+
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+/**
+ * General interface for identifyiable objects. Useful when you have an object
+ * which has a sense of identity -- by having a "name".
+ *
+ * @param <T> template reference to the object name's Identifier class
+ */
+public interface NamedObject<T extends Identifier> {
+ /**
+ * Get the object's Identifier (or "name"). A name uniquely identifies
+ * an object among its peers. Two named objects can have the same
+ * identifier, but need not necessarily be equal.
+ *
+ * @return The object's identifier
+ */
+ public T getName();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * Generic identifier of a network entity. A network entity is typically a
+ * host. Hosts may be contained within a network -- which is represented by
+ * a @sa Prefix. To support operation within the context of a prefix,
+ * NetworkAddresses have to support a concept of 'masking', where all bits
+ * beyond first <n> bit are set to 0 and any bytes are trimmed.
+ *
+ * @param <T> subtype of Network Address
+ */
+public interface NetworkAddress<T extends NetworkAddress<?>> extends Comparable<T>, Identifier {
+ /**
+ * Returns the raw address of this object. The result is in network
+ * byte order: the highest order byte of the address is in
+ * getAddress()[0].
+ *
+ * @return the raw address of this object, guaranteed to be non-null
+ */
+ public byte[] getAddress();
+
+ /**
+ * Apply a mask of first #bits, setting the rest to zero.
+ *
+ * @param bits Number of bits to keep in place. Has to be
+ * non-negative.
+ * @return A new NetworkAddress instance.
+ */
+ public T applyMask(int bits);
+
+ /**
+ * Convert the address into a prefix of specified length.
+ *
+ * @param length Prefix length
+ * @return A prefix representation of this address.
+ */
+ public Prefix<T> asPrefix(int length);
+
+ /**
+ * Convert the address into a host prefix, e.g. a prefix with length
+ * equal to the address bitsize.
+ *
+ * @return A prefix representation of this address.
+ */
+ public Prefix<T> asHostPrefix();
+
+ /**
+ * Returns the address family class.
+ *
+ * @return address family class
+ */
+ public AddressFamily<T> getAddressFamily();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * A network prefix object. Prefix is a networking concept grouping together
+ * a set of addresses into a 'subnet', such that their attributes can be easily
+ * expressed. A prefix is formed by a base NetworkAddress and number of leading
+ * bits which are considered significant. An address is considered to be a part
+ * of a prefix if it differes only in insignificant (right-most) bits.
+ *
+ * @param <T> template reference to a Network Address class
+ */
+public interface Prefix<T extends NetworkAddress<?>> extends Identifier {
+ /**
+ * Get the base address of the prefix.
+ *
+ * @return Base network address
+ */
+ public T getAddress();
+
+ /**
+ * The the length of significant part of the base address.
+ *
+ * @return Prefix length
+ */
+ public int getLength();
+
+ /**
+ * Check if a Prefix contains a particular network address.
+ *
+ * @param address Network address to check for membership
+ * @return true if address belongs to this subnet, false otherwise
+ */
+ public boolean contains(NetworkAddress<?> address);
+
+ /**
+ * Returns the address family class.
+ *
+ * @return address family class
+ */
+ public AddressFamily<T> getAddressFamily();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+
+/**
+ * Class representing a Shared Risk Link Group identifier. A link may be
+ * part of multiple such groups. Membership in such a group indicates that
+ * members share a common risk (such as single wire, etc.).
+ */
+public class SharedRiskLinkGroup implements Comparable<SharedRiskLinkGroup>, Identifier {
+ private static final long serialVersionUID = -760766663668819360L;
+ private final long value;
+
+ /**
+ * Create a new group with a particular value. Valid values are in
+ * the range of 0-4294967295. Two groups with the same value are
+ * considered equal.
+ * @param value SRLG value
+ */
+ public SharedRiskLinkGroup(final long value) {
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid SRLG value");
+ this.value = value;
+ }
+
+ /**
+ * Returns value attribute of {@link SharedRiskLinkGroup}.
+ * @return value of {@link SharedRiskLinkGroup}
+ */
+ public long getValue() {
+ return value;
+ }
+
+ @Override
+ public int compareTo(final SharedRiskLinkGroup other) {
+ if (value < other.value)
+ return -1;
+ if (value > other.value)
+ return 1;
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (value ^ (value >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof SharedRiskLinkGroup))
+ return false;
+ final SharedRiskLinkGroup other = (SharedRiskLinkGroup) obj;
+ if (value != other.value)
+ return false;
+ return true;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.io.Serializable;
+
+/**
+ * Interface identifying a piece of state information. Implementations of this interface are required to be immutable.
+ * It is also recommended for the projects to be eligible (and carry) the @Immutable JSR-305 annotation.
+ */
+public interface State extends Immutable, Serializable {
+ /**
+ * Report a string representation of the state. The interface contract of this method, unlike its normal Object
+ * ancestor, its return value must be consistent with the equals() method, such that the following always holds:
+ *
+ * o1.toString().equals(o2.toString()) == o1.equals(o2)
+ *
+ * @return String representation of the state information
+ */
+ @Override
+ public String toString();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+/**
+ * Interface marking object which hold some state, which can be captured and saved. Capturing this state is useful for
+ * various entities which need to see a consistent, point-in-time view of the state.
+ *
+ * @param <T> Type reference of the returned state object
+ */
+public interface Stateful<T extends State> {
+ /**
+ * Return a reference to the current state of the object. The returned object must remain immutable throughout its
+ * lifetime. Furthermore using equals() on two state objects returned from this method must return true if and only
+ * if the internal state of this object the the two points was equivalent.
+ *
+ * @return Reference to a point-in-time consistent state of the object.
+ */
+ public T currentState();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Traffic Engineering metric class.
+ */
+@Immutable
+public final class TEMetric extends AbstractMetric<TEMetric> {
+ private static final long serialVersionUID = -6843828299489991771L;
+
+ /**
+ * Construct a new TE metric object.
+ *
+ * @param value Metric value
+ * @throws IllegalArgumentException ex when value is outside of allowed
+ * range (0-4294967295)
+ */
+ public TEMetric(final long value) {
+ super(value);
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid TE metric value");
+ }
+}
+
--- /dev/null
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+ <body>
+ <head>${project.artifactId}</head>
+ <links>
+ <item name="${project.artifactId}" href="index.html"/>
+ </links>
+
+ <menu ref="parent"/>
+
+ <menu ref="reports"/>
+
+
+ </body>
+</project>
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class ASNumberTest {
+ private ASNumber asn1, asn2, asn3, asn4;
+
+ @Before
+ public void setUp() {
+ asn1 = new ASNumber(100, 200);
+ asn2 = new ASNumber(6553800);
+ asn3 = new ASNumber(0, 200);
+ asn4 = new ASNumber(100, 199);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testHighValueUnderflow() {
+ new ASNumber(-1, 0);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testHighValueOverflow() {
+ new ASNumber(65536, 0);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testLowValueUnderflow() {
+ new ASNumber(0, -1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testLowValueOverflow() {
+ new ASNumber(0, 65536);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testAsnUnderflow() {
+ new ASNumber(0, -1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testAsnOverflow() {
+ new ASNumber(4294967296L);
+ }
+
+ @Test
+ public void testHashCode() {
+ final Set<ASNumber> set = new HashSet<ASNumber>();
+
+ set.add(asn1);
+ assertEquals(1, set.size());
+
+ set.add(asn2);
+ assertEquals(1, set.size());
+
+ set.add(asn3);
+ assertEquals(2, set.size());
+ }
+
+ @Test
+ public void testCompareTo() {
+ final Set<ASNumber> set = new TreeSet<ASNumber>();
+
+ set.add(asn1);
+ assertEquals(1, set.size());
+
+ set.add(asn2);
+ assertEquals(1, set.size());
+
+ set.add(asn3);
+ assertEquals(2, set.size());
+
+ set.add(asn4);
+ assertEquals(3, set.size());
+ }
+
+ @Test
+ public void testGetters() {
+ assertEquals(100, asn1.getHighValue());
+ assertEquals(200, asn1.getLowValue());
+ assertEquals(6553800, asn1.getAsn());
+ }
+
+ @Test
+ public void testEquals() {
+ assertThat(asn1, equalTo(asn2));
+ assertThat(asn1, not(equalTo(asn3)));
+ assertThat(asn1, not(equalTo(asn4)));
+ assertThat(asn1, not(equalTo(new Object())));
+ assertFalse(asn1.equals(new Object()));
+ }
+
+ @Test
+ public void testToString() {
+ assertEquals("100.200", asn1.toString());
+ assertEquals("200", asn3.toString());
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+public class AbstractIdentifierTest {
+
+ private class AbstractIdentifierT extends AbstractIdentifier<AbstractIdentifierT> {
+
+ private static final long serialVersionUID = 3803643153695225193L;
+
+ public byte[] bytes;
+
+ public AbstractIdentifierT(final byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ protected byte[] getBytes() {
+ return this.bytes;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("bytes", ByteArray.toHexString(bytes, "."));
+ }
+ }
+
+ @Test
+ public void testToString() {
+ final AbstractIdentifier<AbstractIdentifierT> ai = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 168, 31, 8});
+
+ assertEquals("AbstractIdentifierT{bytes=ac.a8.1f.08}", ai.toString());
+ }
+
+
+ @Test
+ public void testCompareTo() {
+ final AbstractIdentifier<AbstractIdentifierT> a1 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 168, 31, 8});
+ final AbstractIdentifier<AbstractIdentifierT> a2 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 167, 31, 8});
+ final AbstractIdentifier<AbstractIdentifierT> a4 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 167});
+
+ assertEquals(0, a1.compareTo((AbstractIdentifierT) a1));
+ assertEquals(-1, a2.compareTo((AbstractIdentifierT) a1));
+ assertEquals(1, a1.compareTo((AbstractIdentifierT) a2));
+
+ final AbstractIdentifier<AbstractIdentifier<?>> a3 = new AbstractIdentifier<AbstractIdentifier<?>>() {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected byte[] getBytes() {
+ return null;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper;
+ }
+ };
+
+ try {
+ a3.compareTo(a1);
+ fail("Exception should have occured.");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Object " + a1 + " is not assignable to " + a3.getClass() , e.getMessage());
+ }
+
+ assertEquals(2, a2.compareTo((AbstractIdentifierT) a4));
+ }
+
+ @Test
+ public void testHashCodeEquals() {
+ final AbstractIdentifier<AbstractIdentifierT> a1 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 168, 31, 8});
+ final AbstractIdentifier<AbstractIdentifierT> a2 = new AbstractIdentifierT(new byte[] {(byte) 172, (byte) 167, 31, 8});
+
+ assertNotSame(a1.hashCode(), a2.hashCode());
+ assertFalse(a1.equals(a2));
+ assertEquals(a1, a1);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Test;
+
+public class AddressFamiliesTest {
+ @Test
+ public void testParseIpv4Prefix() throws UnknownHostException {
+ final byte[] pref = new byte[] { (byte) 172, 17, 2 };
+ final Prefix<?> after = IPv4.FAMILY.prefixForBytes(pref, 24);
+ final Prefix<IPv4Address> expected = new IPv4Prefix(new IPv4Address(InetAddress.getByName("172.17.2.0")), 24);
+ assertEquals(expected, after);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseIpv4Prefix2(){
+ IPv4.FAMILY.prefixForBytes(new byte[5], 20);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseIpv4Prefix3(){
+ IPv4.FAMILY.prefixForBytes(new byte[] { (byte) 172, 17, 2 }, 33);
+ }
+
+ @Test
+ public void testParseIpv6Prefix() throws UnknownHostException {
+ final byte[] pref = new byte[] { (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x02 };
+ final Prefix<?> after =IPv6.FAMILY.prefixForBytes(pref, 64);
+ final Prefix<IPv6Address> expected = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:1:2::")), 64);
+ assertEquals(expected, after);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseIpv6Prefix2(){
+ IPv4.FAMILY.prefixForBytes(new byte[17], 30);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseIpv6Prefix3(){
+ IPv4.FAMILY.prefixForBytes(new byte[] { (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x02 }, 129);
+ }
+
+ @Test
+ public void testParseIpv6PrefixList(){
+ assertTrue(IPv6.FAMILY.prefixListForBytes(new byte[0]).isEmpty());
+ }
+
+ @Test
+ public void testParseIpv6PrefixList2(){
+ assertEquals(2, IPv6.FAMILY.prefixListForBytes(new byte[] { (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, (byte) 0x00, (byte) 0x01, (byte) 0x00, }).size());
+ }
+
+ @Test
+ public void testParseIpv4PrefixList(){
+ assertTrue(IPv4.FAMILY.prefixListForBytes(new byte[0]).isEmpty());
+ }
+
+ @Test
+ public void testParseIpv4PrefixList2(){
+ assertFalse(IPv4.FAMILY.prefixListForBytes(new byte[] { (byte) 15, 17, 2 }).isEmpty());
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class BandwidthTest {
+ private Bandwidth b1, b2, b3, b4;
+
+ @Before
+ public void setUp() {
+ b1 = new Bandwidth(1000);
+ b2 = new Bandwidth(2000);
+ b3 = new Bandwidth(2000);
+ b4 = new Bandwidth(100);
+ }
+
+ @Test
+ public void testBitsBytes() {
+ assertEquals(8000, b1.getBitsPerSecond());
+ assertEquals(1000.0, b1.getBytesPerSecond(), 0.1);
+ }
+
+ @Test
+ public void testEquals() {
+ assertFalse(b1.equals(null));
+ assertThat(b1, not(equalTo(new Object())));
+ assertThat(b1, equalTo(b1));
+ assertThat(b1, not(equalTo(b2)));
+ assertThat(b2, equalTo(b3));
+ assertFalse(b1.equals(new Object()));
+ }
+
+ @Test
+ public void testToString(){
+ String s1 = "Bandwidth [bytesPerSecond=" + b1.getBytesPerSecond() + "]";
+ assertEquals(s1, b1.toString());
+
+ }
+
+ @Test
+ public void testHashCode() {
+ final Set<Bandwidth> set = new HashSet<Bandwidth>();
+
+ set.add(b1);
+ assertEquals(1, set.size());
+
+ set.add(b2);
+ assertEquals(2, set.size());
+
+ set.add(b3);
+ assertEquals(2, set.size());
+
+ set.add(b4);
+ assertEquals(3, set.size());
+ }
+
+ @Test
+ public void testCompareTo() {
+ final Set<Bandwidth> set = new TreeSet<Bandwidth>();
+
+ set.add(b1);
+ assertEquals(1, set.size());
+
+ set.add(b2);
+ assertEquals(2, set.size());
+
+ set.add(b3);
+ assertEquals(2, set.size());
+
+ set.add(b4);
+ assertEquals(3, set.size());
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+public class IGPMetricTest {
+
+ @Test
+ public void testOverflows() {
+ try {
+ new IGPMetric(-2);
+ fail("Constructor successful unexpectedly");
+ } catch(IllegalArgumentException e) {}
+ try {
+ new IGPMetric(16777216);
+ fail("Constructor successful unexpectedly");
+ } catch(IllegalArgumentException e) {}
+ }
+
+ @Test
+ public void testGetValue() {
+ IGPMetric metric = new IGPMetric(951357);
+ assertEquals(951357, metric.getValue());
+ }
+
+ @Test
+ public void testEqualsObject() {
+ IGPMetric metric1 = new IGPMetric(159357);
+ IGPMetric metric2 = new IGPMetric(159357);
+ IGPMetric metric3 = new IGPMetric(258456);
+ IGPMetric metric4 = metric3;
+
+ assertEquals(metric1, metric2);
+ assertEquals(metric1.hashCode(), metric2.hashCode());
+ assertEquals(metric3, metric4);
+ assertNotNull(metric1);
+ assertThat(metric1, not(new Object()));
+ assertThat(metric1, not(metric3));
+ assertThat(metric1.hashCode(), not(metric3.hashCode()));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertTrue;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+public class IPAddressesAndPrefixesTest {
+
+ @Test
+ public void test1(){
+ assertTrue(IPAddresses.parseNetworkAddress("123.123.123.123") instanceof IPv4Address);
+ assertTrue(IPAddresses.parseNetworkAddress("2001::1") instanceof IPv6Address);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void test2(){
+ IPAddresses.parseNetworkAddress("256.125.126.256");
+ }
+
+ @Test
+ public void test3() {
+ assertTrue("123.123.123.123".equals(IPv4.FAMILY.addressForString("123.123.123.123").toString()));
+ assertTrue("2001:0:0:0:0:0:0:1".equals(IPv6.FAMILY.addressForString("2001::1").toString()));
+ }
+
+ @Test
+ public void test4() throws UnknownHostException{
+ assertTrue(IPAddresses.createNetworkAddress(InetAddress.getByName("123.123.123.123")) instanceof IPv4Address);
+ assertTrue(IPAddresses.createNetworkAddress(InetAddress.getByName("2001::1")) instanceof IPv6Address);
+ }
+
+ @Test
+ public void test5() {
+ assertTrue("123.123.123.0/24".equals(IPv4.FAMILY.addressForString("123.123.123.123").asPrefix(24).toString()));
+ assertTrue("123.123.123.0/24".equals(IPv4.FAMILY.prefixForString("123.123.123.123/24").toString()));
+ assertTrue("2001:0:0:0:0:0:0:0/120".equals(IPv6.FAMILY.addressForString("2001::1").asPrefix(120).toString()));
+ assertTrue("2001:0:0:0:0:0:0:0/120".equals(IPv6.FAMILY.prefixForString("2001::1/120").toString()));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+
+public class IPv4AddressTest {
+ private IPv4Address a1, a2, a3, a4, a5;
+
+ @Before
+ public void setUp() {
+ this.a1 = IPv4.FAMILY.addressForString("10.0.0.1");
+ this.a2 = IPv4.FAMILY.addressForString("10.0.0.2");
+ this.a3 = IPv4.FAMILY.addressForString("10.0.0.2");
+ this.a4 = IPv4.FAMILY.addressForString("10.0.0.0");
+ this.a5 = this.a4.applyMask(24);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testFactoryFailure() {
+ final byte[] fail_bytes = { 1, 2, 3, 4, 5 };
+ new IPv4Address(fail_bytes);
+ }
+
+ @Test
+ public void testFactorySuccess() {
+ final byte[] succ_bytes = { 10, 0, 0, 1 };
+
+ final IPv4Address a = new IPv4Address(succ_bytes);
+ assertEquals(this.a1, a);
+ assertArrayEquals(a.getAddress(), succ_bytes);
+ }
+
+ @Test
+ public void testEquals() {
+ assertEquals(this.a2, this.a3);
+ assertFalse(this.a1.equals(this.a2));
+ assertFalse(this.a1.equals(new Object()));
+ }
+
+ @Test
+ public void testHashCode() {
+ final Set<IPv4Address> set = Sets.newHashSet();
+
+ set.add(this.a1);
+ assertEquals(1, set.size());
+
+ set.add(this.a2);
+ assertEquals(2, set.size());
+
+ set.add(this.a3);
+ assertEquals(2, set.size());
+
+ set.add(this.a4);
+ assertEquals(3, set.size());
+ }
+
+ @Test
+ public void testCompareTo() throws Exception {
+ final Set<IPv4Address> set = Sets.newTreeSet();
+
+ set.add(this.a1);
+ assertEquals(1, set.size());
+
+ set.add(this.a2);
+ assertEquals(2, set.size());
+
+ set.add(this.a3);
+ assertEquals(2, set.size());
+
+ set.add(this.a4);
+ assertEquals(3, set.size());
+ }
+
+ @Test
+ public void testCompareToExtended() {
+ IPv4Address an1 = IPv4.FAMILY.addressForString("192.168.4.5");
+ IPv4Address an2 = IPv4.FAMILY.addressForString("190.168.4.5");
+
+ assertEquals(2, an1.compareTo(an2));
+ assertFalse(an1.equals(an2));
+
+ assertEquals(-2, an2.compareTo(an1));
+ assertFalse(an2.equals(an1));
+
+ an1 = IPv4.FAMILY.addressForString("192.10.4.5");
+ an2 = IPv4.FAMILY.addressForString("10.10.4.5");
+
+ assertEquals(182, an1.compareTo(an2));
+ assertFalse(an1.equals(an2));
+
+ assertEquals(-182, an2.compareTo(an1));
+ assertFalse(an2.equals(an1));
+
+ an1 = IPv4.FAMILY.addressForString("255.10.4.5");
+ an2 = IPv4.FAMILY.addressForString("0.10.4.5");
+
+ assertEquals(255, an1.compareTo(an2));
+ assertFalse(an1.equals(an2));
+
+ assertEquals(-255, an2.compareTo(an1));
+ assertFalse(an2.equals(an1));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testIllegalArgument() {
+ IPv4.FAMILY.addressForString("2001:db8:85a3:0:0:8a2e:370:7332");
+ }
+
+ @Test
+ public void testToString() {
+ assertEquals("10.0.0.1", this.a1.toString());
+ assertEquals("10.0.0.2", this.a2.toString());
+ assertEquals("10.0.0.2", this.a3.toString());
+ assertEquals("10.0.0.0", this.a4.toString());
+ assertEquals("10.0.0.0", this.a5.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class IPv4PrefixTest {
+ private Prefix<IPv4Address> p1, p2, p3, p4;
+ private IPv4Address addr;
+
+ @Before
+ public void setUp() throws Exception {
+ p1 = new IPv4Prefix(new IPv4Address(InetAddress.getByName("10.0.0.1")), 32);
+ p2 = new IPv4Prefix(new IPv4Address(InetAddress.getByName("10.0.0.2")), 32);
+ p3 = new IPv4Prefix(new IPv4Address(InetAddress.getByName("10.0.0.2")), 32);
+ p4 = new IPv4Prefix(new IPv4Address(InetAddress.getByName("10.0.0.0")), 24);
+ addr = new IPv4Address(InetAddress.getByName("1.2.3.4"));
+ }
+
+ @Test
+ public void testGetLength() {
+ assertEquals(32, p1.getLength());
+ assertEquals(32, p2.getLength());
+ assertEquals(32, p3.getLength());
+ assertEquals(24, p4.getLength());
+ }
+
+ @Test
+ public void testEquals() {
+ Prefix<IPv4Address> p5 = p4;
+ assertEquals(p4, p5);
+ assertNotNull(p4);
+ assertThat(p4, not(new Object()));
+ assertEquals(p2, p3);
+ }
+
+ @Test
+ public void testHashCode() {
+ final Set<Prefix<IPv4Address>> set = new HashSet<Prefix<IPv4Address>>();
+
+ set.add(p1);
+ assertEquals(1, set.size());
+
+ set.add(p2);
+ assertEquals(2, set.size());
+
+ set.add(p3);
+ assertEquals(2, set.size());
+
+ set.add(p4);
+ assertEquals(3, set.size());
+ }
+
+ @Test
+ public void testCompareTo() {
+ final Set<Prefix<IPv4Address>> set = new TreeSet<Prefix<IPv4Address>>();
+
+ set.add(p1);
+ assertEquals(1, set.size());
+
+ set.add(p2);
+ assertEquals(2, set.size());
+
+ set.add(p3);
+ assertEquals(2, set.size());
+
+ set.add(p4);
+ assertEquals(3, set.size());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNegativeLength() {
+ new IPv4Prefix(addr, -1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testLongLength() {
+ new IPv4Prefix(addr, 33);
+ }
+
+ @Test
+ public void testToString() {
+ String name1 = p1.getAddress().toString() +"/"+ p1.getLength();
+ assertEquals(name1, p1.toString());
+
+ String name2 = p2.getAddress().toString() +"/"+ p2.getLength();
+ assertEquals(name2, p2.toString());
+ }
+
+ @Test
+ public void testMatches() throws Exception {
+ IPv4Address address1 = new IPv4Address(InetAddress.getByName("10.0.0.1"));
+ IPv4Address address2 = new IPv4Address(InetAddress.getByName("10.0.0.2"));
+ IPv4Prefix p1 = new IPv4Prefix(address1, 32);
+ IPv4Prefix p2 = new IPv4Prefix(address1, 16);
+ assertTrue(p1.contains(address1));
+ assertFalse(p1.contains(address2));
+ assertTrue(p2.contains(address1));
+ assertTrue(p2.contains(address2));
+ }
+
+ @Test
+ public void testApplyMask() throws Exception {
+ final IPv4Address addr = new IPv4Address(InetAddress.getByName("10.1.2.3"));
+ final IPv4Prefix p5 = new IPv4Prefix(addr, 30);
+ final IPv4Prefix p6 = new IPv4Prefix(addr, 31);
+ final IPv4Prefix p7 = new IPv4Prefix(addr, 32);
+ final IPv4Prefix p8 = new IPv4Prefix(addr, 16);
+
+ assertFalse(addr == p5.getAddress());
+ assertFalse(addr == p6.getAddress());
+ assertFalse(addr == p7.getAddress());
+ assertEquals("10.1.2.3", addr.toString());
+ assertEquals("10.1.2.0/30", p5.toString());
+ assertEquals("10.1.2.2/31", p6.toString());
+ assertEquals("10.1.2.3/32", p7.toString());
+ assertEquals("10.1.0.0/16", p8.toString());
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class IPv6AddressTest {
+ private IPv6Address a1, a2, a3, a4, a5;
+
+ @Before
+ public void setUp() throws Exception {
+ this.a1 = new IPv6Address(
+ InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7331"));
+ this.a2 = new IPv6Address(
+ InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7332"));
+ this.a3 = new IPv6Address(
+ InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7332"));
+ this.a4 = new IPv6Address(
+ InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:0000"));
+ this.a5 = this.a4.applyMask(112);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testFailingFactory() {
+ final byte[] fail_bytes = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17 };
+
+ new IPv6Address(fail_bytes);
+ }
+
+ @Test
+ public void testFactory() {
+ final byte[] succ_bytes = { 32, 1, 13, -72, -123, -93, 0, 0, 0, 0,
+ -118, 46, 3, 112, 115, 49 };
+
+ final IPv6Address a = new IPv6Address(succ_bytes);
+ assertEquals(this.a1, a);
+ assertEquals(succ_bytes, a.getAddress());
+ }
+
+ @Test
+ public void testEquals() {
+ assertTrue(this.a2.equals(this.a3));
+ assertFalse(this.a1.equals(this.a2));
+ assertFalse(this.a1.equals(new Object()));
+ }
+
+ @Test
+ public void testHashCode() {
+ final Set<IPv6Address> set = new HashSet<IPv6Address>();
+
+ set.add(this.a1);
+ assertEquals(1, set.size());
+
+ set.add(this.a2);
+ assertEquals(2, set.size());
+
+ set.add(this.a3);
+ assertEquals(2, set.size());
+
+ set.add(this.a4);
+ assertEquals(3, set.size());
+ }
+
+ @Test
+ public void testCompareTo() {
+ final Set<IPv6Address> set = new TreeSet<IPv6Address>();
+
+ set.add(this.a1);
+ assertEquals(1, set.size());
+
+ set.add(this.a2);
+ assertEquals(2, set.size());
+
+ set.add(this.a3);
+ assertEquals(2, set.size());
+
+ set.add(this.a4);
+ assertEquals(3, set.size());
+ }
+
+ @Test
+ public void testCompareToExtended() throws Exception {
+ IPv6Prefix an1 = new IPv6Prefix(new IPv6Address(
+ InetAddress.getByName("8:0:0:0:0:0:0:0")), 128);
+ IPv6Prefix an2 = new IPv6Prefix(new IPv6Address(
+ InetAddress.getByName("1:0:0:0:0:0:0:0")), 128);
+
+ assertEquals(7, an1.compareTo(an2));
+ assertThat(an1, not(an2));
+
+ assertEquals(-7, an2.compareTo(an1));
+ assertThat(an2, not(an1));
+
+ an1 = new IPv6Prefix(new IPv6Address(
+ InetAddress.getByName("aa:0:0:0:0:0:0:0")), 128);
+ an2 = new IPv6Prefix(new IPv6Address(
+ InetAddress.getByName("1:0:0:0:0:0:0:0")), 128);
+
+ assertEquals(169, an1.compareTo(an2));
+ assertThat(an1, not(an2));
+
+ assertEquals(-169, an2.compareTo(an1));
+ assertThat(an2, not(an1));
+
+ an1 = new IPv6Prefix(new IPv6Address(
+ InetAddress.getByName("ff:0:0:0:0:0:0:0")), 128);
+ an2 = new IPv6Prefix(new IPv6Address(
+ InetAddress.getByName("0:0:0:0:0:0:0:0")), 128);
+
+ assertEquals(255, an1.compareTo(an2));
+ assertThat(an1, not(an2));
+
+ assertEquals(-255, an2.compareTo(an1));
+ assertThat(an2, not(an1));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testIllegalArgument() throws Exception {
+ new IPv6Address(InetAddress.getByName("120.20.20.20"));
+ }
+
+ @Test
+ public void testToString() {
+ assertEquals("2001:db8:85a3:0:0:8a2e:370:7331", this.a1.toString());
+ assertEquals("2001:db8:85a3:0:0:8a2e:370:7332", this.a2.toString());
+ assertEquals("2001:db8:85a3:0:0:8a2e:370:7332", this.a3.toString());
+ assertEquals("2001:db8:85a3:0:0:8a2e:370:0", this.a4.toString());
+ assertEquals("2001:db8:85a3:0:0:8a2e:370:0", this.a5.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class IPv6PrefixTest {
+ private Prefix<IPv6Address> p1, p2, p3, p4;
+ private IPv6Address addr;
+
+ @Before
+ public void setUp() throws Exception {
+ p1 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7331")), 128);
+ p2 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7332")), 128);
+ p3 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7332")), 128);
+ p4 = new IPv6Prefix(new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7300")), 120);
+ addr = new IPv6Address(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7331"));
+ }
+
+ @Test
+ public void testEquals() {
+ assertTrue(p2.equals(p3));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNegativeLength() {
+ new IPv6Prefix(addr, -1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testLongLength() throws Exception {
+ new IPv6Prefix(addr, 129);
+ }
+
+ @Test
+ public void testHashCode() {
+ final Set<Prefix<IPv6Address>> set = new HashSet<Prefix<IPv6Address>>();
+
+ set.add(p1);
+ assertEquals(1, set.size());
+
+ set.add(p2);
+ assertEquals(2, set.size());
+
+ set.add(p3);
+ assertEquals(2, set.size());
+
+ set.add(p4);
+ assertEquals(3, set.size());
+ }
+
+ @Test
+ public void testCompareTo() {
+ final Set<Prefix<IPv6Address>> set = new TreeSet<Prefix<IPv6Address>>();
+
+ set.add(p1);
+ assertEquals(1, set.size());
+
+ set.add(p2);
+ assertEquals(2, set.size());
+
+ set.add(p3);
+ assertEquals(2, set.size());
+
+ set.add(p4);
+ assertEquals(3, set.size());
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ISOSystemIdentifierTest {
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testISOSystemIdentifier() {
+ byte[] b = new byte[]{10,12,127,0,9,1,1};
+ new ISOSystemIdentifier(b);
+ }
+
+ @Test
+ public void testGetBytes() {
+ byte[] b = new byte[]{10,12,127,0,9,1};
+ ISOSystemIdentifier id = new ISOSystemIdentifier(b);
+ Assert.assertArrayEquals(new byte[]{10,12,127,0,9,1}, id.getBytes());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.concepts;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+public class TEMetricTest {
+
+ @Test
+ public void testOverflows() {
+ try {
+ new TEMetric(-2);
+ fail("Constructor successful unexpectedly");
+ } catch(IllegalArgumentException e) {}
+ try {
+ new TEMetric(4294967296L);
+ fail("Constructor successful unexpectedly");
+ } catch(IllegalArgumentException e) {}
+ }
+
+ @Test
+ public void testGetValue() {
+ TEMetric metric = new TEMetric(951357);
+ assertEquals(951357, metric.getValue());
+ }
+
+ @Test
+ public void testEqualsObject() {
+ TEMetric metric1 = new TEMetric(159357);
+ TEMetric metric2 = new TEMetric(159357);
+ TEMetric metric3 = new TEMetric(258456);
+ TEMetric metric4 = metric3;
+
+ assertEquals(metric1, metric2);
+ assertEquals(metric1.hashCode(), metric2.hashCode());
+ assertEquals(metric3, metric4);
+ assertNotNull(metric1);
+ assertThat(metric1, not(equalTo(new Object())));
+ assertThat(metric1, not(equalTo(metric3)));
+ assertThat(metric1.hashCode(), not(equalTo(metric3.hashCode())));
+ }
+}
+
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>common-protocol</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>protocol-parent</artifactId>
+ <version>0.1</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>framework</artifactId>
+ <description>Common protocol framework</description>
+ <packaging>bundle</packaging>
+ <version>1.0</version>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>util</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Import-Package>
+ com.google.common.base,
+ com.google.common.collect,
+ org.opendaylight.protocol.concepts,
+ org.slf4j,
+ javax.net.ssl,
+ org.opendaylight.protocol.util,
+ javax.annotation,
+ javax.management,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.protocol.framework,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.version}</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>COMMON-PROTOCOL Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+/**
+ * Used when something occurs during parsing bytes to java objects.
+ */
+public class DeserializerException extends Exception {
+
+ private static final long serialVersionUID = -2247000673438452870L;
+
+ /**
+ * Creates a deserializer exception.
+ * @param err string
+ */
+ public DeserializerException(final String err) {
+ this(err, null);
+ }
+
+ /**
+ * Creates a deserializer exception.
+ * @param err string
+ * @param e underlying exception
+ */
+ public DeserializerException(final String err, final Exception e) {
+ super(err, e);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import javax.net.ssl.SSLContext;
+
+/**
+ * Dispatcher class for creating protocol servers and clients. The idea is to first create servers and clients and the run the start method
+ * that will handle sockets in different thread.
+ */
+public interface Dispatcher {
+ /**
+ * Creates server. Each server needs factories to pass their instances to client sessions.
+ * @param address to be bound with the server
+ * @param connectionFactory factory for connection specific attributes
+ * @param sfactory to create specific session
+ * @param isFactory protocol specific input stream factory
+ *
+ * @return instance of ProtocolServer
+ * @throws IOException if some IO error occurred
+ */
+ public ProtocolServer createServer(final InetSocketAddress address, final ProtocolConnectionFactory connectionFactory,
+ final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory) throws IOException;
+
+ /**
+ * Creates secure server. Each server needs factories to pass their instances to client sessions.
+ * @param address to be bound with the server
+ * @param connectionFactory factory for connection specific attributes
+ * @param sfactory to create specific session
+ * @param isFactory protocol-specific input stream factory
+ * @param context SSLContext to use in secure communications
+ *
+ * @return instance of ProtocolServer
+ * @throws IOException if some IO error occurred
+ */
+ public ProtocolServer createServer(final InetSocketAddress address, final ProtocolConnectionFactory connectionFactory,
+ final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory, final SSLContext context) throws IOException;
+
+ /**
+ * Creates a client.
+ * @param connection connection specific attributes
+ * @param sfactory protocol message factory to be passed to session
+ * @param isFactory protocol-specific input stream factory
+ *
+ * @return session associated with this client
+ * @throws IOException if some IO error occurred
+ */
+ public ProtocolSession createClient(final ProtocolConnection connection, final ProtocolSessionFactory sfactory,
+ final ProtocolInputStreamFactory isFactory) throws IOException;
+
+ /**
+ * Creates secure client.
+ * @param connection connection specific attributes
+ * @param sfactory protocol message factory to be passed to session
+ * @param isFactory protocol-specific input stream factory
+ * @param context SSLContext to use in secure communications
+ *
+ * @return session associated with this client
+ * @throws IOException if some IO error occurred
+ */
+ public ProtocolSession createClient(final ProtocolConnection connection, final ProtocolSessionFactory sfactory,
+ final ProtocolInputStreamFactory isFactory, final SSLContext context) throws IOException;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Queue;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+import javax.net.ssl.SSLContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+
+/**
+ * Dispatcher class for creating servers and clients. The idea is to first create servers and clients and the run the
+ * start method that will handle sockets in different thread.
+ */
+public final class DispatcherImpl implements Dispatcher, SessionParent {
+
+ private static final Logger logger = LoggerFactory.getLogger(Dispatcher.class);
+
+ public static final int DEFAULT_MAX_RECONNECT_COUNT = 30;
+
+ public static final int DEFAULT_RECONNECT_MILLIS = 30000;
+ public static final int DEFAULT_SERVICE_MILLIS = 1000;
+
+ private static final int BUFFER_SIZE = 16384;
+
+ private static final boolean SSL_ENABLED = true;
+
+ private int serviceMillis = DEFAULT_SERVICE_MILLIS;
+ private int reconnectMillis = 5000;
+
+ private int maxConnectCount = 0;
+
+ /**
+ * List of servers created by this dispatcher. Servers are identified as a pair Server and the InetSocketAddress to
+ * which the server is bound.
+ */
+ private final Map<InetSocketAddress, ProtocolServer> servers = new HashMap<InetSocketAddress, ProtocolServer>();
+
+ /**
+ * Mapping of client Sessions to keys (Either clients created by the dispatcher directly or clients connected to one
+ * of the dispatchers server).
+ */
+ private final Map<ProtocolSession, SelectionKey> sessionKeys = new HashMap<ProtocolSession, SelectionKey>();
+
+ /**
+ * List of clients created by this dispatcher. Each client has its own Session. They are identified as a pair of
+ * Session and the InetSocketAddress to which they are connected.
+ */
+ private final BiMap<InetSocketAddress, ProtocolSession> clients;
+
+ /**
+ * Timer object grouping FSM Timers
+ */
+ private final Timer stateTimer;
+
+ /**
+ * Variable indicating that there was a request for stopping this dispatcher.
+ */
+ private volatile boolean requestStop = false;
+
+ private final Thread innerThread;
+
+ private final ExecutorService executorService;
+
+ private final InnerRun innerRun;
+
+ /**
+ * Configuration dependency used for testing of reusability.
+ */
+ private final ThreadFactory threadFactory;
+
+ private final class InnerRun implements Runnable {
+
+ /**
+ * Common selector for client/server parts.
+ */
+ public final Selector selector;
+
+ private final DispatcherImpl parent;
+
+ protected InnerRun(final DispatcherImpl parent) throws IOException {
+ final Selector s = SelectorProvider.provider().openSelector();
+
+ if (SSL_ENABLED)
+ this.selector = new SSLSelector(s);
+ else
+ this.selector = s;
+
+ this.parent = parent;
+ }
+
+ @Override
+ public void run() {
+ // this method finishes only when stop() method was called
+ while (!this.parent.requestStop) {
+ try {
+ this.selector.select();
+ } catch (final IOException e) {
+ logger.warn("Selection operation failed", e);
+ break;
+ }
+
+ /*
+ * This block runs under lock. The idea is that
+ * selection key notifiers will first acquire the
+ * lock, then wake up the selector, then do their
+ * modifications.
+ *
+ * This means that there are two possibilities:
+ *
+ * 1) we arrive here as a result of a selector wake
+ * up, at which point the modifier already holds
+ * the lock, and we'll wait for it.
+ *
+ * 2) we arrive here as a result of an event, in which
+ * case we will prevent modifiers from starting
+ * by holding the lock.
+ */
+ // logger.debug("Acquiring lock");
+ synchronized (this) {
+ final Set<SelectionKey> keys = this.selector.selectedKeys();
+ if (keys.isEmpty())
+ continue;
+
+ /*
+ * Calculate maximum nanoseconds we can spend on read
+ * or write. Each key can do a pair of operations in one
+ * iteration.
+ */
+ final long serviceTime = serviceMillis * 500000 / keys.size();
+
+ final Iterator<SelectionKey> selectedKeys = keys.iterator();
+ while (selectedKeys.hasNext()) {
+ final SelectionKey key = selectedKeys.next();
+ selectedKeys.remove();
+
+ if (!key.isValid()) {
+ continue;
+ }
+
+ try {
+ if (key.isAcceptable()) {
+ this.parent.accept(key);
+ }
+ if (key.isConnectable()) {
+ if (!this.parent.finishConnection(key)) {
+ continue;
+ }
+ }
+
+ /*
+ * Split read/write fairness. If this key is only
+ * readable or only writable, double the time
+ */
+ final long keyTime = key.isReadable() == key.isWritable() ? serviceTime : 2 * serviceTime;
+
+ /*
+ * If this key is readable, read it. That operation may
+ * detect end-of-stream, which it will report internally,
+ * and inform us by returning true.
+ *
+ * If that is the case, we do not want to proceed with the
+ * write case, because the key may no longer be valid.
+ */
+ if (key.isReadable() && this.parent.read(key, System.nanoTime() + keyTime)) {
+ continue;
+ }
+
+ /*
+ * If this key is writable, write it. This may completely
+ * drain the output queue, in which case write returns true.
+ *
+ * If that is the case, we need to suspend selecting for
+ * writability -- it will be re-enabled once the queue goes
+ * non-empty.
+ */
+ if (key.isWritable() && this.parent.write(key, System.nanoTime() + keyTime) && key.isValid()) {
+ key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
+ }
+
+ } catch (final IOException e) {
+ logger.debug("Channel {} incurred unexpected error, closing it", key.channel(), e);
+ key.cancel();
+ try {
+ key.channel().close(); // close the channel that caused problems
+ } catch (final IOException e1) {
+ logger.error("Channel: {} could not be closed, because {}", key.channel(), e1.getMessage(), e1);
+ }
+ }
+ }
+ }
+ }
+
+ logger.trace("Ended run of dispatcher.");
+ try {
+ this.selector.close();
+ } catch (final IOException e) {
+ throw new RuntimeException("Failed to close selector", e);
+ }
+ }
+ }
+
+ /**
+ * Creates an instance of Dispatcher, gets the default selector and opens it.
+ *
+ * @param tfactory default Thread Factory
+ * @throws IOException if some error occurred during opening the selector
+ */
+ public DispatcherImpl(final ThreadFactory tfactory) throws IOException {
+ this.threadFactory = tfactory;
+ this.executorService = Executors.newSingleThreadExecutor(tfactory);
+ this.stateTimer = new Timer();
+ this.clients = HashBiMap.create();
+ this.innerRun = new InnerRun(this);
+ this.innerThread = tfactory.newThread(this.innerRun);
+ this.innerThread.start();
+ }
+
+ protected synchronized ProtocolServer startServer(final ServerSocketChannel serverChannel, final InetSocketAddress address,
+ final ProtocolConnectionFactory connectionFactory, final ProtocolSessionFactory sfactory,
+ final ProtocolInputStreamFactory isFactory) throws IOException {
+
+ // Notify the thread to update its selection keys
+ this.innerRun.selector.wakeup();
+
+ // logger.debug("Selector notified.");
+ serverChannel.configureBlocking(false);
+ serverChannel.bind(address);
+
+ final SelectionKey key = serverChannel.register(this.innerRun.selector, SelectionKey.OP_ACCEPT);
+ final ProtocolServer server = new ProtocolServer(this, address, serverChannel, connectionFactory, sfactory, isFactory);
+ key.attach(server);
+ this.servers.put(address, server);
+
+ logger.info("Server created.");
+ return server;
+ }
+
+ @Override
+ public ProtocolServer createServer(final InetSocketAddress address, final ProtocolConnectionFactory connectionFactory,
+ final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory) throws IOException {
+ synchronized (this.innerRun) {
+ if (this.servers.get(address) != null) {
+ logger.warn("Server with this address: {} was already created.", address);
+ throw new IllegalStateException("Server with this address: " + address + " was already created.");
+ }
+
+ return this.startServer(ServerSocketChannel.open(), address, connectionFactory, sfactory, isFactory);
+ }
+ }
+
+ @Override
+ public ProtocolServer createServer(final InetSocketAddress address, final ProtocolConnectionFactory connectionFactory,
+ final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory, final SSLContext context) throws IOException {
+
+ if (!SSL_ENABLED)
+ throw new UnsupportedOperationException("SSL has not been enabled");
+
+ synchronized (this.innerRun) {
+ if (this.servers.get(address) != null) {
+ logger.warn("Server with this address: {} was already created.", address);
+ throw new IllegalStateException("Server with this address: " + address + " was already created.");
+ }
+
+ return this.startServer(SSLServerSocketChannel.open(this.innerRun.selector, context, this.executorService), address,
+ connectionFactory, sfactory, isFactory);
+ }
+ }
+
+ private void connectChannel(final SelectionKey key) {
+ final SessionStreams state = (SessionStreams) key.attachment();
+ state.timer = null;
+
+ state.connectCount++;
+ logger.debug("Connecting to {} attempt {}", state.connection.getPeerAddress(), state.connectCount);
+
+ final SocketChannel channel = (SocketChannel) key.channel();
+ try {
+ channel.connect(state.connection.getPeerAddress());
+ } catch (final IOException e) {
+ this.connectFailed(key, e);
+ return;
+ }
+
+ if (channel.isConnected()) {
+ logger.trace("Connected, update interestops");
+ key.interestOps(SelectionKey.OP_READ);
+ state.getSession().startSession();
+ } else
+ key.interestOps(SelectionKey.OP_CONNECT);
+ }
+
+ private void connectFailed(final SelectionKey key, final IOException e) {
+ final SessionStreams state = (SessionStreams) key.attachment();
+
+ key.interestOps(0);
+
+ if (this.maxConnectCount >= 0 && state.connectCount >= this.maxConnectCount) {
+ logger.debug("Connection to {} failed", state.connection.getPeerAddress().getAddress(), e);
+ this.clients.inverse().remove(state.getSession());
+ state.getSession().onConnectionFailed(e);
+ return;
+ }
+
+ logger.trace("Connect to {} failed, will retry in {} milliseconds", state.connection.getPeerAddress().getAddress(),
+ this.reconnectMillis, e);
+ state.timer = new TimerTask() {
+ @Override
+ public void run() {
+ DispatcherImpl.this.connectChannel(key);
+ }
+ };
+ this.stateTimer.schedule(state.timer, this.reconnectMillis);
+ }
+
+ private ProtocolSession startClient(final SocketChannel channel, final ProtocolConnection connection,
+ final ProtocolSessionFactory sfactory, final ProtocolInputStreamFactory isFactory) throws IOException {
+
+ // Notify the thread to update its selection keys
+ this.innerRun.selector.wakeup();
+
+ channel.configureBlocking(false);
+
+ final ProtocolSession session;
+ final SelectionKey key;
+ synchronized (this) {
+ session = sfactory.getProtocolSession(this, this.stateTimer, connection, 0);
+
+ final PipedOutputStream pos = new PipedOutputStream();
+ final PipedInputStream pis = new PipedInputStream(pos, session.maximumMessageSize());
+
+ key = channel.register(this.innerRun.selector, SelectionKey.OP_CONNECT);
+ key.attach(new SessionStreams(pos, pis, isFactory.getProtocolInputStream(pis, session.getMessageFactory()), session, connection));
+
+ this.sessionKeys.put(session, key);
+ this.clients.put(connection.getPeerAddress(), session);
+ logger.info("Client created.");
+ }
+
+ this.connectChannel(key);
+ return session;
+ }
+
+ @Override
+ public ProtocolSession createClient(final ProtocolConnection connection, final ProtocolSessionFactory sfactory,
+ final ProtocolInputStreamFactory isFactory) throws IOException {
+ synchronized (this.innerRun) {
+ if (this.clients.containsKey(connection.getPeerAddress())) {
+ logger.warn("Attempt to create duplicate client session to the same address: {}", connection.getPeerAddress());
+ throw new IllegalStateException("Attempt to create duplicate client session to the same address: "
+ + connection.getPeerAddress());
+ }
+
+ return this.startClient(SocketChannel.open(), connection, sfactory, isFactory);
+ }
+ }
+
+ @Override
+ public ProtocolSession createClient(final ProtocolConnection connection, final ProtocolSessionFactory sfactory,
+ final ProtocolInputStreamFactory isFactory, final SSLContext context) throws IOException {
+
+ if (!SSL_ENABLED)
+ throw new UnsupportedOperationException("SSL has not been enabled");
+
+ synchronized (this.innerRun) {
+ if (this.clients.containsKey(connection.getPeerAddress())) {
+ logger.warn("Attempt to create duplicate client session to the same address: {}", connection.getPeerAddress());
+ throw new IllegalStateException("Attempt to create duplicate client session to the same address: "
+ + connection.getPeerAddress());
+ }
+
+ final SocketChannel sock = SSLSocketChannel.open(SocketChannel.open(), context, this.executorService, null);
+ return this.startClient(sock, connection, sfactory, isFactory);
+ }
+ }
+
+ /**
+ * Requests to stop dispatchers run() method. This method wakes up the selector, even if there are no selectedKeys
+ * to stop blocking the thread.
+ */
+ public void stop() {
+ logger.debug("Requested stop of the Dispatcher.");
+ this.requestStop = true;
+ this.innerRun.selector.wakeup();
+ try {
+ this.innerThread.join();
+ } catch (final InterruptedException e) {
+ logger.error("Stopping interrupted.", e);
+ }
+
+ this.executorService.shutdown();
+ }
+
+ /**
+ * Removes given server from list of servers created by this dispatcher.
+ *
+ * @param server to be removed
+ */
+ void removeServer(final ProtocolServer server) {
+ this.servers.remove(server.getAddress());
+ logger.trace("Server removed.");
+ }
+
+ /**
+ * Reads from socket and sends data to session through Piped Streams.
+ *
+ * @param key selection key that was marked as ready to read from
+ * @return true if the read has encountered end of channel (so no data will ever come) false if the method did read
+ * all of its input
+ * @throws IOException if there was some error with IO streams
+ */
+ private boolean read(final SelectionKey key, final long deadline) throws IOException {
+ logger.trace("Started reading.");
+ final SocketChannel chan = (SocketChannel) key.channel();
+ final SessionStreams streams = (SessionStreams) key.attachment();
+ final ProtocolInputStream pcepis = streams.getProtocolInputStream();
+ final PipedOutputStream pos = streams.getPipedOutputStream();
+ final PipedInputStream pis = streams.getPipedInputStream();
+ final ProtocolSession session = streams.getSession();
+
+ try {
+ final ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
+ int r = chan.read(byteBuffer);
+
+ while (r != 0) {
+ byteBuffer.flip();
+
+ // if we have some unread data in the buffer
+ while (byteBuffer.hasRemaining()) {
+ final int pisFree = session.maximumMessageSize() - pis.available();
+ if (pisFree == 0)
+ throw new IOException("Protocol failed to detect no-progress situation");
+
+ int toMove = byteBuffer.remaining();
+
+ // Do not try to write more than the input stream can accept
+ if (toMove > pisFree)
+ toMove = pisFree;
+
+ // Write to the output stream and adjust buffer position
+ pos.write(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(), toMove);
+ byteBuffer.position(byteBuffer.position() + toMove);
+
+ // Notify input stream that it can read more stuff
+ pos.flush();
+
+ // process any messages which became available
+ while (pcepis.isMessageAvailable()) {
+ // read and parse message
+ final ProtocolMessage msg = pcepis.getMessage();
+ // send it to session for handling
+ session.handleMessage(msg);
+ }
+ }
+ byteBuffer.clear();
+
+ /*
+ * We reached end-of-input stream. Notify close the output stream
+ * and notify the user. He is then supposed to close the session,
+ * releasing the write-end of things.
+ */
+ if (r == -1) {
+ logger.warn("End of input stream reached.");
+ /*
+ * The input stream has some bytes, but no others are coming
+ * in. This means it should have been a complete message,
+ * but is not -> that's a malformed message.
+ */
+ if (pis.available() != 0) {
+ logger.warn("Received incomplete message.");
+ throw new DeserializerException("Incomplete message at the end of input stream");
+ }
+ key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
+ session.endOfInput();
+ return true;
+ }
+
+ if (!chan.isOpen())
+ return true;
+
+ final long now = System.nanoTime();
+ if (deadline <= now) {
+ logger.trace("Read service time exceeded by {} nanoseconds.", now - deadline);
+ break;
+ }
+
+ r = chan.read(byteBuffer);
+ }
+ } catch (final DeserializerException e) {
+ // An unrecoverable malformed message has been received. Notify
+ // session to take care of the fallout.
+ logger.warn("Malformed message {}", e.getMessage(), e);
+ session.handleMalformedMessage(e);
+ } catch (final DocumentedException e) {
+ // A potentially recoverable malformed message has been received.
+ // Push it to the session, it will take care of the details.
+ logger.warn("Malformed message {}", e.getMessage(), e);
+ session.handleMalformedMessage(e);
+ } catch (final RuntimeException e) {
+ logger.error("Unrecoverable internal session error: {}", e.getMessage(), e);
+ throw new IOException("Unrecoverable internal session error", e);
+ }
+ return false;
+ }
+
+ /**
+ * Writes data from ProtocolOutputStream to socket.
+ *
+ * @param key selection key that was marked as ready to write from
+ * @return false if the writing was not successful true if the queue of messages became empty
+ * @throws IOException if there was some error with the IO streams
+ */
+ private boolean write(final SelectionKey key, final long deadline) throws IOException {
+ logger.trace("Started writing.");
+
+ // TODO: promote to hard error?
+ final SocketChannel socketChannel = (SocketChannel) key.channel();
+ if (!socketChannel.isConnected()) {
+ logger.warn("Channel is not connected yet.");
+ return false;
+ }
+
+ final SessionStreams streams = (SessionStreams) key.attachment();
+ final Queue<ByteBuffer> queue = streams.getSession().getStream().getBuffers();
+
+ synchronized (queue) {
+ logger.trace("Synchronized writing started.");
+ // Write until there's not more data
+ while (!queue.isEmpty()) {
+ final ByteBuffer buf = queue.element();
+ socketChannel.write(buf);
+ if (buf.remaining() > 0) {
+ /*
+ * If there is not enough space in the socket to write all the data
+ * stay in writing mode and attempt to write after the next select()
+ * call
+ */
+ logger.trace("Socket queue full.");
+ return false;
+ }
+ queue.remove();
+
+ final long now = System.nanoTime();
+ if (deadline <= now) {
+ logger.trace("Write service time exceeded by {} nanoseconds.", now - deadline);
+ return false;
+ }
+ }
+ logger.trace("Write queue empty.");
+ return true;
+ }
+ }
+
+ private void acceptChannel(final ProtocolServer server, final SocketChannel socketChannel, final InetSocketAddress clientAddress)
+ throws IOException {
+ socketChannel.configureBlocking(false);
+
+ final ProtocolSession s = server.createSession(this.stateTimer, clientAddress);
+ final PipedOutputStream pos = new PipedOutputStream();
+ final PipedInputStream pis = new PipedInputStream(pos, s.maximumMessageSize());
+ final ProtocolInputStream inputStream = server.createInputStream(pis, s.getMessageFactory());
+
+ final SelectionKey skey = socketChannel.register(this.innerRun.selector, SelectionKey.OP_READ);
+ skey.attach(new SessionStreams(pos, pis, inputStream, s, null));
+ this.sessionKeys.put(s, skey);
+
+ // FIXME: catch RuntimeExceptions here, undo the put/attach above?
+ // or can we move the .put() after this call?
+ s.startSession();
+ }
+
+ /**
+ * Accepts incoming connection from a client to one of the running servers.
+ *
+ * @param key selection key that was marked as ready to accept connections
+ * @throws IOException if there was some error with IO streams
+ */
+ private void accept(final SelectionKey key) throws IOException {
+ final ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
+ final SocketChannel socketChannel = serverSocketChannel.accept();
+ if (socketChannel == null)
+ return;
+
+ final InetSocketAddress clientAddress = (InetSocketAddress) socketChannel.getRemoteAddress();
+ logger.info("Requested connection for: {}", clientAddress.getAddress().getHostAddress());
+
+ try {
+ this.acceptChannel((ProtocolServer) key.attachment(), socketChannel, clientAddress);
+ } catch (final Exception e) {
+ logger.warn("Failed to start protocol session", e);
+ socketChannel.close();
+ }
+ }
+
+ /**
+ * Finishes connection of the client to the server. Starts session.
+ *
+ * @param key selection key that was marked as ready to finish connection
+ */
+ private boolean finishConnection(final SelectionKey key) {
+ final SocketChannel socketChannel = (SocketChannel) key.channel();
+ final SessionStreams streams = (SessionStreams) key.attachment();
+ logger.trace("Finishing connection for key {}", key);
+ try {
+ if (socketChannel.finishConnect()) {
+ key.interestOps(SelectionKey.OP_READ);
+ streams.getSession().startSession();
+ }
+ } catch (final IOException e) {
+ this.connectFailed(key, e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Closes channel and cancels key assigned to given session.
+ *
+ * @param session session that was closed
+ */
+ void closeSessionSockets(final ProtocolSession session) {
+ synchronized (this.innerRun) {
+ logger.debug("Trying to close sesion.");
+ final SelectionKey key = this.sessionKeys.get(session);
+ if (key != null) {
+
+ try {
+ key.channel().close();
+ } catch (final IOException e) {
+ logger.error("Session channel could not be closed.");
+ } finally {
+ final SessionStreams streams = (SessionStreams) key.attachment();
+ if (streams.timer != null) {
+ streams.timer.cancel();
+ streams.timer = null;
+ }
+
+ logger.trace("Cancelling key.");
+ key.cancel();
+
+ final PipedOutputStream pos = streams.getPipedOutputStream();
+ try {
+ pos.close();
+ } catch (final IOException e) {
+ logger.error("Session-internal output stream could not be closed.");
+ } finally {
+ final PipedInputStream pis = streams.getPipedInputStream();
+ try {
+ pis.close();
+ } catch (final IOException e) {
+ logger.error("Session-internal input stream could not be closed.");
+ }
+ }
+ }
+ }
+ this.sessionKeys.remove(key);
+ logger.debug("Session sockets closed.");
+ }
+ }
+
+ @Override
+ public void onSessionClosed(final ProtocolSession session) {
+ synchronized (this.innerRun) {
+ this.innerRun.selector.wakeup();
+ this.closeSessionSockets(session);
+ this.clients.inverse().remove(session);
+ logger.debug("Session {} removed.", session);
+ }
+ }
+
+ @Override
+ public void checkOutputBuffer(final ProtocolSession session) {
+ final SelectionKey key = this.sessionKeys.get(session);
+ key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
+ key.selector().wakeup();
+ }
+
+ @Override
+ public void close() throws IOException {
+ for (final Entry<InetSocketAddress, ProtocolServer> s : this.servers.entrySet()) {
+ s.getValue().close();
+ }
+ for (final Entry<InetSocketAddress, ProtocolSession> s : this.clients.entrySet()) {
+ s.getValue().close();
+ }
+ }
+
+ /**
+ * Gets milliseconds between reconnects.
+ * @return time in milliseconds between reconnects
+ */
+ public synchronized int getReconnectMillis() {
+ return this.reconnectMillis;
+ }
+
+ /**
+ * Sets milliseconds between reconnects.
+ * @param reconnectMillis new value
+ */
+ public synchronized void setReconnectMillis(final int reconnectMillis) {
+ Preconditions.checkArgument(reconnectMillis > 0, "Reconnect milliseconds value has to be positive");
+ this.reconnectMillis = reconnectMillis;
+ // FIXME: readjust all pending timers
+ }
+
+ /**
+ * Gets maximum tries for connection.
+ * @return max connection count
+ */
+ public synchronized int getMaxConnectCount() {
+ return this.maxConnectCount;
+ }
+
+ /**
+ * Sets maximum tries for connection.
+ * @param maxConnectCount new value
+ */
+ public synchronized void setMaxConnectCount(final int maxConnectCount) {
+ this.maxConnectCount = maxConnectCount;
+ // FIXME: purge all sessions which already exceed the limit
+ }
+
+ public synchronized int getServiceMillis() {
+ return this.serviceMillis;
+ }
+
+ public synchronized void setServiceMillis(final int serviceMillis) {
+ Preconditions.checkArgument(serviceMillis > 0);
+ this.serviceMillis = serviceMillis;
+ }
+
+ /**
+ * Gets thread factory.
+ * @return thread factory
+ */
+ public ThreadFactory getThreadFactory() {
+ return this.threadFactory;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+/**
+ * Documented exception occurrs when an error is thrown that is documented
+ * in any RFC or draft for the specific protocol.
+ */
+public class DocumentedException extends Exception {
+
+ private static final long serialVersionUID = -3727963789710833704L;
+
+ /**
+ * Creates a documented exception
+ * @param message string
+ */
+ public DocumentedException(final String message) {
+ this(message, null);
+ }
+
+ /**
+ * Creates a documented exception
+ * @param err string
+ * @param e underlying exception
+ */
+ public DocumentedException(final String err, final Exception e) {
+ super(err, e);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.net.InetSocketAddress;
+
+/**
+ * Specifies connection attributes.
+ */
+public interface ProtocolConnection {
+
+ /**
+ * Returns address to which the connection should bind.
+ * @return inet socket address
+ */
+ InetSocketAddress getPeerAddress();
+
+ /**
+ * Returns listener for the session.
+ * @return listener for the session
+ */
+ SessionListener getListener();
+
+ /**
+ * Returns session preferences (attributes for Open object).
+ * @return session preferences
+ */
+ SessionPreferences getProposal();
+
+ /**
+ * Returns session preferences checker.
+ * @return session preferences checker
+ */
+ SessionPreferencesChecker getProposalChecker();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.net.InetSocketAddress;
+
+/**
+ * Factory creating Protocol connections.
+ */
+public interface ProtocolConnectionFactory {
+
+ /**
+ * Returns new Protocol Connection object. The rest of the attributes are
+ * protocol specific.
+ * @param address to be bind
+ * @return new Protocol Connection.
+ */
+ ProtocolConnection createProtocolConnection(final InetSocketAddress address);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+
+/**
+ * Data stream interface between Protocol Message and byte array, that represents this message as Java object. Used by
+ * the Dispatcher.
+ */
+public interface ProtocolInputStream {
+
+ /**
+ * Check availability of a message in underlying input stream. A message is available when there are more or the
+ * same amount of bytes in the stream as the message length is specified in message header. If there are not enough
+ * bytes for the message or even to read a message header, return false. Needs to be synchronized.
+ *
+ * @return true if there are enough bytes to read a message false if there are not enough bytes to read a message or
+ * a message header.
+ *
+ * @throws IOException this exception may be thrown when "impossible" protocol buffering conditions occur.
+ * Examples include: we are attempting to wait for more data than is theoretically possible (e.g. framing
+ * error), peer is attempting to make us buffer more data than possible to accomodate (2G chunk), etc.
+ */
+ public boolean isMessageAvailable() throws IOException;
+
+ /**
+ * If there are enough bytes in the underlying stream, parse the message. Blocking, till there are enough bytes to
+ * read, therefore the call of method isMessageAvailable() is suggested first. Needs to be synchronized.
+ *
+ * @return protocol specific message
+ *
+ * @throws DeserializerException if the parsing was not successful due to syntax error
+ * @throws IOException if there was problem with extracting bytes from the stream
+ * @throws DocumentedException if the parsing was not successful
+ */
+ public ProtocolMessage getMessage() throws DeserializerException, IOException, DocumentedException;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.PipedInputStream;
+
+/**
+ * Factory for creating Protocol input streams. Should be implemented to return protocol
+ * specific input stream.
+ */
+public interface ProtocolInputStreamFactory {
+
+ /**
+ * Creates and returns protocol input stream.
+ * @param pis underlying piped input stream
+ * @param pmf protocol message factory
+ * @return protocol specific input stream
+ */
+ ProtocolInputStream getProtocolInputStream(PipedInputStream pis, ProtocolMessageFactory pmf);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.Serializable;
+
+/**
+ * Marker interface. Serves as a general concept of protocol message, smallest unit of
+ * information exchanged in a protocol. Classes in common-protocol work only with this
+ * type of message, so that the rest of the module can be used without knowing specifics
+ * of underlying protocol. Each implemented protocol either has some abstract class in
+ * its API that represents abstract protocol specific message and implements this interface
+ * or has only specific protocol messages and uses this interface directly.
+ *
+ * Example:
+ *
+ * public abstract SpecificProtocolMessage implements ProtocolMessage { .. }
+ *
+ * public class SpecificOpenMessage extends SpecificProtocolMessage { .. }
+ */
+public interface ProtocolMessage extends Serializable {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+/**
+ * Interface for factory for parsing and serializing protocol specific
+ * messages. Needs to be implemented by a protocol specific message
+ * factory. The methods put/parse should delegate parsing to specific
+ * message parsers, e.g. OpenMessageParser etc.
+ */
+public interface ProtocolMessageFactory {
+
+ /**
+ * Parses message from byte array. Requires specific protocol message
+ * header object to parse the header.
+ * @param bytes byte array from which the message will be parsed
+ * @param msgHeader protocol specific message header to parse the header
+ * @return specific protocol message
+ * @throws DeserializerException if some parsing error occurs
+ * @throws DocumentedException if some documented error occurs
+ */
+ public ProtocolMessage parse(final byte[] bytes, final ProtocolMessageHeader msgHeader) throws DeserializerException, DocumentedException;
+
+ /**
+ * Serializes protocol specific message to byte array.
+ * @param msg message to be serialized.
+ * @return byte array resulting message
+ */
+ public byte[] put(final ProtocolMessage msg);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+/**
+ * Interface common for each protocol message header. Needs to be
+ * implemented by a specific protocol.
+ */
+public interface ProtocolMessageHeader {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+/**
+ * Data stream interface between ProtocolMessage and byte array,
+ * that represents this message in serialized form. Its instance
+ * needs to be present in protocol specific session, to allow
+ * sending messages from the session via the put() method.
+ */
+public final class ProtocolOutputStream {
+
+ /**
+ * List of Buffers whose content needs to be written to socket.
+ */
+ private final Queue<ByteBuffer> pendingData = new ArrayDeque<ByteBuffer>();
+
+ /**
+ * Assumes that the message is valid (that you cannot create an invalid
+ * message from API). Serializes given messages to byte array, converts this
+ * byte array to byteBuffer and adds it to List.
+ * @param message message to be written
+ * @param factory protocol specific message factory
+ */
+ public void putMessage(final ProtocolMessage message, final ProtocolMessageFactory factory) {
+ final byte[] bytes = factory.put(message);
+ if (bytes == null) {
+ throw new IllegalArgumentException("Message parsed to null.");
+ }
+ synchronized (this.pendingData) {
+ this.pendingData.add(ByteBuffer.wrap(bytes));
+ }
+ }
+
+ /**
+ * Used by PCEPDispatcher to retrieve the data that needs to be written to
+ * socket.
+ *
+ * @return data that needs to be written to socket
+ */
+ Queue<ByteBuffer> getBuffers() {
+ return this.pendingData;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.channels.ServerSocketChannel;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Timer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+
+/**
+ * Representation of a server, created by {@link Dispatcher}. Should be extended by a protocol specific server
+ * implementation.
+ */
+public class ProtocolServer implements SessionParent {
+
+ private static final Logger logger = LoggerFactory.getLogger(ProtocolServer.class);
+
+ private static final int SESSIONS_LIMIT = 255;
+
+ private final InetSocketAddress serverAddress;
+
+ private final ServerSocketChannel channel;
+
+ private final ProtocolConnectionFactory connectionFactory;
+ private final ProtocolSessionFactory sessionFactory;
+ private final ProtocolInputStreamFactory inputStreamFactory;
+
+ /**
+ * Maps clients of this server to their address. The client is represented as PCEP session. Used BiMap for
+ * implementation to allow easy manipulation with both InetSocketAddress and PCEPSessionImpl representing a key.
+ */
+ private final BiMap<InetSocketAddress, ProtocolSession> sessions;
+
+ private final Map<InetSocketAddress, Integer> sessionIds;
+
+ private final DispatcherImpl dispatcher;
+
+ /**
+ * Creates a Protocol server.
+ *
+ * @param dispatcher Dispatcher
+ * @param address address to which this server is bound
+ * @param connectionFactory factory for connection specific properties
+ * @param channel server socket channel
+ * @param sessionFactory factory for sessions
+ * @param inputStreamFactory factory for input streams
+ */
+ public ProtocolServer(final DispatcherImpl dispatcher, final InetSocketAddress address, final ServerSocketChannel channel,
+ final ProtocolConnectionFactory connectionFactory, final ProtocolSessionFactory sessionFactory,
+ final ProtocolInputStreamFactory inputStreamFactory) {
+ this.dispatcher = dispatcher;
+ this.serverAddress = address;
+ this.channel = channel;
+ this.sessions = HashBiMap.create();
+ this.connectionFactory = connectionFactory;
+ this.sessionFactory = sessionFactory;
+ this.inputStreamFactory = inputStreamFactory;
+ this.sessionIds = new HashMap<InetSocketAddress, Integer>();
+ }
+
+ /**
+ * Creates a session. This method is called after the server accepts incoming client connection. A session is
+ * created for each client. If a session for a client (represented by the address) was already created, return this,
+ * else create a new one.
+ *
+ * @param clientAddress IP address of the client
+ * @param timer Timer common for all sessions
+ * @return new or existing PCEPSession
+ * @see <a href="http://tools.ietf.org/html/rfc5440#appendix-A">RFC</a>
+ */
+ public ProtocolSession createSession(final Timer timer, final InetSocketAddress clientAddress) {
+ ProtocolSession session = null;
+ if (this.sessions.containsKey(clientAddress)) { // when the session is created, the key is the InetSocketAddress
+ session = this.sessions.get(clientAddress);
+ if (compareTo(this.serverAddress.getAddress(), clientAddress.getAddress()) > 0) {
+ try {
+ session.close();
+ } catch (final IOException e) {
+ logger.error("Session {} could not be closed.", session);
+ }
+ }
+ } else {
+ final int sessionId = getNextId(this.sessionIds.get(clientAddress), SESSIONS_LIMIT - 1);
+ session = this.sessionFactory.getProtocolSession(this, timer, this.connectionFactory.createProtocolConnection(clientAddress),
+ sessionId);
+ this.sessionIds.put(clientAddress, sessionId);
+ }
+ this.sessions.put(clientAddress, session);
+ return session;
+ }
+
+ ProtocolInputStream createInputStream(final PipedInputStream pis, final ProtocolMessageFactory pmf) {
+ return this.inputStreamFactory.getProtocolInputStream(pis, pmf);
+ }
+
+ /**
+ * Returns server address.
+ *
+ * @return server address
+ */
+ public InetSocketAddress getAddress() {
+ return this.serverAddress;
+ }
+
+ @Override
+ public synchronized void close() throws IOException {
+ for (final Entry<InetSocketAddress, ProtocolSession> s : this.sessions.entrySet()) {
+ s.getValue().close();
+ }
+ this.sessions.clear();
+ this.dispatcher.removeServer(this);
+ this.channel.close();
+ logger.debug("Server {} closed.", this);
+ }
+
+ @Override
+ public synchronized void onSessionClosed(final ProtocolSession session) {
+ this.sessions.inverse().remove(session); // when the session is closed, the key is the instance of the session
+ this.dispatcher.closeSessionSockets(session);
+ }
+
+ @Override
+ public void checkOutputBuffer(final ProtocolSession session) {
+ this.dispatcher.checkOutputBuffer(session);
+ }
+
+ private static int getNextId(Integer lastId, final int maxId) {
+ return (lastId == null || maxId == lastId) ? 0 : ++lastId;
+ }
+
+ /**
+ * Compares byte array representations of two InetAddresses.
+ *
+ * @param addrOne
+ * @param addrTwo
+ * @throws IllegalArgumentException if InetAddresses don't belong to the same subclass of InetAddress.
+ * @return 1 if addrOne is greater than addrTwo, 0 if they are the same, -1 if addrOne is lower than addrTwo
+ */
+ private static int compareTo(final InetAddress addrOne, final InetAddress addrTwo) {
+ if ((addrOne instanceof Inet4Address && addrOne instanceof Inet6Address)
+ || (addrOne instanceof Inet6Address && addrOne instanceof Inet4Address)) {
+ throw new IllegalArgumentException("Cannot compare InetAddresses. They both have to be the same subclass of InetAddress.");
+ }
+ final byte[] byteOne = addrOne.getAddress();
+ final byte[] byteTwo = addrTwo.getAddress();
+ for (int i = 0; i < byteOne.length; i++) {
+ if (byteOne[i] > byteTwo[i])
+ return 1;
+ else if (byteOne[i] < byteTwo[i])
+ return -1;
+ }
+ return 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * Protocol Session represents the finite state machine in underlying
+ * protocol, including timers and its purpose is to create a connection
+ * between server and client. Session is automatically started, when TCP
+ * connection is created, but can be stopped manually.
+ * If the session is up, it has to redirect messages to/from user.
+ * Handles also malformed messages and unknown requests.
+ *
+ * This interface should be implemented by a final class representing
+ * a protocol specific session.
+ */
+public interface ProtocolSession extends Closeable {
+
+ /**
+ * Starts the session. This method should be used only internally by
+ * the Dispatcher.
+ */
+ public void startSession();
+
+ /**
+ * Returns underlying output stream to provide writable stream to the
+ * Dispatcher.
+ * @return underlying protocol specific output stream
+ */
+ public ProtocolOutputStream getStream();
+
+ /**
+ * Handles incoming message (parsing, reacting if necessary).
+ * @param msg incoming message
+ */
+ public void handleMessage(final ProtocolMessage msg);
+
+ /**
+ * Handles malformed message when a deserializer exception occurred.
+ * The handling might be different from when a documented exception
+ * is thrown.
+ * @param e deserializer exception that occurred
+ */
+ public void handleMalformedMessage(final DeserializerException e);
+
+ /**
+ * Handles malformed message when a documented exception occurred.
+ * The handling might be different from when a deserializer exception
+ * is thrown.
+ * @param e documented exception that occurred
+ */
+ public void handleMalformedMessage(final DocumentedException e);
+
+ /**
+ * Called when reached the end of input stream while reading.
+ */
+ public void endOfInput();
+
+ /**
+ * Getter for message factory
+ * @return protocol specific message factory
+ */
+ public ProtocolMessageFactory getMessageFactory();
+
+ /**
+ * Session is notified about the connection not being
+ * established successfully.
+ *
+ * @param e IOException that was the cause of
+ * failed connection.
+ */
+ public void onConnectionFailed(final IOException e);
+
+ /**
+ * Returns the maximum message size (in bytes) for purposes of dispatcher
+ * buffering -- the dispatcher allocates a buffer this big, and if it gets
+ * full without making decoding progress, the dispatcher terminates the
+ * session.
+ *
+ * @return maximum message size
+ */
+ public int maximumMessageSize();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.util.Timer;
+
+/**
+ * Factory for generating Protocol Sessions. This class should be extended to
+ * return protocol specific session.
+ */
+public interface ProtocolSessionFactory {
+
+ /**
+ * Creates and returns protocol specific session.
+ * @param parent SessionParent
+ * @param timer Timer
+ * @param connection connection attributes
+ * @param sessionId session identifier
+ * @return new session
+ */
+ public ProtocolSession getProtocolSession(SessionParent parent, Timer timer, ProtocolConnection connection, int sessionId);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+/**
+ * As in order to work with SSLSelectionKey, a channel needs to implement
+ * this interface. It is used to determine SSL progress and update interestOps
+ * of underlying channel.
+ */
+interface SSLSelectableChannel {
+ /**
+ * Return the events which the underlying channel should be selected for,
+ * based on what the user would like to see from us.
+ *
+ * @param ops user's interest ops
+ * @return Calculated interest ops, including internal needs
+ */
+ public int computeInterestOps(final int ops);
+
+ /**
+ * Return a freshly-calculated operations which the channel is ready to
+ * make progress on.
+ *
+ * @return Calculated ready ops
+ */
+ public int computeReadyOps();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectionKey;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class SSLSelectionKey extends AbstractSelectionKey {
+ private static final Logger logger = LoggerFactory.getLogger(SSLSelectionKey.class);
+ private final SelectableChannel channel;
+ private final Selector selector;
+ private final SelectionKey key;
+ private int ops = 0, readyOps = 0;
+
+ SSLSelectionKey(final Selector selector, final SelectionKey key, final SelectableChannel channel) {
+ this.selector = selector;
+ this.channel = channel;
+ this.key = key;
+ }
+
+ @Override
+ public SelectableChannel channel() {
+ return channel;
+ }
+
+ @Override
+ public int interestOps() {
+ return ops;
+ }
+
+ @Override
+ public SelectionKey interestOps(final int ops) {
+ this.ops = ops;
+ return this;
+ }
+
+ @Override
+ public int readyOps() {
+ return readyOps;
+ }
+
+ @Override
+ public Selector selector() {
+ return selector;
+ }
+
+ void cancelSlave() {
+ key.cancel();
+ }
+
+ void updateInterestOps() {
+ int newOps = ops;
+
+ if (channel instanceof SSLSocketChannel) {
+ newOps = ((SSLSocketChannel)channel).computeInterestOps(ops);
+ } else if (channel instanceof SSLServerSocketChannel) {
+ newOps = ((SSLServerSocketChannel)channel).computeInterestOps(ops);
+ }
+
+ logger.trace("Updating interestOps to {} (before SSL={})", newOps, ops);
+
+ // FIXME: is this check sufficient?
+ if (key.isValid())
+ key.interestOps(newOps);
+ }
+
+ boolean preselectReady() {
+ final int newReadyOps;
+
+ // FIXME: abstract out interface
+ if (channel instanceof SSLSocketChannel) {
+ final SSLSocketChannel sc = (SSLSocketChannel)channel;
+ newReadyOps = sc.computeReadyOps();
+
+ if (sc.hasParent()) {
+ logger.trace("Child key, ready {}", newReadyOps);
+ if ((newReadyOps & SelectionKey.OP_CONNECT) != 0) {
+ try {
+ if (sc.finishConnect()) {
+ this.cancel();
+ return true;
+ } else
+ logger.trace("finishConnect indicated non-connect after poll. Possible leak.");
+ } catch (IOException e) {
+ logger.trace("Failed to establish child socket", e);
+ this.cancel();
+ }
+ }
+ return false;
+ }
+ } else if (channel instanceof SSLServerSocketChannel) {
+ newReadyOps = ((SSLServerSocketChannel)channel).computeReadyOps();
+ } else
+ newReadyOps = 0;
+
+ logger.trace("Preselect: ready {} interest {} (A: {} R: {} W: {})",
+ newReadyOps, ops, SelectionKey.OP_CONNECT, SelectionKey.OP_READ, SelectionKey.OP_WRITE);
+ return (newReadyOps & ops) != 0;
+ }
+
+ boolean updateReadyOps() {
+ int newReadyOps = 0;
+ if (channel instanceof SSLServerSocketChannel) {
+ newReadyOps = ((SSLServerSocketChannel)channel).computeReadyOps();
+ } else if (channel instanceof SSLSocketChannel) {
+ final SSLSocketChannel sc = (SSLSocketChannel)channel;
+
+ // Do not report events for internal channels
+ if (!sc.hasParent())
+ newReadyOps = sc.computeReadyOps();
+ } else {
+ try {
+ newReadyOps = key.readyOps();
+ } catch (CancelledKeyException e) {
+ logger.trace("Encountered cancelled key, ignoring", e);
+ }
+ }
+
+ if (readyOps == newReadyOps)
+ return false;
+
+ logger.trace("Updating readyOps from {} to {}", readyOps, newReadyOps);
+ readyOps = newReadyOps;
+ return true;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.util.Collections;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.RemoveOnlySet;
+import com.google.common.collect.Sets;
+
+class SSLSelector extends AbstractSelector {
+ private static final Logger logger = LoggerFactory.getLogger(SSLSelector.class);
+ private final Set<SelectionKey> selectedKeys = Sets.newHashSet();
+ private final Set<SelectionKey> keys = Sets.newCopyOnWriteArraySet();
+
+ private final Set<SelectionKey> guardedSelectedKeys = RemoveOnlySet.wrap(selectedKeys);
+ private final Set<SelectionKey> guardedKeys = Collections.unmodifiableSet(keys);
+ private final Selector selector;
+ private boolean closed = false;
+
+ SSLSelector(final Selector selector) throws IOException {
+ super(selector.provider());
+ this.selector = selector;
+ }
+
+ @Override
+ protected void implCloseSelector() throws IOException {
+ // Make sure selection won't block
+ selector.wakeup();
+
+ synchronized (this) {
+ if (!closed) {
+ closed = true;
+ for (SelectionKey k : keys)
+ k.cancel();
+
+ keys.clear();
+ selector.close();
+ }
+ }
+ }
+
+ @Override
+ protected synchronized SelectionKey register(final AbstractSelectableChannel ch, final int ops, final Object att) {
+ ensureOpen();
+
+ final AbstractSelectableChannel slave;
+ if (ch instanceof SSLServerSocketChannel)
+ slave = ((SSLServerSocketChannel)ch).channel;
+ else if (ch instanceof SSLSocketChannel)
+ slave = ((SSLSocketChannel)ch).channel;
+ else
+ slave = ch;
+
+ logger.trace("Register channel {} slave {} with ops {}", ch, slave, ops);
+
+ final SelectionKey key;
+ try {
+ key = new SSLSelectionKey(this, slave.register(selector, 0, null), ch);
+ } catch (ClosedChannelException e) {
+ throw new IllegalStateException("Slave selector found the channel closed", e);
+ }
+ key.interestOps(ops);
+ key.attach(att);
+ keys.add(key);
+ return key;
+ }
+
+ @Override
+ public synchronized Set<SelectionKey> keys() {
+ ensureOpen();
+ return guardedKeys;
+ }
+
+ private void ensureOpen() {
+ if (closed)
+ throw new ClosedSelectorException();
+ }
+
+ private int afterSelect() {
+ logger.trace("Running afterSelect");
+ int ret = 0;
+
+ final Set<SelectionKey> ck = cancelledKeys();
+ synchronized (ck) {
+ selectedKeys.removeAll(ck);
+
+ for (final SelectionKey k : keys) {
+ final boolean updated = ((SSLSelectionKey)k).updateReadyOps();
+ if ((k.readyOps() & k.interestOps()) != 0) {
+ selectedKeys.add(k);
+ if (updated)
+ ++ret;
+ } else
+ selectedKeys.remove(k);
+ }
+ }
+
+ return ret;
+ }
+
+ private boolean beforeSelect() {
+ logger.trace("Running beforeSelect");
+
+ final Set<SelectionKey> ck = cancelledKeys();
+ synchronized (ck) {
+ for (final SelectionKey k : ck)
+ ((SSLSelectionKey)k).cancelSlave();
+ selectedKeys.removeAll(ck);
+ keys.removeAll(ck);
+ ck.clear();
+
+ for (final SelectionKey k : keys) {
+ final SSLSelectionKey sk = (SSLSelectionKey)k;
+ if (sk.preselectReady()) {
+ logger.trace("Key {} ready in preselect", k);
+ return true;
+ } else
+ sk.updateInterestOps();
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public synchronized int select() throws IOException {
+ return select(0);
+ }
+
+ @Override
+ public synchronized int select(final long timeout) throws IOException {
+ ensureOpen();
+
+ if (!beforeSelect()) {
+ try {
+ begin();
+ selector.select(timeout);
+ } finally {
+ end();
+ }
+ }
+ return afterSelect();
+ }
+
+ @Override
+ public synchronized int selectNow() throws IOException {
+ ensureOpen();
+
+ if (!beforeSelect())
+ selector.selectNow();
+ return afterSelect();
+ }
+
+ @Override
+ public synchronized Set<SelectionKey> selectedKeys() {
+ ensureOpen();
+ return guardedSelectedKeys;
+ }
+
+ @Override
+ public Selector wakeup() {
+ logger.trace("Running wakeup");
+ selector.wakeup();
+ return this;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+import javax.net.ssl.SSLContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Queues;
+
+/**
+ * SSL-enabled equivalent of ServerSocketChannel. This class uses a backend
+ * ServerSocketChannel to implement network functionality. Each instance is
+ * bound to a SSLContext, which is used to create a per-connection SSLEngine,
+ * which is encapsulated into the returned SSLSocketChannel.
+ */
+final class SSLServerSocketChannel extends ServerSocketChannel implements SSLSelectableChannel {
+ private static final Logger logger = LoggerFactory.getLogger(SSLServerSocketChannel.class);
+ private final Queue<SocketChannel> newChannels = Queues.newArrayDeque();
+ private final SSLContext context;
+ private final Executor executor;
+ private final Selector selector;
+ private boolean closed = false;
+
+ protected final ServerSocketChannel channel;
+
+ private SSLServerSocketChannel(final Selector selector, final ServerSocketChannel channel, final SSLContext context, final Executor executor) {
+ super(channel.provider());
+ this.selector = selector;
+ this.executor = executor;
+ this.channel = channel;
+ this.context = context;
+ }
+
+ public static SSLServerSocketChannel open(final Selector selector, final SSLContext context, final Executor executor) throws IOException {
+ return new SSLServerSocketChannel(selector, ServerSocketChannel.open(), context, executor);
+ }
+
+ @Override
+ public final synchronized SocketChannel accept() {
+ return newChannels.poll();
+ }
+
+ @Override
+ public ServerSocket socket() {
+ // We do not support this operation, everyone should use Java 7 interfaces
+ throw new UnsupportedOperationException("SSLSocketChannel does not provide a fake Socket implementation");
+ }
+
+ @Override
+ protected synchronized void implCloseSelectableChannel() throws IOException {
+ closed = true;
+ while (!newChannels.isEmpty()) {
+ final SocketChannel c = newChannels.poll();
+ try {
+ c.close();
+ } catch (IOException e) {
+ logger.trace("Failed to close a queued channel", e);
+ }
+ }
+ channel.close();
+ }
+
+ @Override
+ protected void implConfigureBlocking(final boolean block) throws IOException {
+ channel.configureBlocking(block);
+ }
+
+ @Override
+ public final synchronized int computeInterestOps(final int ops) {
+ // We are always interested in accepting stuff
+ return SelectionKey.OP_ACCEPT;
+ }
+
+ private void performIO() {
+ while (true) {
+ final SocketChannel newchan;
+ try {
+ newchan = channel.accept();
+ if (newchan == null)
+ break;
+ } catch (IOException e) {
+ logger.trace("Underlying accept() failed", e);
+ return;
+ }
+
+ try {
+ final SocketChannel sc;
+ try {
+ sc = SSLSocketChannel.open(newchan, context, executor, this);
+ } catch (IOException e) {
+ logger.trace("Failed to create SSL channel", e);
+ newchan.close();
+ continue;
+ }
+
+ try {
+ sc.configureBlocking(false);
+ sc.register(selector, SelectionKey.OP_CONNECT, null);
+ } catch (IOException e) {
+ logger.trace("Failed to register SSL channel", e);
+ sc.close();
+ continue;
+ }
+
+ logger.trace("Accepted new connection, channel is {} backend {}", sc, newchan);
+ } catch (IOException e1) {
+ logger.trace("Failed to close failed channel", e1);
+ }
+ }
+ }
+
+ @Override
+ public final synchronized int computeReadyOps() {
+ if (closed)
+ return 0;
+
+ performIO();
+
+ // We need to be non-closed and have enqueue channels to be ready
+ if (!closed && !newChannels.isEmpty())
+ return SelectionKey.OP_ACCEPT;
+ return 0;
+ }
+
+ /**
+ * Enqueue a freshly-established child channel for reporting as
+ * a ready-to-accept connection.
+ *
+ * @param channel Fresh channel, expected to be in connected state
+ */
+ final synchronized void addNewChannel(final SocketChannel channel) {
+ if (closed) {
+ try {
+ channel.close();
+ } catch (IOException e) {
+ logger.trace("Failed to close a queued channel", e);
+ }
+ } else
+ newChannels.add(channel);
+ }
+
+ @Override
+ public SocketAddress getLocalAddress() throws IOException {
+ return channel.getLocalAddress();
+ }
+
+ @Override
+ public <T> T getOption(SocketOption<T> name) throws IOException {
+ return channel.getOption(name);
+ }
+
+ @Override
+ public Set<SocketOption<?>> supportedOptions() {
+ return channel.supportedOptions();
+ }
+
+ @Override
+ public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
+ channel.bind(local, backlog);
+ return this;
+ }
+
+ @Override
+ public <T> ServerSocketChannel setOption(SocketOption<T> name, T value) throws IOException {
+ channel.setOption(name, value);
+ return this;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketOption;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*
+ * Base class for an SSL-enabled socket channel. It is completed as
+ * SSLSocketChannel in one of the two Java version-specific files.
+ */
+final class SSLSocketChannel extends SocketChannel implements SSLSelectableChannel {
+ private enum InternalState {
+ /**
+ * Freshly created socket. Must be connected.
+ */
+ IDLE,
+ /**
+ * Underlying TCP connection is being established.
+ */
+ CONNECTING,
+ /**
+ * Underlying TCP connection is established, we are currently
+ * negotiating SSL session parameters.
+ */
+ NEGOTIATING,
+ /**
+ * Connection attempt has been resolved, we need the user
+ * to call finishConnect().
+ */
+ CONNECT_RESOLVED,
+ /**
+ * We have notified the user that the connection has failed,
+ * all we need to do is cleanup resources.
+ */
+ CONNECT_FAILED,
+ /**
+ * We have notified user that the connection has been
+ * established and the channel is fully operational.
+ */
+ CONNECTED,
+ /**
+ * We are closing down the channel. From user's perspective
+ * it is already dead, we just need to cleanup.
+ */
+ CLOSING,
+ /**
+ * The channel has been closed and all resources released.
+ */
+ CLOSED,
+ }
+
+ private static final Logger logger = LoggerFactory.getLogger(SSLSocketChannel.class);
+ private SSLServerSocketChannel parent;
+ final SocketChannel channel;
+ final SSLEngine engine;
+
+ private final ByteBuffer fromNetwork, toNetwork, toUser;
+ private final ByteBuffer empty = ByteBuffer.allocate(0);
+ private final Executor executor;
+ private IOException connectResult = null;
+ private IOException writeFailed = null, closeFailed = null;
+ private boolean readDone = false;
+ private boolean closedInput = false, closedOutput = false;
+ private InternalState state;
+
+ private SSLSocketChannel(final SocketChannel channel, final SSLEngine engine,
+ final Executor executor, final SSLServerSocketChannel parent) throws SSLException {
+ super(channel.provider());
+ this.executor = executor;
+ this.channel = channel;
+ this.parent = parent;
+ this.engine = engine;
+
+ final SSLSession session = engine.getSession();
+ fromNetwork = ByteBuffer.allocate(session.getPacketBufferSize());
+ fromNetwork.limit(0);
+ toNetwork = ByteBuffer.allocate(session.getPacketBufferSize());
+ toNetwork.limit(0);
+ toUser = ByteBuffer.allocate(session.getApplicationBufferSize());
+
+ if (parent != null) {
+ engine.setUseClientMode(false);
+ engine.setWantClientAuth(true);
+ engine.setNeedClientAuth(false);
+ engine.beginHandshake();
+ state = InternalState.NEGOTIATING;
+ } else
+ state = InternalState.IDLE;
+ }
+
+ public static SSLSocketChannel open(final SocketChannel channel, final SSLContext context,
+ final Executor executor, final SSLServerSocketChannel parent) throws IOException {
+
+ return new SSLSocketChannel(channel, context.createSSLEngine(), executor, parent);
+ }
+
+ @Override
+ public synchronized boolean connect(final SocketAddress remote) throws IOException {
+ switch (state) {
+ case CLOSED:
+ case CLOSING:
+ case CONNECT_FAILED:
+ throw new ClosedChannelException();
+ case CONNECTED:
+ throw new AlreadyConnectedException();
+ case CONNECTING:
+ case CONNECT_RESOLVED:
+ case NEGOTIATING:
+ throw new ConnectionPendingException();
+ case IDLE:
+ if (channel.connect(remote)) {
+ engine.setUseClientMode(true);
+ engine.beginHandshake();
+ state = InternalState.NEGOTIATING;
+ } else
+ state = InternalState.CONNECTING;
+ return false;
+ }
+
+ throw new IllegalStateException("Unhandled state " + state);
+ }
+
+ @Override
+ public synchronized boolean finishConnect() throws IOException {
+ logger.trace("Attempting to finish connection in state {}", state);
+
+ switch (state) {
+ case CLOSED:
+ case CLOSING:
+ case CONNECT_FAILED:
+ throw new ClosedChannelException();
+ case CONNECTED:
+ return true;
+ case CONNECT_RESOLVED:
+ if (connectResult != null) {
+ state = InternalState.CONNECT_FAILED;
+ try {
+ logger.trace("Internal close after failed connect");
+ close();
+ } catch (IOException e) {
+ logger.trace("Failed to invoked internal close", e);
+ }
+ throw connectResult;
+ }
+
+ state = InternalState.CONNECTED;
+ if (parent != null) {
+ parent.addNewChannel(this);
+ parent = null;
+ }
+ return true;
+ case CONNECTING:
+ case NEGOTIATING:
+ return false;
+ case IDLE:
+ throw new NoConnectionPendingException();
+ }
+
+ throw new IllegalStateException("Unhandled state " + state);
+ }
+
+ @Override
+ public synchronized boolean isConnected() {
+ return state == InternalState.CONNECTED;
+ }
+
+ @Override
+ public synchronized boolean isConnectionPending() {
+ switch (state) {
+ case CONNECTING:
+ case CONNECT_RESOLVED:
+ case NEGOTIATING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private int readNetwork() throws IOException {
+ fromNetwork.compact();
+
+ final int ret;
+ try {
+ ret = channel.read(fromNetwork);
+ } finally {
+ fromNetwork.flip();
+ }
+
+ logger.trace("Channel {} has input {} after {}", this, fromNetwork.remaining(), ret);
+ return ret;
+ }
+
+ private int writeNetwork() throws IOException {
+ toNetwork.flip();
+
+ final int ret;
+ try {
+ ret = channel.write(toNetwork);
+ } finally {
+ toNetwork.compact();
+ }
+
+ logger.trace("Channel {} has output {} after {}", this, toNetwork.remaining(), ret);
+ return ret;
+ }
+
+ private void checkChannelState() throws IOException {
+ switch (state) {
+ case CLOSED:
+ case CLOSING:
+ case CONNECT_FAILED:
+ throw new ClosedChannelException();
+ case CONNECTED:
+ break;
+ case CONNECT_RESOLVED:
+ case CONNECTING:
+ case IDLE:
+ case NEGOTIATING:
+ throw new NotYetConnectedException();
+ }
+ }
+
+ private boolean checkReadState() throws IOException {
+ checkChannelState();
+ return closedInput;
+ }
+
+ @Override
+ public synchronized int read(final ByteBuffer dst) throws IOException {
+ if (checkReadState())
+ return -1;
+
+ /*
+ * If we have some data overflowed from negotiation, flush that
+ * first.
+ */
+ if (toUser.position() != 0) {
+ logger.trace("toUser has {}", toUser.position());
+ toUser.flip();
+
+ final int xfer = Math.min(toUser.remaining(), dst.remaining());
+ dst.put(toUser.array(), toUser.arrayOffset() + toUser.position(), xfer);
+ toUser.position(toUser.position() + xfer);
+ toUser.compact();
+ return xfer;
+ }
+
+ // We have input data, unwrap it
+ if (fromNetwork.hasRemaining()) {
+ final SSLEngineResult res = engine.unwrap(fromNetwork, dst);
+ return res.bytesProduced();
+ }
+
+ // EOF on underlying stream, inform the engine
+ if (readDone)
+ engine.closeInbound();
+
+ // SSL engine says there may be some more input
+ if (!engine.isInboundDone())
+ return 0;
+
+ logger.trace("SSL engine indicates clean shutdown");
+ return -1;
+ }
+
+ @Override
+ public synchronized long read(final ByteBuffer[] dsts, final int offset, final int length) throws IOException {
+ if (checkReadState())
+ return -1;
+
+ /*
+ * Search for the first buffer with available data and perform
+ * a single-buffer read into it. Not completely efficient, but
+ * does the work required.
+ */
+ for (int i = offset; i < length; ++i)
+ if (dsts[i].remaining() != 0)
+ return read(dsts[i]);
+
+ return 0;
+ }
+
+ @Override
+ public Socket socket() {
+ // We do not support this operation, everyone should use Java 7 interfaces
+ throw new UnsupportedOperationException("SSLSocketChannel does not provide a fake Socket implementation");
+ }
+
+ private void checkWriteState() throws IOException {
+ checkChannelState();
+
+ if (closedOutput)
+ throw new ClosedChannelException();
+
+ if (writeFailed != null)
+ throw writeFailed;
+ }
+
+ @Override
+ public synchronized int write(final ByteBuffer src) throws IOException {
+ checkWriteState();
+
+ final SSLEngineResult res = engine.wrap(src, toNetwork);
+ return res.bytesConsumed();
+ }
+
+ @Override
+ public synchronized long write(final ByteBuffer[] srcs, final int offset, final int length) throws IOException {
+ checkWriteState();
+
+ final SSLEngineResult res = engine.wrap(srcs, offset, length, toNetwork);
+ return res.bytesConsumed();
+ }
+
+ @Override
+ protected synchronized void implCloseSelectableChannel() throws IOException {
+ logger.trace("Closing channel in state {}", state);
+
+ switch (state) {
+ case CONNECTED:
+ state = InternalState.CLOSING;
+ engine.closeOutbound();
+ break;
+ case CLOSED:
+ case CLOSING:
+ // Nothing to do
+ break;
+ case CONNECT_FAILED:
+ case CONNECT_RESOLVED:
+ case CONNECTING:
+ case IDLE:
+ case NEGOTIATING:
+ state = InternalState.CLOSED;
+ channel.close();
+ break;
+ }
+ }
+
+ @Override
+ protected void implConfigureBlocking(final boolean block) throws IOException {
+ channel.configureBlocking(block);
+ }
+
+ @Override
+ public synchronized int computeInterestOps(int userOps) {
+ logger.trace("Interestops in state {} userOps {}", state, userOps);
+
+ int ret = 0;
+
+ switch (state) {
+ case CLOSED:
+ case CONNECT_FAILED:
+ case CONNECT_RESOLVED:
+ case IDLE:
+ return 0;
+ case CLOSING:
+ if (engine.isOutboundDone() && toNetwork.position() == 0)
+ throw new IllegalStateException("Network flush completed, but still in CLOSING state");
+ return SelectionKey.OP_WRITE;
+ case CONNECTING:
+ return SelectionKey.OP_CONNECT;
+ case NEGOTIATING:
+ userOps = 0;
+
+ final HandshakeStatus st = engine.getHandshakeStatus();
+
+ logger.trace("SSL Engine status {}", st);
+
+ switch (st) {
+ case NEED_UNWRAP:
+ userOps = SelectionKey.OP_READ;
+ break;
+ case NEED_WRAP:
+ userOps = SelectionKey.OP_WRITE;
+ break;
+ default:
+ logger.trace("Unexpected SSLEngine handshake status {}", st);
+ connectResult = new IOException("Unexpected SSLEngine handshake status " + st);
+ connectResult.fillInStackTrace();
+ state = InternalState.CONNECT_RESOLVED;
+ return 0;
+ }
+
+ // Intentional fall through
+ case CONNECTED:
+ if ((userOps & SelectionKey.OP_READ) != 0 && !fromNetwork.hasRemaining())
+ ret |= SelectionKey.OP_READ;
+ if ((userOps & SelectionKey.OP_WRITE) != 0 && !toNetwork.hasRemaining())
+ ret |= SelectionKey.OP_WRITE;
+
+ logger.trace("userOps {} fromNetwork {} toNetwork {} ret {}", userOps, fromNetwork.remaining(), toNetwork.remaining(), ret);
+ return ret;
+ }
+
+ throw new IllegalStateException("Unhandled state " + state);
+ }
+
+ private void performIO() {
+ logger.trace("IO operations in state {}", state);
+
+ switch (state) {
+ case CLOSED:
+ case CONNECT_RESOLVED:
+ case IDLE:
+ // Nothing to do
+ break;
+ case CLOSING:
+ boolean forceClose = false;
+ if (!engine.isOutboundDone()) {
+ try {
+ engine.wrap(empty, toNetwork);
+ } catch (SSLException e) {
+ logger.trace("Failed to close down SSL engine outbound", e);
+ }
+ }
+
+ if (toNetwork.position() != 0) {
+ try {
+ writeNetwork();
+ } catch (IOException e) {
+ logger.trace("Failed to flush outstanding buffers, forcing close", e);
+ forceClose = true;
+ }
+ }
+
+ if (forceClose || (engine.isOutboundDone() && toNetwork.position() == 0)) {
+ logger.trace("Completed state flush");
+ state = InternalState.CLOSED;
+ try {
+ channel.close();
+ } catch (IOException e) {
+ logger.trace("Failed to close slave channel", e);
+ }
+ }
+ break;
+ case CONNECT_FAILED:
+ try {
+ logger.trace("Invoking internal close after failure");
+ close();
+ } catch (IOException e) {
+ logger.trace("Internal fail closed", e);
+ }
+ break;
+ case CONNECTED:
+ try {
+ if (!readDone && readNetwork() < 0) {
+ readDone = true;
+ try {
+ engine.closeInbound();
+ } catch (IOException e) {
+ logger.trace("TLS reported close error", e);
+ closeFailed = e;
+ }
+ }
+ } catch (IOException e) {
+ logger.trace("Background read failed", e);
+ readDone = true;
+ }
+
+ try {
+ if (toNetwork.position() != 0)
+ writeNetwork();
+ } catch (IOException e) {
+ logger.trace("Background write failed", e);
+ writeFailed = e;
+ toNetwork.clear();
+ }
+ break;
+ case CONNECTING:
+ try {
+ if (channel.finishConnect()) {
+ engine.setUseClientMode(true);
+ engine.beginHandshake();
+ state = InternalState.NEGOTIATING;
+ }
+ } catch (IOException e) {
+ logger.trace("Finished connection with error", e);
+ connectResult = e;
+ state = InternalState.CONNECT_RESOLVED;
+ }
+ break;
+ case NEGOTIATING:
+ boolean needMore = true;
+
+ do {
+ final HandshakeStatus st = engine.getHandshakeStatus();
+ if (st == HandshakeStatus.NEED_TASK) {
+ // Dispatch any blocking tasks that SSLEngine has for us.
+ while (true) {
+ final Runnable r = engine.getDelegatedTask();
+ if (r == null)
+ break;
+
+ executor.execute(r);
+ }
+ continue;
+ }
+
+ try {
+ if (readNetwork() < 0) {
+ logger.trace("Unexpected end of stream during negotiation");
+ connectResult = new EOFException("Unexpected end-of-channel during SSL negotiation");
+ connectResult.fillInStackTrace();
+ state = InternalState.CONNECT_RESOLVED;
+ break;
+ }
+ writeNetwork();
+ } catch (IOException e) {
+ logger.trace("IO error during SSL negotiation", e);
+ connectResult = e;
+ state = InternalState.CONNECT_RESOLVED;
+ break;
+ }
+
+ final SSLEngineResult res;
+ try {
+ logger.trace("Status {} fromNetwork {} toNetwork {} toUser {}", st, fromNetwork.remaining(), toNetwork.remaining(), toUser.remaining());
+
+ if (st == HandshakeStatus.NEED_UNWRAP) {
+ // SSLEngine needs to read some data from the network
+ res = engine.unwrap(fromNetwork, toUser);
+ if (res.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW)
+ needMore = false;
+ } else if (st == HandshakeStatus.NEED_WRAP) {
+ // SSLEngine needs to write some data to the network
+ res = engine.wrap(empty, toNetwork);
+ if (res.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW)
+ needMore = false;
+ } else {
+ logger.trace("Unexpected state {} in SSL negotiation", engine.getHandshakeStatus());
+ connectResult = new IOException("Unexpected SSL negotiation state");
+ connectResult.fillInStackTrace();
+ state = InternalState.CONNECT_RESOLVED;
+ break;
+ }
+ } catch (SSLException e) {
+ logger.trace("SSL negotiation failed", e);
+ connectResult = e;
+ state = InternalState.CONNECT_RESOLVED;
+ break;
+ }
+
+ logger.trace("SSL needMore {} result {}", needMore, res);
+
+ if (res.getHandshakeStatus() == HandshakeStatus.FINISHED) {
+ final SSLSession s = engine.getSession();
+ logger.trace("SSL session established: {}", s);
+ state = InternalState.CONNECT_RESOLVED;
+ break;
+ }
+ } while (needMore);
+ }
+ }
+
+ @Override
+ public synchronized int computeReadyOps() {
+ performIO();
+
+ logger.trace("Readyops in state {}", state);
+
+ switch (state) {
+ case CLOSED:
+ case CLOSING:
+ case CONNECT_FAILED:
+ case CONNECTING:
+ case IDLE:
+ case NEGOTIATING:
+ return 0;
+ case CONNECT_RESOLVED:
+ return SelectionKey.OP_CONNECT;
+ case CONNECTED:
+ int ret = 0;
+
+ if (toNetwork.hasRemaining() || writeFailed != null)
+ ret |= SelectionKey.OP_WRITE;
+ if (fromNetwork.hasRemaining() || toUser.position() != 0)
+ ret |= SelectionKey.OP_READ;
+
+ return ret;
+ }
+
+ throw new IllegalStateException("Unhandled state " + state);
+ }
+
+ @Override
+ public SocketChannel bind(final SocketAddress local) throws IOException {
+ channel.bind(local);
+ return this;
+ }
+
+ @Override
+ public SocketAddress getLocalAddress() throws IOException {
+ return channel.getLocalAddress();
+ }
+
+ @Override
+ public SocketAddress getRemoteAddress() throws IOException {
+ return channel.getRemoteAddress();
+ }
+
+ @Override
+ public synchronized SocketChannel shutdownInput() throws IOException {
+ checkChannelState();
+
+ if (!closedInput) {
+ closedInput = true;
+ if (closeFailed != null)
+ throw closeFailed;
+ logger.debug("Socket {} input shut down", this);
+ }
+
+ return this;
+ }
+
+ @Override
+ public synchronized SocketChannel shutdownOutput() throws IOException {
+ checkChannelState();
+
+ if (!closedOutput) {
+ closedOutput = true;
+ engine.closeOutbound();
+ logger.debug("Socket {} output shut down", this);
+ }
+
+ return this;
+ }
+
+ @Override
+ public <T> T getOption(SocketOption<T> name) throws IOException {
+ return channel.getOption(name);
+ }
+
+ @Override
+ public <T> SocketChannel setOption(SocketOption<T> name, T value) throws IOException {
+ channel.setOption(name, value);
+ return this;
+ }
+
+ @Override
+ public Set<SocketOption<?>> supportedOptions() {
+ return channel.supportedOptions();
+ }
+
+ synchronized boolean hasParent() {
+ return parent != null;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.util.EventListener;
+
+/**
+ * Listener that receives session state informations. This interface should be
+ * implemented by a protocol specific abstract class, that is extended by
+ * a final class that implements the methods.
+ */
+public interface SessionListener extends EventListener {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.net.InetAddress;
+
+/**
+ * Factory for generating Session Listeners. Used by a server. This interface should be
+ * implemented by a protocol specific abstract class, that is extended by
+ * a final class that implements the methods.
+ */
+public interface SessionListenerFactory {
+ /**
+ * Returns one session listener
+ * @param address serves as constraint, so that factory is able to
+ * return different listeners for different factories
+ * @return specific session listener
+ */
+ public SessionListener getSessionListener(final InetAddress address);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.Closeable;
+
+/**
+ * Interface that groups together the classes that can create a session (Dispatcher and Server). When a session
+ * is closing, it has to notify its parent about closing. Each parent keeps a Map of its sessions. When some session closes,
+ * it fires onSessionClosed event with its own instance as parameter and the parent of this session will remove it from his map.
+ */
+public interface SessionParent extends Closeable {
+
+ /**
+ * This listener method is called when a session that was created by a class implementing this interface,
+ * is closing. Implementation should remove corresponding session from its list of sessions.
+ * @param session a session that is closing
+ */
+ public void onSessionClosed(final ProtocolSession session);
+
+ /**
+ * This listener method is called when a session has produced some output and the parent needs to react to
+ * it.
+ * @param session a session that has produced output
+ */
+ public void checkOutputBuffer(final ProtocolSession session);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+/**
+ * Marker interface to be implemented by underlying protocol. This object represents
+ * a DTO for all session characteristics, that are negotiated during the protocol
+ * handshake.
+ */
+public interface SessionPreferences {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+/**
+ * Interface to work with session preferences. They need to be
+ * checked during the establishment phase. If they are not
+ * acceptable a new proposal needs to be requested.
+ * This interface should be implemented by a protocol specific
+ * abstract class, that is extended by a final class that implements
+ * the methods.
+ */
+public interface SessionPreferencesChecker {
+
+ /**
+ * Checks session characteristics, if they are acceptable.
+ *
+ * @param openObj
+ * storage for session characteristics
+ * @return true = acceptable, false = negotiable, null = unacceptable
+ * @throws DocumentedException when there is specific protocol error
+ * for rejecting the session characteristics
+ */
+ public Boolean checkSessionCharacteristics(final SessionPreferences openObj) throws DocumentedException;
+
+ /**
+ * In case of negotiable session characteristics, new ones are requested
+ * through this method.
+ *
+ * @param oldOpen old open object with unacceptable session characteristics
+ * @return
+ * <li> new session characteristics wrapped in Open Object
+ * <li> null if there are not available any different acceptable
+ * session characteristics
+ */
+ public SessionPreferences getNewProposal(final SessionPreferences oldOpen);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.net.InetSocketAddress;
+
+/**
+ * Factory for generating Session preferences Checkers. Used by a server.
+ * This interface should be implemented by a protocol specific abstract class,
+ * that is extended by a final class that implements the methods.
+ */
+public interface SessionPreferencesCheckerFactory {
+
+ /**
+ * Returns one session preferences checker.
+ * @param address serves as constraint, so that factory is able to
+ * return different checkers for different clients
+ * @return specific session preferences checker
+ */
+ public SessionPreferencesChecker getPreferencesChecker(final InetSocketAddress address);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+/**
+ * Interface that provides the initial acceptable session characteristics
+ * with which the session should be started. This interface should be
+ * implemented by a protocol specific abstract class, that is extended by
+ * a final class that implements the methods.
+ */
+public interface SessionProposal {
+
+ /**
+ * Returns specific Session Preferences object for this IP address.
+ * @return SessionPreferences DTO with acceptable session characteristics
+ */
+ public SessionPreferences getProposal();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.net.InetSocketAddress;
+
+/**
+ * Factory for generating Session proposals. Used by a server. Interface needs to be implemented
+ * by a protocol specific abstract class that will produce protocol specific Session Proposals.
+ * The abstract class should be extended by the user in order to return particular object.
+ *
+ * Example:
+ *
+ * public abstract class PCEPSessionProposalFactory implements SessionProposalFactory { ... }
+ *
+ * public final class SimplePCEPSessionProposalFactory extends PCEPSessionProposalFactory { ... }
+ */
+public interface SessionProposalFactory {
+
+ /**
+ * Returns session proposal.
+ *
+ * @param address
+ * serves as constraint, so that factory is able to return
+ * different proposals for different addresses
+ * @param sessionId
+ * identifier of the session
+ * @return specific session proposal
+ */
+ public SessionProposal getSessionProposal(final InetSocketAddress address, final int sessionId);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.TimerTask;
+
+/**
+ * DTO object to be attached to socket channel. Contains session and
+ * streams associated with the socket channel.
+ */
+final class SessionStreams {
+
+ private final ProtocolInputStream inputStream;
+
+ private final PipedInputStream pipedInputStream;
+
+ private final PipedOutputStream pipedOutputStream;
+
+ private final ProtocolSession session;
+
+ final ProtocolConnection connection;
+ int connectCount = 0;
+ TimerTask timer = null;
+
+ SessionStreams(PipedOutputStream pipedOutputStream,
+ PipedInputStream pipedInputStream,
+ ProtocolInputStream inputStream,
+ ProtocolSession session, ProtocolConnection connection) {
+ this.pipedOutputStream = pipedOutputStream;
+ this.pipedInputStream = pipedInputStream;
+ this.inputStream = inputStream;
+ this.session = session;
+ this.connection = connection;
+ }
+
+ PipedOutputStream getPipedOutputStream() {
+ return this.pipedOutputStream;
+ }
+
+ PipedInputStream getPipedInputStream() {
+ return this.pipedInputStream;
+ }
+
+ ProtocolInputStream getProtocolInputStream() {
+ return this.inputStream;
+ }
+
+ ProtocolSession getSession() {
+ return this.session;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+/**
+ * Marker interface for grouping session termination cause.
+ */
+public interface TerminationReason {
+
+ /**
+ * Get cause of session termination.
+ * @return human-readable cause.
+ */
+ public String getErrorMessage();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class ComplementaryTest {
+
+ private class ProtocolMessageImpl implements ProtocolMessage {
+
+ private static final long serialVersionUID = 1L;
+ }
+
+ private class ProtocolMessageFactoryImpl implements ProtocolMessageFactory {
+
+ public ProtocolMessageFactoryImpl() {
+
+ }
+
+ @Override
+ public ProtocolMessage parse(final byte[] bytes,
+ final ProtocolMessageHeader msgHeader) throws DeserializerException,
+ DocumentedException {
+ return null;
+ }
+
+ @Override
+ public byte[] put(final ProtocolMessage msg) {
+ return new byte[]{ 12, 13 };
+ }
+ }
+
+ @Test
+ public void testExceptions() {
+ final DeserializerException de = new DeserializerException("some error");
+ final DocumentedException ee = new DocumentedException("some error");
+
+ assertEquals(de.getMessage(), ee.getMessage());
+ }
+
+ @Test
+ public void testProtocolOutputStream() {
+ final ProtocolOutputStream pos = new ProtocolOutputStream();
+ pos.putMessage(new ProtocolMessageImpl(), new ProtocolMessageFactoryImpl());
+ try {
+ pos.putMessage(new ProtocolMessageImpl(), new ProtocolMessageFactory() {
+
+ @Override
+ public byte[] put(final ProtocolMessage msg) {
+ return null;
+ }
+
+ @Override
+ public ProtocolMessage parse(final byte[] bytes, final ProtocolMessageHeader msgHeader)
+ throws DeserializerException, DocumentedException {
+ return null;
+ }
+ });
+ fail("Exception should have occured.");
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Message parsed to null.", e.getMessage());
+ assertEquals(1, pos.getBuffers().size());
+ assertArrayEquals(new byte[] { 12, 13}, pos.getBuffers().peek().array());
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+public class Message implements ProtocolMessage {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String s;
+
+ public Message(final String s) {
+ this.s = s;
+ }
+
+ public String getMessage() {
+ return s;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.nio.ByteBuffer;
+
+import com.google.common.base.Charsets;
+
+public class MessageFactory implements ProtocolMessageFactory {
+
+ @Override
+ public ProtocolMessage parse(byte[] bytes, ProtocolMessageHeader msgHeader)
+ throws DeserializerException, DocumentedException {
+ return new Message(Charsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString());
+ }
+
+ @Override
+ public byte[] put(ProtocolMessage msg) {
+ return ((Message)msg).getMessage().getBytes();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Random;
+import java.util.Timer;
+import java.util.concurrent.Executors;
+
+import javax.net.ssl.SSLContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.util.SSLUtil;
+
+public class SecureServerTest {
+ static final Random rnd = new Random();
+
+ private static final int MAX_MSGSIZE = 500;
+ final SimpleSessionListener pce = new SimpleSessionListener();
+ ProtocolSession session;
+ ProtocolServer server;
+ DispatcherImpl dispatcher;
+ SSLContext context;
+ int port;
+
+ @Before
+ public void setUp() throws Exception {
+ final InputStream keyStore = SecureServerTest.class.getResourceAsStream("/keystore.jks");
+ final InputStream trustStore = SecureServerTest.class.getResourceAsStream("/keystore.jks");
+ this.context = SSLUtil.initializeSecureContext("keystore", keyStore, trustStore, "SunX509");
+ keyStore.close();
+ trustStore.close();
+
+ this.dispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+ this.port = rnd.nextInt(10000) + 20000;
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ this.dispatcher.onSessionClosed(this.session);
+ this.server.close();
+ this.dispatcher.stop();
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testServerConnection() throws Exception {
+
+ this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", this.port), new ProtocolConnectionFactory() {
+ @Override
+ public ProtocolConnection createProtocolConnection(final InetSocketAddress address) {
+ return new ProtocolConnection() {
+ @Override
+ public SessionPreferencesChecker getProposalChecker() {
+ return new SimpleSessionProposalChecker();
+ }
+
+ @Override
+ public SessionPreferences getProposal() {
+ return new SimpleSessionPreferences();
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return address;
+ }
+
+ @Override
+ public SessionListener getListener() {
+ return new SimpleSessionListener();
+ }
+ };
+ }
+ }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY, this.context);
+
+ try {
+ this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", this.port), null, null, null, null);
+ fail("Exception should have occured.");
+ } catch (final IllegalStateException e) {
+ assertTrue(e.getMessage().startsWith("Server with this address:") && e.getMessage().endsWith("was already created."));
+ }
+
+ this.session = this.dispatcher.createClient(new ProtocolConnection() {
+ @Override
+ public SessionPreferencesChecker getProposalChecker() {
+ return new SimpleSessionProposalChecker();
+ }
+
+ @Override
+ public SessionPreferences getProposal() {
+ return new SimpleSessionPreferences();
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return new InetSocketAddress("127.0.0.3", SecureServerTest.this.port);
+ }
+
+ @Override
+ public SessionListener getListener() {
+ return SecureServerTest.this.pce;
+ }
+ }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY, this.context);
+
+ try {
+ this.session = this.dispatcher.createClient(new ProtocolConnection() {
+ @Override
+ public SessionPreferencesChecker getProposalChecker() {
+ return new SimpleSessionProposalChecker();
+ }
+
+ @Override
+ public SessionPreferences getProposal() {
+ return new SimpleSessionPreferences();
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return new InetSocketAddress("127.0.0.3", SecureServerTest.this.port);
+ }
+
+ @Override
+ public SessionListener getListener() {
+ return SecureServerTest.this.pce;
+ }
+ }, null, null, null);
+ fail("Exception should have occured.");
+ } catch (final IllegalStateException e) {
+ assertTrue(e.getMessage().startsWith("Attempt to create duplicate client session to the same address:"));
+ }
+
+ synchronized (this.pce) {
+ while (!this.pce.up)
+ this.pce.wait();
+ }
+ }
+
+ @Test
+ public void testIO() throws IOException, InterruptedException, KeyManagementException, UnrecoverableKeyException,
+ NoSuchAlgorithmException, KeyStoreException, CertificateException {
+ this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", this.port), new ProtocolConnectionFactory() {
+ @Override
+ public ProtocolConnection createProtocolConnection(final InetSocketAddress address) {
+ return new ProtocolConnection() {
+
+ @Override
+ public SessionPreferencesChecker getProposalChecker() {
+ return new SimpleSessionProposalChecker();
+ }
+
+ @Override
+ public SessionPreferences getProposal() {
+ return new SimpleSessionPreferences();
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return address;
+ }
+
+ @Override
+ public SessionListener getListener() {
+ return new SimpleSessionListener();
+ }
+ };
+ }
+ }, new ProtocolSessionFactory() {
+ @Override
+ public ProtocolSession getProtocolSession(final SessionParent parent, final Timer timer, final ProtocolConnection connection,
+ final int sessionId) {
+ return new Session(parent, MAX_MSGSIZE);
+ }
+ }, SimpleInputStream.FACTORY, this.context);
+
+ this.session = this.dispatcher.createClient(new ProtocolConnection() {
+ @Override
+ public SessionPreferencesChecker getProposalChecker() {
+ return new SimpleSessionProposalChecker();
+ }
+
+ @Override
+ public SessionPreferences getProposal() {
+ return new SimpleSessionPreferences();
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return new InetSocketAddress("127.0.0.3", SecureServerTest.this.port);
+ }
+
+ @Override
+ public SessionListener getListener() {
+ return new SimpleSessionListener();
+ }
+ }, new ProtocolSessionFactory() {
+ @Override
+ public ProtocolSession getProtocolSession(final SessionParent parent, final Timer timer, final ProtocolConnection connection,
+ final int sessionId) {
+ return new Session(parent, MAX_MSGSIZE);
+ }
+ }, SimpleInputStream.FACTORY, this.context);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+import org.junit.After;
+import org.junit.Test;
+
+public class ServerTest {
+ private static final int MAX_MSGSIZE = 500;
+ public static final int PORT = 18080;
+
+ DispatcherImpl clientDispatcher, dispatcher;
+
+ final SimpleSessionListener pce = new SimpleSessionListener();
+
+ ProtocolSession session = null;
+
+ ProtocolServer server = null;
+
+ @Test
+ public void testConnectionEstablished() throws Exception {
+ this.dispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+
+ this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", PORT), new ProtocolConnectionFactory() {
+ @Override
+ public ProtocolConnection createProtocolConnection(final InetSocketAddress address) {
+
+ return new ProtocolConnection() {
+ @Override
+ public SessionPreferencesChecker getProposalChecker() {
+ return new SimpleSessionProposalChecker();
+ }
+
+ @Override
+ public SessionPreferences getProposal() {
+ return new SimpleSessionPreferences();
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return address;
+ }
+
+ @Override
+ public SessionListener getListener() {
+ return new SimpleSessionListener();
+ }
+ };
+ }
+ }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY);
+
+ try {
+ this.server = this.dispatcher.createServer(new InetSocketAddress("127.0.0.3", PORT), null, null, null);
+ fail("Exception should have occured.");
+ } catch (final IllegalStateException e) {
+ assertTrue(e.getMessage().startsWith("Server with this address:") && e.getMessage().endsWith("was already created."));
+ }
+
+ this.clientDispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+
+ this.session = this.clientDispatcher.createClient(new ProtocolConnection() {
+ @Override
+ public SessionPreferencesChecker getProposalChecker() {
+ return new SimpleSessionProposalChecker();
+ }
+
+ @Override
+ public SessionPreferences getProposal() {
+ return new SimpleSessionPreferences();
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return new InetSocketAddress("127.0.0.3", PORT);
+ }
+
+ @Override
+ public SessionListener getListener() {
+ return ServerTest.this.pce;
+ }
+ }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY);
+
+ final int maxAttempts = 1000;
+ int attempts = 0;
+ synchronized (this.pce) {
+ while (!this.pce.up && ++attempts < maxAttempts) {
+ this.pce.wait(100);
+ }
+ }
+ assertTrue(this.pce.up);
+ }
+
+ @Test
+ public void testConnectionFailed() throws IOException, InterruptedException {
+ this.dispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+ this.clientDispatcher = new DispatcherImpl(Executors.defaultThreadFactory());
+
+ this.session = this.clientDispatcher.createClient(new ProtocolConnection() {
+ @Override
+ public SessionPreferencesChecker getProposalChecker() {
+ return new SimpleSessionProposalChecker();
+ }
+
+ @Override
+ public SessionPreferences getProposal() {
+ return new SimpleSessionPreferences();
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return new InetSocketAddress("127.0.0.3", PORT);
+ }
+
+ @Override
+ public SessionListener getListener() {
+ return ServerTest.this.pce;
+ }
+ }, new SimpleSessionFactory(MAX_MSGSIZE), SimpleInputStream.FACTORY);
+ final int maxAttempts = 1000;
+ int attempts = 0;
+ synchronized (this.pce) {
+ while (!this.pce.failed && ++attempts < maxAttempts) {
+ this.pce.wait(100);
+ }
+ }
+ assertTrue(this.pce.failed);
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ this.dispatcher.onSessionClosed(this.session);
+ if (this.server != null)
+ this.server.close();
+ this.dispatcher.stop();
+ this.clientDispatcher.stop();
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+public class Session implements ProtocolSession {
+
+ private static final Logger logger = LoggerFactory.getLogger(Session.class);
+
+ private final ProtocolOutputStream pos;
+
+ public final List<ProtocolMessage> msgs = Lists.newArrayList();
+
+ private final ProtocolMessageFactory pmf = new MessageFactory();
+
+ private final SessionParent parent;
+
+ public boolean up = false;
+
+ private final int maxMsgSize;
+
+ public Session(final SessionParent parent, final int maxMsgSize) {
+ this.pos = new ProtocolOutputStream();
+ this.parent = parent;
+ this.maxMsgSize = maxMsgSize;
+ }
+
+ @Override
+ public void close() throws IOException {
+
+ }
+
+ @Override
+ public void startSession() {
+ this.pos.putMessage(new Message("hello"), this.pmf);
+ this.parent.checkOutputBuffer(this);
+ }
+
+ @Override
+ public ProtocolOutputStream getStream() {
+ return this.pos;
+ }
+
+ @Override
+ public void handleMessage(ProtocolMessage msg) {
+ logger.debug("Message received: {}", ((Message)msg).getMessage());
+ this.up = true;
+ this.msgs.add(msg);
+ logger.debug(this.msgs.size() + "");
+ }
+
+ @Override
+ public void handleMalformedMessage(DeserializerException e) {
+ logger.debug("Malformed message: {}", e.getMessage(), e);
+ }
+
+ @Override
+ public void handleMalformedMessage(DocumentedException e) {
+ logger.debug("Malformed message: {}", e.getMessage(), e);
+ }
+
+ @Override
+ public void endOfInput() {
+ logger.debug("End of input reported.");
+ }
+
+ @Override
+ public ProtocolMessageFactory getMessageFactory() {
+ return null;
+ }
+
+ @Override
+ public void onConnectionFailed(IOException e) {
+ logger.debug("Connection failed: {}", e.getMessage(), e);
+ }
+
+ @Override
+ public int maximumMessageSize() {
+ return maxMsgSize;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+
+public class SimpleInputStream implements ProtocolInputStream {
+ public static final ProtocolInputStreamFactory FACTORY = new ProtocolInputStreamFactory() {
+ @Override
+ public ProtocolInputStream getProtocolInputStream(final PipedInputStream pis, final ProtocolMessageFactory pmf) {
+ return new SimpleInputStream();
+ }
+ };
+
+ private SimpleInputStream() {
+ }
+
+ @Override
+ public boolean isMessageAvailable() throws IOException {
+ return true;
+ }
+
+ @Override
+ public ProtocolMessage getMessage() throws DeserializerException, IOException, DocumentedException {
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+public class SimpleMessageFactory implements ProtocolMessageFactory {
+
+ @Override
+ public ProtocolMessage parse(byte[] bytes, ProtocolMessageHeader msgHeader)
+ throws DeserializerException, DocumentedException {
+ return null;
+ }
+
+ @Override
+ public byte[] put(ProtocolMessage msg) {
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+
+public final class SimpleSession implements ProtocolSession {
+
+ private final SessionListener listener;
+
+ private final SessionParent d;
+
+ private final int maxMsgSize;
+
+ public SimpleSession(ProtocolConnection connection, SessionParent d, int maxMsgSize) {
+ this.listener = connection.getListener();
+ this.d = d;
+ this.maxMsgSize = maxMsgSize;
+ }
+
+ @Override
+ public void close() throws IOException {
+ this.d.onSessionClosed(this);
+ }
+
+ @Override
+ public void startSession() {
+ ((SimpleSessionListener)this.listener).onSessionUp(this, null, null);
+ }
+
+ @Override
+ public ProtocolOutputStream getStream() {
+ return null;
+ }
+
+ @Override
+ public void handleMessage(ProtocolMessage msg) {
+ }
+
+ @Override
+ public void handleMalformedMessage(DeserializerException e) {
+ }
+
+ @Override
+ public void handleMalformedMessage(DocumentedException e) {
+ }
+
+ @Override
+ public void endOfInput() {
+ }
+
+ @Override
+ public ProtocolMessageFactory getMessageFactory() {
+ return null;
+ }
+
+ @Override
+ public void onConnectionFailed(IOException e) {
+ ((SimpleSessionListener)this.listener).onConnectionFailed(this, e);
+ }
+
+ @Override
+ public int maximumMessageSize() {
+ return maxMsgSize;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.util.Timer;
+
+public final class SimpleSessionFactory implements ProtocolSessionFactory {
+ private final int maximumMessageSize;
+
+ public SimpleSessionFactory(int maximumMessageSize) {
+ this.maximumMessageSize = maximumMessageSize;
+ }
+
+ @Override
+ public ProtocolSession getProtocolSession(SessionParent parent, Timer timer, ProtocolConnection connection, int sessionId) {
+ return new SimpleSession(connection, parent, maximumMessageSize);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Simple Session Listener that is notified about messages and changes in the session.
+ */
+public class SimpleSessionListener implements SessionListener {
+ private static final Logger logger = LoggerFactory.getLogger(SimpleSessionListener.class);
+
+ public List<ProtocolMessage> messages = new ArrayList<ProtocolMessage>();
+
+ public boolean up = false;
+
+ public boolean failed = false;
+
+ public void onMessage(ProtocolSession session, ProtocolMessage message) {
+ logger.debug("Received message: " + message.getClass() + " " + message);
+ this.messages.add(message);
+ }
+
+ public synchronized void onSessionUp(ProtocolSession session, SimpleSessionPreferences local,
+ SimpleSessionPreferences remote) {
+ logger.debug("Session up.");
+ this.up = true;
+ this.notifyAll();
+ }
+
+ public synchronized void onConnectionFailed(ProtocolSession session, Exception e) {
+ logger.debug("Connection Failed: {}", e.getMessage(), e);
+ this.failed = true;
+ this.notifyAll();
+ try {
+ session.close();
+ } catch (final IOException ex) {
+ logger.warn("Session could not be closed.");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.net.InetAddress;
+
+public class SimpleSessionListenerFactory implements SessionListenerFactory {
+
+ @Override
+ public SimpleSessionListener getSessionListener(InetAddress address) {
+ return new SimpleSessionListener();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+public class SimpleSessionPreferences implements SessionPreferences {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+public class SimpleSessionProposal implements SessionProposal {
+ @Override
+ public SessionPreferences getProposal() {
+ return new SimpleSessionPreferences();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+public class SimpleSessionProposalChecker implements SessionPreferencesChecker {
+
+ @Override
+ public Boolean checkSessionCharacteristics(SessionPreferences openObj) {
+ return true;
+ }
+
+ @Override
+ public SessionPreferences getNewProposal(SessionPreferences open) {
+ return new SimpleSessionPreferences();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.net.InetSocketAddress;
+
+public class SimpleSessionProposalCheckerFactory implements
+ SessionPreferencesCheckerFactory {
+
+ @Override
+ public SessionPreferencesChecker getPreferencesChecker(
+ InetSocketAddress address) {
+ return new SimpleSessionProposalChecker();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.framework;
+
+import java.net.InetSocketAddress;
+
+public class SimpleSessionProposalFactory implements SessionProposalFactory {
+
+ @Override
+ public SessionProposal getSessionProposal(InetSocketAddress address, int sessionId) {
+ return new SimpleSessionProposal();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>mockito-configuration</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>mockito-configuration</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>protocol-parent</artifactId>
+ <version>0.1</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>mockito-configuration</artifactId>
+ <description>Default mockito configuration</description>
+ <packaging>jar</packaging> <!-- not needed in OSGi -->
+ <name>${project.artifactId}</name>
+ <version>1.0</version>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <!-- all those dependencies will be in test scope as mockito-configuration should be referenced as test scope dependency -->
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.9.5</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ </dependency>
+ </dependencies>
+
+ <distributionManagement>
+ <site>
+ <id>mockito-configuration</id>
+ <name>MOCKITO-CONFIGURATION Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>protocol-parent</artifactId>
+ <version>0.1</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>mockito-configuration</artifactId>
+ <description>Default mockito configuration</description>
+ <packaging>jar</packaging> <!-- not needed in OSGi -->
+ <name>${project.artifactId}</name>
+ <version>1.0</version>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <!-- all those dependencies will be in test scope as mockito-configuration should be referenced as test scope dependency -->
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.9.5</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ </dependency>
+ </dependencies>
+
+ <distributionManagement>
+ <site>
+ <id>mockito-configuration</id>
+ <name>MOCKITO-CONFIGURATION Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.mockito.configuration;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+import java.util.List;
+
+/**
+ * Verifier that extracts arguments from actual invocation. Useful when deeper validation of arguments is needed.
+ *
+ */
+public class ArgumentsExtractorVerifier implements VerificationMode {
+ private Object[] arguments;
+
+ @Override
+ public void verify(VerificationData data) {
+ InvocationsFinder finder = new InvocationsFinder();
+ List<Invocation> actualInvocations = finder.findInvocations(data.getAllInvocations(), data.getWanted());
+ if (actualInvocations.size() != 1) {
+ throw new MockitoException("This verifier can only be used with 1 invocation, got " + actualInvocations.size());
+ }
+ Invocation invocation = actualInvocations.get(0);
+ arguments = invocation.getArguments();
+ invocation.markVerified();
+
+ }
+ public Object[] getArguments(){
+ return arguments;
+ }
+ }
--- /dev/null
+/*
+ * Copyright (c) 2013 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.mockito.configuration;
+
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Configuration customization for Mockito. Change default answer from {@link ReturnsEmptyValues}
+ * to {@link ThrowsUnstubbedMethodException}.
+ */
+public class MockitoConfiguration extends DefaultMockitoConfiguration {
+
+ @Override
+ public Answer<Object> getDefaultAnswer() {
+ return new ThrowsUnstubbedMethodException();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.mockito.configuration;
+
+import java.io.Serializable;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Answer that throws {@link UnstubbedMethodException}.
+ */
+public class ThrowsUnstubbedMethodException implements Answer<Object>, Serializable {
+ private static final long serialVersionUID = 1L;
+
+ public ThrowsUnstubbedMethodException() {
+ }
+
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Throwable t = new UnstubbedMethodException(invocation.toString() + " was not stubbed");
+ throw t;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.mockito.configuration;
+
+
+/**
+ * Exception to be thrown on unstubbed method call.
+ */
+public class UnstubbedMethodException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public UnstubbedMethodException(String message) {
+ super(message);
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+ </encoder>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.mockito.configuration;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class ArgumentsExtractorVerifierTest {
+
+ @Mock
+ List<String> mockedList;
+
+ @Test
+ public void test() {
+ MockitoAnnotations.initMocks(this);
+ doReturn(true).when(this.mockedList).add(any(String.class));
+ final String argument = "something";
+ this.mockedList.add(argument);
+ // retrieve argument
+ final ArgumentsExtractorVerifier argumentsExtractorVerifier = new ArgumentsExtractorVerifier();
+ verify(this.mockedList, argumentsExtractorVerifier).add(any(String.class));
+ assertArrayEquals(new Object[] { argument }, argumentsExtractorVerifier.getArguments());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.mockito.configuration;
+
+import static org.junit.Assert.*;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class DefaultAnswerTest {
+
+ @Test
+ public void testAnswering() throws IOException {
+ Closeable mock = Mockito.mock(Closeable.class);
+ try {
+ mock.close();
+ fail();
+ } catch (UnstubbedMethodException e) {
+ assertEquals("closeable.close(); was not stubbed", e.getMessage());
+ }
+ }
+
+
+
+}
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>pcep-subsystem</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+target
+.settings
+.classpath
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>pcep-api</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>pcep-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>pcep-api</artifactId>
+ <description>PCE Protocol API</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>framework</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.protocol.pcep,
+ org.opendaylight.protocol.pcep.concepts,
+ org.opendaylight.protocol.pcep.message,
+ org.opendaylight.protocol.pcep.object,
+ org.opendaylight.protocol.pcep.subobject,
+ org.opendaylight.protocol.pcep.tlv,
+ </Export-Package>
+ <Import-Package>
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.framework,
+ org.opendaylight.protocol.util,
+ com.google.common.*,
+ javax.management,
+ org.slf4j.*
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.version}</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker-api.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>PCEP-API Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+
+/**
+ * Used as a reason when one of the regular reasons was the cause of the
+ * termination of a session.
+ */
+public final class PCEPCloseTermination implements TerminationReason {
+
+ private final Reason reason;
+
+ /**
+ * Creates new Termination.
+ * @param reason reason for termination
+ */
+ public PCEPCloseTermination(Reason reason) {
+ this.reason = reason;
+ }
+
+ /* (non-Javadoc)
+ * @see org.opendaylight.protocol.pcep.PCEPTerminationReason#getErrorMessage()
+ */
+ @Override
+ public String getErrorMessage() {
+ return this.reason.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+
+public interface PCEPConnection extends ProtocolConnection {
+ @Override
+ public PCEPSessionListener getListener();
+
+ @Override
+ public PCEPSessionPreferences getProposal();
+
+ @Override
+ public PCEPSessionProposalChecker getProposalChecker();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.ProtocolConnectionFactory;
+
+public interface PCEPConnectionFactory extends ProtocolConnectionFactory {
+ @Override
+ public PCEPConnection createProtocolConnection(final InetSocketAddress address);
+
+ public void setProposal(final PCEPSessionProposalFactory proposals, final InetSocketAddress address, final int sessionId);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+
+/**
+ * Used when something occurs during parsing bytes to java objects.
+ */
+public class PCEPDeserializerException extends DeserializerException {
+
+ private static final long serialVersionUID = -7511681435692278498L;
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPDeserializerException.class);
+
+ private final String message;
+
+ /**
+ * Used when no exact error (from rfc or from draft) is specified.
+ *
+ * @param err
+ * error message describing the error that occurred
+ */
+ public PCEPDeserializerException(String err) {
+ this(null, err);
+ }
+
+ /**
+ * Used when we want to pass also the exception that occurred.
+ *
+ * @param e
+ * specific exception that occurred
+ * @param err
+ * error message describing the error that occurred
+ */
+ public PCEPDeserializerException(Exception e, String err) {
+ super(err, e);
+ this.message = err;
+ logger.error("", this);
+ }
+
+ /**
+ * Returns error message.
+ *
+ * @return error message
+ */
+ public String getErrorMessage() {
+ return this.message;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.ProtocolServer;
+
+/**
+ * Dispatcher class for creating servers and clients.
+ */
+public interface PCEPDispatcher {
+
+ /**
+ * Creates server. Each server needs three factories to pass their instances to client sessions.
+ * @param address to be bound with the server
+ * @param listenerFactory to create listeners for clients
+ * @param proposalFactory to create proposed open objects for clients
+ * @param checkerFactory to create session characteristics checker for clients
+ * @return instance of PCEPServer
+ * @throws IOException if some IO error occurred
+ */
+ public ProtocolServer createServer(final InetSocketAddress address, final PCEPConnectionFactory connectionFactory) throws IOException;
+
+ /**
+ * Creates a client. Needs to be started via the start method.
+ * @param address of the server, where the client will connect
+ * @param sessionListener listener to this session who will be notified about incoming messages and other session events
+ * @param proposal proposes initial Open object
+ * @param checker checks session characteristics and proposes another Open object if necessary
+ * @return session associated with this client.
+ * @throws IOException if some IO error occurred
+ */
+ public PCEPSession createClient(PCEPConnection connection) throws IOException;
+
+ /**
+ * Sets the limit of maximum unknown messages per minute. If not set by the user, default is 5 messages/minute.
+ * @param limit maximum unknown messages per minute
+ */
+ public void setMaxUnknownMessages(final int limit);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DocumentedException;
+
+/**
+ * There are several errors documented in RFC5440 or in draft, that have
+ * specific meaning for the PCE. This exception is used, when any of those
+ * errors occurs.
+ */
+public class PCEPDocumentedException extends DocumentedException {
+
+ private static final long serialVersionUID = 5146586011100522025L;
+
+ private final PCEPErrors error;
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPDocumentedException.class);
+
+ /**
+ * Used when an error occured that is described in rfc or draft
+ *
+ * @param message
+ * message bound with this exception
+ * @param error
+ * specific documented error
+ */
+ public PCEPDocumentedException(String message, PCEPErrors error) {
+ super(message);
+ this.error = error;
+ logger.error("Error = " + error, this);
+ }
+
+ /**
+ * Returns specific documented error
+ *
+ * @return documented error
+ */
+ public PCEPErrors getError() {
+ return this.error;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+
+/**
+ * Used as a reason when a documented error was the cause of the
+ * termination of a session.
+ */
+public final class PCEPErrorTermination implements TerminationReason {
+
+ private final PCEPErrors error;
+
+ /**
+ * Creates new Termination.
+ * @param error Error that happened.
+ */
+ public PCEPErrorTermination(PCEPErrors error) {
+ this.error = error;
+ }
+
+ /* (non-Javadoc)
+ * @see org.opendaylight.protocol.pcep.PCEPTerminationReason#getErrorMessage()
+ */
+ @Override
+ public String getErrorMessage() {
+ return this.error.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+/**
+ * Possible errors listed in RFC5440, RFC 5455 and stateful draft.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-9.12">PCEP-ERROR
+ * Object(RFC5440)</a>, <a href=
+ * "http://tools.ietf.org/html/draft-ietf-pce-stateful-pce-01#section-8.4"
+ * >PCEP-ERROR Object(stateful draft)</a>, <a
+ * href="http://tools.ietf.org/html/rfc5455#section-3.6">Error Codes for
+ * CLASSTYPE Object(RFC5455)</a>, <a href=
+ * "http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt#section-7.1"
+ * >PCEP-Error Object</a>
+ */
+public enum PCEPErrors {
+ /**
+ * Reception of an invalid Open message or a non Open message.
+ */
+ NON_OR_INVALID_OPEN_MSG,
+ /**
+ * No Open message received before the expiration of the OpenWait timer.
+ */
+ NO_OPEN_BEFORE_EXP_OPENWAIT,
+ /**
+ * Unacceptable and non-negotiable session characteristics.
+ */
+ NON_ACC_NON_NEG_SESSION_CHAR,
+ /**
+ * Unacceptable but negotiable session characteristics.
+ */
+ NON_ACC_NEG_SESSION_CHAR,
+ /**
+ * Reception of a second Open message with still unacceptable session
+ * characteristics.
+ */
+ SECOND_OPEN_MSG,
+ /**
+ * Reception of a PCErr message proposing unacceptable session
+ * characteristics.
+ */
+ PCERR_NON_ACC_SESSION_CHAR,
+ /**
+ * No Keepalive or PCErr message received before the expiration of the
+ * KeepWait timer.
+ */
+ NO_MSG_BEFORE_EXP_KEEPWAIT,
+ /**
+ * Capability not supported.
+ */
+ CAPABILITY_NOT_SUPPORTED,
+ /**
+ * PCEP version not supported.
+ */
+ PCEP_VERSION_NOT_SUPPORTED,
+ /**
+ * Unrecognized object class.
+ */
+ UNRECOGNIZED_OBJ_CLASS,
+ /**
+ * Unrecognized object Type.
+ */
+ UNRECOGNIZED_OBJ_TYPE,
+ /**
+ * Not supported object class.
+ */
+ NOT_SUPPORTED_OBJ_CLASS,
+ /**
+ * Not supported object Type.
+ */
+ NOT_SUPPORTED_OBJ_TYPE,
+ /**
+ * C bit of the METRIC object set (request rejected).
+ */
+ C_BIT_SET,
+ /**
+ * O bit of the RP object cleared (request rejected).
+ */
+ O_BIT_SET,
+ /**
+ * Objective function not allowed (request rejected)
+ */
+ OF_NOT_ALLOWED,
+ /**
+ * OF bit of the RP object set (request rejected)
+ */
+ OF_BIT_SET,
+ /**
+ * Global concurrent optimization not allowed (GCO extension)
+ */
+ GCO_NOT_ALLOWED,
+ /**
+ * P2MP Path computation is not allowed
+ */
+ P2MP_COMPUTATION_NOT_ALLOWED,
+ /**
+ * RP object missing
+ */
+ RP_MISSING,
+ /**
+ * RRO missing for a reoptimization request (R bit of the RP object set).
+ */
+ RRO_MISSING,
+ /**
+ * END-POINTS object missing
+ */
+ END_POINTS_MISSING,
+ /**
+ * LSP cleanup TLV missing
+ */
+ LSP_CLEANUP_TLV_MISSING,
+ /**
+ * SYMBOLIC-PATH-NAME TLV missing
+ */
+ SYMBOLIC_PATH_NAME_MISSING,
+ /**
+ * Synchronized path computation request missing.
+ */
+ SYNC_PATH_COMP_REQ_MISSING,
+ /**
+ * Unknown request reference
+ */
+ UNKNOWN_REQ_REF,
+ /**
+ * Attempt to establish a second PCEP session.
+ */
+ ATTEMPT_2ND_SESSION,
+ /**
+ * LSP Object missing.
+ */
+ LSP_MISSING,
+ /**
+ * ERO Object missing for a path in an LSP Update Request where TE-LSP setup
+ * is requested.
+ */
+ ERO_MISSING,
+ /**
+ * BANDWIDTH Object missing for a path in an LSP Update Request where TE-LSP
+ * setup is requested.
+ */
+ BANDWIDTH_MISSING,
+ /**
+ * LSPA Object missing for a path in an LSP Update Request where TE-LSP
+ * setup is requested.
+ */
+ LSPA_MISSING,
+ /**
+ * LSP-DB-VERSION TLV missing.
+ */
+ DB_VERSION_TLV_MISSING,
+ /**
+ * Reception of an object with P flag not set although the P flag must be
+ * set according to this specification.
+ */
+ P_FLAG_NOT_SET,
+ /**
+ * Insufficient memory (GCO extension)
+ */
+ INSUFFICIENT_MEMORY,
+ /**
+ * Global concurrent optimization not supported (GCO extension)
+ */
+ GCO_NOT_SUPPORTED,
+ /**
+ * Diffserv-aware TE error: Unsupported Class-Type.
+ */
+ UNSUPPORTED_CT,
+ /**
+ * Diffserv-aware TE error: Invalid Class-Type.
+ */
+ INVALID_CT,
+ /**
+ * Diffserv-aware TE error: Class-Type and setup priority do not form a
+ * configured TE-class.
+ */
+ CT_AND_SETUP_PRIORITY_DO_NOT_FORM_TE_CLASS,
+
+ /**
+ * The PCE cannot satisfy the request due to insufficient memory
+ */
+ CANNOT_SATISFY_P2MP_REQUEST_DUE_TO_INSUFFISIENT_MEMMORY,
+ /**
+ * The PCE is not capable of P2MP computation
+ */
+ NOT_CAPPABLE_P2MP_COMPUTATION,
+ /**
+ * The PCE is not capable to satisfy the request due to no END-POINTS with
+ * leaf type 2
+ */
+ P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT2,
+ /**
+ * The PCE is not capable to satisfy the request due to no END-POINTS with
+ * leaf type 3
+ */
+ P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT3,
+ /**
+ * The PCE is not capable to satisfy the request due to no END-POINTS with
+ * leaf type 4
+ */
+ P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT4,
+ /**
+ * The PCE is not capable to satisfy the request due to inconsistent
+ * END-POINTS
+ */
+ P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_INCONSISTENT_EP,
+ /**
+ * P2MP Fragmented request failure
+ */
+ P2MP_FRAGMENTATION_FAILRUE,
+ /**
+ * Attempted LSP Update Request for a non- delegated LSP. The PCEP-ERROR
+ * Object is followed by the LSP Object that identifies the LSP.
+ */
+ UPDATE_REQ_FOR_NON_LSP,
+ /**
+ * Attempted LSP Update Request if active stateful PCE capability was not
+ * negotiated active PCE.
+ */
+ UPDATE_REQ_FOR_NO_STATEFUL,
+ /**
+ * PCE-initiated LSP limit reached.
+ */
+ LSP_LIMIT_REACHED,
+ /**
+ * Delegation for PCE-initiated LSP cannot be revoked
+ */
+ DELEGATION_NOT_REVOKED,
+ /**
+ * A PCE indicates to a PCC that it can not process (an otherwise valid) LSP
+ * State Report. The PCEP-ERROR Object is followed by the LSP Object that
+ * identifies the LSP.
+ */
+ CANNOT_PROCESS_STATE_REPORT,
+ /**
+ * LSP Database version mismatch.
+ */
+ LSP_DB_VERSION_MISMATCH,
+ /**
+ * The LSP-DB-VERSION TLV Missing when State Synchronization Avoidance
+ * enabled.
+ */
+ DB_VERSION_TLV_MISSING_WHEN_SYNC_ALLOWED,
+ /**
+ * SYMBOLIC-PATH-NAME in use
+ */
+ USED_SYMBOLIC_PATH_NAME
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import java.util.List;
+
+import org.opendaylight.protocol.framework.ProtocolMessage;
+
+/**
+ * Basic structure for PCEP Message. Cannot be instantiated directly. Current
+ * PCEP version is 1. Each message contains a list of PCEP objects.
+ *
+ */
+public abstract class PCEPMessage implements ProtocolMessage {
+
+ private static final long serialVersionUID = 4293319459468168384L;
+
+ /**
+ * Current supported version of PCEP.
+ */
+ public static final int PCEP_VERSION = 1;
+
+ private final List<PCEPObject> objects;
+
+ /**
+ * Constructor is protected to prevent direct instantiation, but to allow to
+ * call this constructor via super().
+ *
+ * @param objects
+ */
+ protected PCEPMessage(List<PCEPObject> objects) {
+ this.objects = objects;
+ }
+
+ /**
+ * Returns list of all objects that the message contains
+ *
+ * @return list of all objects that the message contains
+ */
+ public List<PCEPObject> getAllObjects() {
+ return this.objects;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.objects == null) ? 0 : this.objects.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPMessage other = (PCEPMessage) obj;
+ if (this.objects == null) {
+ if (other.objects != null)
+ return false;
+ } else if (!this.objects.equals(other.objects))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPMessage [objects=");
+ builder.append(this.objects);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+/**
+ * Enumerable representing ObjectiveFunction codes. Defined in RFC5541.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5541#section-4">Objective
+ * Functions Definition</a>
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.6.1">New Objective
+ * Functions [RFC6006]</a>
+ */
+public enum PCEPOFCodes {
+ /**
+ * Minimum Cost Path
+ */
+ MCP,
+ /**
+ * Minimum Load Path
+ */
+ MLP,
+ /**
+ * Maximum residual Bandwidth Path
+ */
+ MBP,
+ /**
+ * Minimize aggregate Bandwidth Consumption
+ */
+ MBC,
+ /**
+ * Minimize the load of the Most Loaded Link
+ */
+ MLL,
+ /**
+ * Minimize Cumulative Cost of a set of paths
+ */
+ MCC,
+ /**
+ * Name: Shortest Path Tree (SPT)
+ *
+ * Description: Minimize the maximum source-to-leaf cost with respect to a
+ * specific metric or to the TE metric used as the default metric when the
+ * metric is not specified (e.g., TE or IGP metric).
+ */
+ SPT,
+ /**
+ * Name: Minimum Cost Tree (MCT)
+ *
+ * Description: Minimize the total cost of the tree, that is the sum of the
+ * costs of tree links, with respect to a specific metric or to the TE
+ * metric used as the default metric when the metric is not specified.
+ */
+ MCT;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Basic structure for PCEP Objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.2">Common Object
+ * Header</a>
+ */
+public abstract class PCEPObject {
+
+ private final boolean processed;
+
+ private final boolean ignored;
+
+ /**
+ * Constructor is protected to prevent direct instantiation, but to allow to
+ * call this constructor via super().
+ *
+ * @param processed
+ * P flag
+ * @param ignored
+ * I flag
+ */
+ protected PCEPObject(boolean processed, boolean ignored) {
+ this.processed = processed;
+ this.ignored = ignored;
+ }
+
+ /**
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.2"> Common
+ * Object Header</a>
+ *
+ * @return true if P flag is set and false if is not.
+ */
+ public boolean isProcessed() {
+ return this.processed;
+ }
+
+ /**
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.2"> Common
+ * Object Header</a>
+ *
+ * @return true if I flag is set and false if is not.
+ */
+ public boolean isIgnored() {
+ return this.ignored;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.ignored ? 1231 : 1237);
+ result = prime * result + (this.processed ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPObject other = (PCEPObject) obj;
+ if (this.ignored != other.ignored)
+ return false;
+ if (this.processed != other.processed)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString(){
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("processed", this.processed);
+ toStringHelper.add("ignored", this.ignored);
+ return toStringHelper;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import java.io.Closeable;
+
+/**
+ * PCEP Session represents the finite state machine in PCEP,
+ * including timers and its purpose is to create a PCEP connection
+ * between PCE/PCC. Session is automatically started, when TCP
+ * connection is created, but can be stopped manually.
+ * If the session is up, it has to redirect messages to/from user.
+ * Handles also malformed messages and unknown requests.
+ */
+public interface PCEPSession extends Closeable {
+
+ /**
+ * Sends message from user to PCE/PCC. If the user sends an Open
+ * Message, the session returns an error (open message is only
+ * allowed, when a PCEP handshake is in progress). Close message
+ * will close the session and free all the resources.
+ * @param message message to be sent
+ */
+ public void sendMessage(PCEPMessage message);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import java.util.Timer;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.ProtocolSessionFactory;
+import org.opendaylight.protocol.framework.SessionParent;
+
+public interface PCEPSessionFactory extends ProtocolSessionFactory {
+ @Override
+ public ProtocolSession getProtocolSession(SessionParent parent, Timer timer, ProtocolConnection connection, int sessionId);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import org.opendaylight.protocol.framework.SessionListener;
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Listener that receives session informations from the session.
+ */
+public abstract class PCEPSessionListener implements SessionListener {
+
+ /**
+ * Fired when a message is received.
+ * @param session session which received the message
+ * @param message PCEPMessage
+ */
+ public abstract void onMessage(PCEPSession session, PCEPMessage message);
+
+ /**
+ * Fired when the session is in state UP.
+ *
+ * @param session Session which went up
+ * @param local Local open proposal which the peer accepted
+ * @param remote Peer open proposal which we accepted
+ */
+ public abstract void onSessionUp(PCEPSession session, PCEPOpenObject local, PCEPOpenObject remote);
+
+ /**
+ * Fired when the session went down as a result of peer's decision
+ * to tear it down.
+ * Implementation should take care of closing underlying session.
+ *
+ * @param session Session which went down
+ * @param reason Reason for termination, may be null when the underlying
+ * channel was closed without a specific reason.
+ * @param e exception that caused session down
+ */
+ public abstract void onSessionDown(PCEPSession session, PCEPCloseObject reason, Exception e);
+
+ /**
+ * Fired when the session is terminated locally. The session has already
+ * been closed and transitioned to IDLE state. Any outstanding queued
+ * messages were not sent. The user should not attempt to make any use
+ * of the session.
+ *
+ * @param session Session which went down
+ * @param cause the cause why the session went down
+ */
+ public abstract void onSessionTerminated(PCEPSession session, TerminationReason cause);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import java.net.InetAddress;
+
+import org.opendaylight.protocol.framework.SessionListenerFactory;
+
+/**
+ * Factory for generating PCEP Session Listeners. Used by a server.
+ */
+public abstract class PCEPSessionListenerFactory implements SessionListenerFactory {
+
+ /**
+ * Returns one session listener that is registered to this factory
+ * @param address serves as constraint, so that factory is able to
+ * return different listeners for different factories
+ * @return specific session listener
+ */
+ @Override
+ public abstract PCEPSessionListener getSessionListener(InetAddress address);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Implementation of {@link SessionPreferences}.
+ */
+public final class PCEPSessionPreferences implements SessionPreferences {
+
+ private final PCEPOpenObject openObject;
+
+ /**
+ * Construct new session preferences.
+ *
+ * @param openObject encapsulated PCEP OPEN object
+ */
+ public PCEPSessionPreferences(final PCEPOpenObject openObject) {
+ this.openObject = openObject;
+ }
+
+ /**
+ * Return the encapsulated OPEN object.
+ *
+ * @return encapsulated OPEN object.
+ */
+ public PCEPOpenObject getOpenObject() {
+ return this.openObject;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((this.openObject == null) ? 0 : this.openObject.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof PCEPSessionPreferences))
+ return false;
+ final PCEPSessionPreferences other = (PCEPSessionPreferences) obj;
+ if (this.openObject == null) {
+ if (other.openObject != null)
+ return false;
+ } else if (!this.openObject.equals(other.openObject))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import org.opendaylight.protocol.framework.SessionProposal;
+
+/**
+ * Interface that provides the initial acceptable session characteristics
+ * with which the session should be started.
+ */
+public abstract class PCEPSessionProposal implements SessionProposal {
+
+ /**
+ * Returns specific PCEPOpenObject for this IP address.
+ * @param address serves as constraint, the implementation can also
+ * take time into consideration
+ * @return PCEPOpenObject with acceptable session characteristics
+ */
+ @Override
+ public abstract PCEPSessionPreferences getProposal();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.framework.SessionPreferencesChecker;
+
+/**
+ * Interface to work with session characteristics. They need to be
+ * checked during the PCEP establishment phase. If they are not
+ * acceptable a new proposal needs to be requested.
+ */
+public abstract class PCEPSessionProposalChecker implements SessionPreferencesChecker {
+
+ /**
+ * Checks session characteristics, if they are acceptable.
+ *
+ * @param openObj
+ * storage for session characteristics
+ * @return true = acceptable, false = negotiable, null = unacceptable
+ */
+ @Override
+ public abstract Boolean checkSessionCharacteristics(SessionPreferences openObj);
+
+ /**
+ * In case of negotiable session characteristics, new ones are requested
+ * through this method.
+ *
+ * @param open old open object with unacceptable session characteristics
+ * @return
+ * <li> new session characteristics wrapped in Open Object
+ * <li> null if there are not available any different acceptable
+ * session characteristics
+ */
+ public abstract PCEPSessionPreferences getNewProposal(SessionPreferences open);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.SessionPreferencesCheckerFactory;
+
+/**
+ * Factory for generating PCEP Session Proposal Checkers. Used by a server.
+ */
+public abstract class PCEPSessionProposalCheckerFactory implements SessionPreferencesCheckerFactory {
+
+ /**
+ * Returns one session proposal checker that is registered to this factory
+ * @param address serves as constraint, so that factory is able to
+ * return different checkers for different factories
+ * @return specific session proposal checker
+ */
+ @Override
+ public abstract PCEPSessionProposalChecker getPreferencesChecker(InetSocketAddress address);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.SessionProposalFactory;
+
+/**
+ * Factory for generating PCEP Session proposals. Used by a server.
+ */
+public abstract class PCEPSessionProposalFactory implements SessionProposalFactory {
+
+ /**
+ * Returns one session proposal that is registered to this factory
+ *
+ * @param address
+ * serves as constraint, so that factory is able to return
+ * different proposals for different addresses
+ * @param sessionId
+ * is used for creation of PCEPOpenObject
+ * @return specific session proposal
+ */
+ @Override
+ public abstract PCEPSessionProposal getSessionProposal(InetSocketAddress address, int sessionId);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep;
+
+import java.io.Serializable;
+
+/**
+ * Interface grouping all implemented tlvs.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.1">PCEP TLV
+ * Format</a>
+ */
+public interface PCEPTlv extends Serializable {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Basic structure of Extended Tunnel Identifier.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ * Identifiers TLVs</a>
+ * @param <T>
+ */
+public abstract class AbstractExtendedTunnelIdentifier<T extends NetworkAddress<T>> implements Comparable<ExtendedTunnelIdentifier<T>>, ExtendedTunnelIdentifier<T> {
+
+ private static final long serialVersionUID = 110737862492677555L;
+
+ private final T identifier;
+
+ protected AbstractExtendedTunnelIdentifier(final T identifier) {
+ this.identifier = identifier;
+ }
+
+ @Override
+ public T getIdentifier() {
+ return this.identifier;
+ }
+
+ @Override
+ public int compareTo(final ExtendedTunnelIdentifier<T> other) {
+ if (this.identifier == other.getIdentifier())
+ return 0;
+ if (this.identifier == null)
+ return -1;
+ if (other.getIdentifier() == null)
+ return 1;
+ return this.identifier.compareTo(other.getIdentifier());
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.identifier == null) ? 0 : this.identifier.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final AbstractExtendedTunnelIdentifier<?> other = (AbstractExtendedTunnelIdentifier<?>) obj;
+ if (this.identifier == null) {
+ if (other.identifier != null)
+ return false;
+ } else if (!this.identifier.equals(other.identifier))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("AbstractExtendedTunnelIdentifier [identifier=");
+ builder.append(this.identifier);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * Aggregate Bandwidth Consumption metric class.
+ */
+public class AggregateBandwidthConsumptionMetric extends AbstractMetric<AggregateBandwidthConsumptionMetric> {
+
+ private static final long serialVersionUID = 3935025327997428991L;
+
+ /**
+ * Construct a new Aggregate Bandwidth Consumption metric object.
+ *
+ * @param value
+ * Metric value
+ * @throws IllegalArgumentException
+ * ex when value is outside of allowed range (0-4294967295)
+ */
+ public AggregateBandwidthConsumptionMetric(final long value) {
+ super(value);
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid Agregate Bandwidth Consumption metric value");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * Cumulative IGP cost metric class
+ */
+public class CumulativeIGPCostMetric extends AbstractMetric<CumulativeIGPCostMetric> {
+
+ private static final long serialVersionUID = 3935025327997428991L;
+
+ /**
+ * Construct a new Cumulative IGP cost metric object.
+ *
+ * @param value
+ * Metric value
+ * @throws IllegalArgumentException
+ * ex when value is outside of allowed range (0-4294967295)
+ */
+ public CumulativeIGPCostMetric(final long value) {
+ super(value);
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid cumulative IGP cost metric value");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * Cumulative TE cost metric class
+ */
+public class CumulativeTECostMetric extends AbstractMetric<CumulativeTECostMetric> {
+
+ private static final long serialVersionUID = 3935025327997428991L;
+
+ /**
+ * Construct a new Cumulative TE cost metric object.
+ *
+ * @param value
+ * Metric value
+ * @throws IllegalArgumentException
+ * ex when value is outside of allowed range (0-4294967295)
+ */
+ public CumulativeTECostMetric(final long value) {
+ super(value);
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid cumulative TE cost metric value");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Interface grouping Extended Tunnel Identifiers.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ * Identifiers TLVs</a>
+ * @param <T> IPv4 or IPv6 address that is wrapped in this tunnel
+ */
+public interface ExtendedTunnelIdentifier<T extends NetworkAddress<T>> extends Identifier {
+
+ /**
+ * Getter for Identifier of Extended Tunnel.
+ *
+ * @return T IPv4 or IPv6 address
+ */
+ public T getIdentifier();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+
+/**
+ * Specific structure of IPv4 Extended Tunnel Identifier.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ * Identifiers TLVs</a>
+ */
+public final class IPv4ExtendedTunnelIdentifier extends AbstractExtendedTunnelIdentifier<IPv4Address> {
+
+ private static final long serialVersionUID = -8872936514548777175L;
+
+ /**
+ * Creates IPv4ExtendedTunnelIdentifier with given IPv4Address.
+ * @param routerAddress {@link IPv4Address}
+ */
+ public IPv4ExtendedTunnelIdentifier(final IPv4Address routerAddress) {
+ super(routerAddress);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+
+/**
+ * Specific structure of IPv6 Extended Tunnel Identifier.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ * Identifiers TLVs</a>
+ */
+public final class IPv6ExtendedTunnelIdentifier extends AbstractExtendedTunnelIdentifier<IPv6Address> {
+
+ private static final long serialVersionUID = -4603732260818370518L;
+
+ /**
+ * Creates IPv6ExtendedTunnelIdentifier with given IPv6Address.
+ * @param routerAddress {@link IPv6Address}
+ */
+ public IPv6ExtendedTunnelIdentifier(final IPv6Address routerAddress) {
+ super(routerAddress);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * A 16-bit identifier used in the SENDER_TEMPLATE and the FILTER_SPEC that can
+ * be changed to allow a sender to share resources with itself.
+ */
+public final class LSPIdentifier extends AbstractIdentifier<LSPIdentifier> {
+
+ private static final long serialVersionUID = 1337756730239265010L;
+
+ private final byte[] lspId;
+
+ /**
+ * Creates LSPIdentifier using byte array as value.
+ *
+ * @param lspId
+ * value of the LSPIdentifier TLV. Must be exactly 2 bytes long.
+ */
+ public LSPIdentifier(final byte[] lspId) {
+ if (lspId.length != 2)
+ throw new IllegalArgumentException("Invalid LSP identifier");
+ this.lspId = lspId;
+ }
+
+ /**
+ * Gets LSP Id in raw byte array representation.
+ *
+ * @return byte array representation of LSP ID. May be null.
+ */
+ public byte[] getLspId() {
+ return this.lspId;
+ }
+
+ @Override
+ protected byte[] getBytes() {
+ return this.lspId;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("lspId", ByteArray.toHexString(lspId, "."));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.1">The
+ * LSP Symbolic Name TLV</a>
+ */
+public final class LSPSymbolicName extends AbstractIdentifier<LSPSymbolicName> {
+
+ private static final long serialVersionUID = -5649378295100912021L;
+
+ private final byte[] symbolicName;
+
+ /**
+ * Creates LSPSymbolicName using byte array as value.
+ *
+ * @param symbolicName
+ * value of the LSPSymbolicName TLV
+ */
+ public LSPSymbolicName(final byte[] symbolicName) {
+ this.symbolicName = symbolicName;
+ }
+
+ /**
+ * Gets Symbolic Name in raw byte array representation.
+ *
+ * @return byte array representation of Symbolic Name. May be null.
+ */
+ public byte[] getSymbolicName() {
+ return this.symbolicName;
+ }
+
+ @Override
+ protected byte[] getBytes() {
+ return this.symbolicName;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("symbolicName", ByteArray.toHexString(symbolicName, "."));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * Load of the most loaded link metric class
+ */
+public class MostLoadedLinkLoadMetric extends AbstractMetric<MostLoadedLinkLoadMetric> {
+
+ private static final long serialVersionUID = 3935025327997428991L;
+
+ /**
+ * Construct a new Load of the most loaded link metric object.
+ *
+ * @param value
+ * Metric value
+ * @throws IllegalArgumentException
+ * ex when value is outside of allowed range (0-4294967295)
+ */
+ public MostLoadedLinkLoadMetric(final long value) {
+ super(value);
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid Load of the most loaded link metric value");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * P2MP hop count metric class
+ */
+public class P2MPHopCountMetric extends AbstractMetric<P2MPHopCountMetric> {
+
+ private static final long serialVersionUID = 3935025327997428991L;
+
+ /**
+ * Construct a new P2MP hop count metric object.
+ *
+ * @param value
+ * Metric value
+ * @throws IllegalArgumentException
+ * ex when value is outside of allowed range (0-4294967295)
+ */
+ public P2MPHopCountMetric(final long value) {
+ super(value);
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid P2MP hop count metric value");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * P2MP IGP metric class
+ */
+public class P2MPIGPMetric extends AbstractMetric<P2MPIGPMetric> {
+
+ private static final long serialVersionUID = 3935025327997428991L;
+
+ /**
+ * Construct a new P2MP IGP metric metric object.
+ *
+ * @param value
+ * Metric value
+ * @throws IllegalArgumentException
+ * ex when value is outside of allowed range (0-4294967295)
+ */
+ public P2MPIGPMetric(final long value) {
+ super(value);
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid P2MP IGP metric value");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+
+/**
+ * P2MP TE metric class
+ */
+public class P2MPTEMetric extends AbstractMetric<P2MPTEMetric> {
+
+ private static final long serialVersionUID = 3935025327997428991L;
+
+ /**
+ * Construct a new P2MP TE metric object.
+ *
+ * @param value
+ * Metric value
+ * @throws IllegalArgumentException
+ * ex when value is outside of allowed range (0-4294967295)
+ */
+ public P2MPTEMetric(final long value) {
+ super(value);
+ if (value < 0 || value > 4294967295L)
+ throw new IllegalArgumentException("Invalid P2MP TE metri value");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.AbstractIdentifier;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * A 16-bit identifier used in the SESSION that remains constant over the life
+ * of the tunnel.
+ */
+public final class TunnelIdentifier extends AbstractIdentifier<TunnelIdentifier> {
+
+ private static final long serialVersionUID = 137237703900885441L;
+
+ private final byte[] tunnelId;
+
+ /**
+ * Creates TunnelIdentifier using byte array as value.
+ *
+ * @param tunnelId
+ * value of the TunnelIdentifier TLV. Must be exactly 2 bytes
+ * long.
+ */
+ public TunnelIdentifier(final byte[] tunnelId) {
+ if (tunnelId.length != 2)
+ throw new IllegalArgumentException("Invalid tunnel ID.");
+ this.tunnelId = tunnelId;
+ }
+
+ @Override
+ public byte[] getBytes() {
+ return this.tunnelId;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("tunnelId", ByteArray.toHexString(tunnelId, "."));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.concepts;
+
+import org.opendaylight.protocol.concepts.Identifier;
+
+/**
+ * A 32-bit (unsigned) identifying an interface within a router. This identifier
+ * is explicitly local to the router, e.g. each router has its own namespace.
+ */
+public final class UnnumberedInterfaceIdentifier implements Comparable<UnnumberedInterfaceIdentifier>, Identifier {
+
+ private static final long serialVersionUID = -8488014237579913120L;
+
+ private final long interfaceId;
+
+ /**
+ * Creates an instance of UnnumberedInterfaceIdentifier from long number.
+ *
+ * @param interfaceId
+ * long the value of the UnnumberedInterfaceIdentifier
+ */
+ public UnnumberedInterfaceIdentifier(final long interfaceId) {
+ if (interfaceId < 0 || interfaceId > 4294967295L)
+ throw new IllegalArgumentException("Invalid link identifier");
+ this.interfaceId = interfaceId;
+ }
+
+ /**
+ * Getter for Interface Id represented as long.
+ *
+ * @return long representation of Interface Id. From 0 to 4294967295.
+ */
+ public long getInterfaceId() {
+ return this.interfaceId;
+ }
+
+ @Override
+ public int compareTo(final UnnumberedInterfaceIdentifier o) {
+ if (this.interfaceId < o.getInterfaceId())
+ return -1;
+ if (this.interfaceId > o.getInterfaceId())
+ return 1;
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (this.interfaceId ^ (this.interfaceId >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final UnnumberedInterfaceIdentifier other = (UnnumberedInterfaceIdentifier) obj;
+ if (this.interfaceId != other.interfaceId)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("UnnumberedInterfaceIdentifier [interfaceId=");
+ builder.append(this.interfaceId);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeInstantiationObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+
+/**
+ * @see <a href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt">5.1. The LSP Create Message</a>
+ */
+public class PCCreateMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = -2407399568579836171L;
+
+ private final List<CompositeInstantiationObject> lsps;
+
+ /**
+ * Constructs {@link PCCreateMessage}.
+ *
+ * @throws IllegalArgumentException
+ * if there is not even one {@link CompositeInstantiationObject}
+ * in the list.
+ *
+ * @param lsps
+ * List<CompositeInstantiationObject>. Can't be empty or null.
+ */
+ public PCCreateMessage(final List<CompositeInstantiationObject> lsps) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = 1L;
+
+ {
+ if (lsps != null)
+ for (final CompositeInstantiationObject cio : lsps) {
+ this.addAll(cio.getCompositeAsList());
+ }
+ }
+ });
+ if (lsps == null || lsps.isEmpty())
+ throw new IllegalArgumentException("At least one CompositeStateReportObject is mandatory.");
+
+ this.lsps = lsps;
+ }
+
+ /**
+ * Gets list of {@link CompositeStateReportObject}.
+ *
+ * @return List<CompositeStateReportObject>. Can't be null or empty.
+ */
+ public List<CompositeInstantiationObject> getLSPs() {
+ return this.lsps;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.lsps == null) ? 0 : this.lsps.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (!(obj instanceof PCCreateMessage))
+ return false;
+ final PCCreateMessage other = (PCCreateMessage) obj;
+ if (this.lsps == null) {
+ if (other.lsps != null)
+ return false;
+ } else if (!this.lsps.equals(other.lsps))
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCCreateMessage [lsps=");
+ builder.append(this.lsps);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+
+/**
+ * Structure of Close Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.8">Close
+ * Message</a>
+ */
+public class PCEPCloseMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = -2365304678646268281L;
+
+ private final PCEPCloseObject closeObj;
+
+ /**
+ * Constructs a new Close Message, which has to include PCEP Close Object.
+ * Is used to close an established session between PCEP Peers.
+ *
+ * @throws IllegalArgumentException
+ * if the CloseObject passed, is null.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.8">Close
+ * Message</a>
+ *
+ * @param closeObj
+ * Can't be null.
+ */
+ public PCEPCloseMessage(final PCEPCloseObject closeObj) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = -8094080277421295531L;
+
+ {
+ if (closeObj != null)
+ this.add(closeObj);
+ }
+ });
+ if (closeObj == null)
+ throw new IllegalArgumentException("PCEPCloseObject is mandatory. Can't be null.");
+
+ this.closeObj = closeObj;
+ }
+
+ /**
+ * Gets {@link PCEPCloseObject}, which is mandatory object of PCEP Close
+ * Message.
+ *
+ * @return {@link PCEPCloseObject} . Can't be null.
+ */
+ public PCEPCloseObject getCloseObject() {
+ return this.closeObj;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.closeObj == null) ? 0 : this.closeObj.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPCloseMessage other = (PCEPCloseMessage) obj;
+ if (this.closeObj == null) {
+ if (other.closeObj != null)
+ return false;
+ } else if (!this.closeObj.equals(other.closeObj))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPCloseMessage [closeObj=");
+ builder.append(this.closeObj);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Structure of Error Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.7">Error
+ * Message</a>
+ */
+public class PCEPErrorMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = 604782651368689577L;
+
+ private PCEPOpenObject openObj;
+
+ private final List<PCEPErrorObject> errorObjects;
+
+ private final List<CompositeErrorObject> errors;
+
+ public PCEPErrorMessage(final PCEPErrorObject errorObject) {
+ this(new ArrayList<PCEPErrorObject>() {
+ private static final long serialVersionUID = 72172137965955228L;
+
+ {
+ this.add(errorObject);
+ }
+ });
+ }
+
+ public PCEPErrorMessage(final CompositeErrorObject compositeErrorObject) {
+ this(new ArrayList<CompositeErrorObject>() {
+ private static final long serialVersionUID = 72172137965955228L;
+
+ {
+ if (compositeErrorObject != null)
+ this.add(compositeErrorObject);
+ }
+ });
+ }
+
+ /**
+ * Constructs Error Message from list of {@link PCEPErrorObject} or
+ * {@link CompositeErrorObject}.
+ *
+ * @param errorObjects
+ * List<?> either objects of type: {@link PCEPErrorObject} or
+ * {@link CompositeErrorObject}
+ *
+ * @throws IllegalArgumentException
+ * if any other type is passed in the list, that cannot be
+ * processed
+ */
+ public PCEPErrorMessage(final List<?> errorObjects) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = -8607527575304297642L;
+
+ {
+ if (errorObjects != null)
+ for (int i = 0; i < errorObjects.size(); i++) {
+ if (errorObjects.get(i) instanceof CompositeErrorObject) {
+ this.addAll(((CompositeErrorObject) errorObjects.get(i)).getCompositeAsList());
+ } else if (errorObjects.get(i) instanceof PCEPErrorObject) {
+ this.add((PCEPErrorObject) errorObjects.get(i));
+ }
+ }
+ }
+ });
+ this.errors = new ArrayList<CompositeErrorObject>();
+ this.errorObjects = new ArrayList<PCEPErrorObject>();
+
+ if (errorObjects != null) {
+ for (int i = 0; i < errorObjects.size(); i++) {
+ if (errorObjects.get(i) instanceof CompositeErrorObject) {
+ this.errors.add((CompositeErrorObject) errorObjects.get(i));
+ } else if (errorObjects.get(i) instanceof PCEPErrorObject) {
+ this.errorObjects.add((PCEPErrorObject) errorObjects.get(i));
+ } else
+ throw new IllegalArgumentException("Wrong instance passed in list. Acceptable is only CompositeErrorObject or PCEPErrorObject.");
+ }
+ }
+ }
+
+ /**
+ * Constructs Error Message from list of {@link PCEPErrorObject} and
+ * {@link CompositeErrorObject} and {@link PCEPOpenObject} that cannot be
+ * null. This constructor is used during PCEP handshake to suggest new
+ * session characteristics for the session that are listen in
+ * {@link PCEPOpenObject}.
+ *
+ * @param openObj
+ * {@link PCEPOpenObject} cannot be null
+ * @param errorObjects
+ * List<PCEPErrorObject> list of error objects
+ * @param errors
+ * List<CompositeErrorObject> list of composite error objects
+ */
+ public PCEPErrorMessage(final PCEPOpenObject openObj, final List<PCEPErrorObject> errorObjects, final List<CompositeErrorObject> errors) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = -4238105145756981972L;
+
+ {
+ if (errorObjects != null)
+ this.addAll(errorObjects);
+ if (openObj != null)
+ this.add(openObj);
+ if (errors != null)
+ for (final CompositeErrorObject ceo : errors) {
+ this.addAll(ceo.getCompositeAsList());
+ }
+ }
+ });
+ this.openObj = openObj;
+
+ if (errorObjects == null)
+ throw new IllegalArgumentException("At least one PCEPErrorObject is mandatory.");
+ this.errorObjects = errorObjects;
+
+ if (errors == null)
+ this.errors = Collections.emptyList();
+ else
+ this.errors = errors;
+ }
+
+ /**
+ * Gets {@link PCEPOpenObject} if this is included. If its included, it
+ * proposes alternative acceptable session characteristic values.
+ *
+ * @return PCEPOpenObject. May be null.
+ */
+ public PCEPOpenObject getOpenObject() {
+ return this.openObj;
+ }
+
+ /**
+ * In unsolicited manner can be included List of
+ * <code>PCEPErrorObjects</code> <code>PCEPErrorMessage</code>, which is not
+ * sent in response to a request.
+ *
+ * @return List<PCEPErrorObject>
+ */
+ public List<PCEPErrorObject> getErrorObjects() {
+ return this.errorObjects;
+ }
+
+ /**
+ * If the PCErr message is sent in response to a request, the PCErr message
+ * MUST include set of RP objects related to pending path computation
+ * requests that triggered the error condition. In this situation it is
+ * constructed as {@link org.opendaylight.protocol.pcep.object.CompositeErrorObject
+ * CompCompositeErrorObject}. That includes list of RP objects.
+ *
+ * @return CompositeErrorObject. May be null.
+ */
+ public List<CompositeErrorObject> getErrors() {
+ return this.errors;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.errorObjects == null) ? 0 : this.errorObjects.hashCode());
+ result = prime * result + ((this.errors == null) ? 0 : this.errors.hashCode());
+ result = prime * result + ((this.openObj == null) ? 0 : this.openObj.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPErrorMessage other = (PCEPErrorMessage) obj;
+ if (this.errorObjects == null) {
+ if (other.errorObjects != null)
+ return false;
+ } else if (!this.errorObjects.equals(other.errorObjects))
+ return false;
+ if (this.errors == null) {
+ if (other.errors != null)
+ return false;
+ } else if (!this.errors.equals(other.errors))
+ return false;
+ if (this.openObj == null) {
+ if (other.openObj != null)
+ return false;
+ } else if (!this.openObj.equals(other.openObj))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPErrorMessage [openObj=");
+ builder.append(this.openObj);
+ builder.append(", errorObjects=");
+ builder.append(this.errorObjects);
+ builder.append(", errors=");
+ builder.append(this.errors);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.Collections;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure of Keepalive Message
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.3">KeepAlive
+ * Message</a>
+ */
+public final class PCEPKeepAliveMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = 8133032616718362219L;
+
+ /**
+ * Default constructor PCEPKeepAliveMessage.
+ */
+ public PCEPKeepAliveMessage() {
+ super(Collections.<PCEPObject> emptyList());
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPKeepAliveMessage []");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+
+/**
+ * Structure of Notification Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.6">Notification
+ * Message</a>
+ */
+public class PCEPNotificationMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = 2647656169727976386L;
+
+ private final List<CompositeNotifyObject> notifications;
+
+ /**
+ * Constructs new Notification Message.
+ *
+ * @throws IllegalArgumentException
+ * if there is not even one {@link CompositeNotifyObject} in the
+ * list.
+ *
+ * @param notifications
+ * List<CompositeNotifyObject>. Can't be empty or null.
+ */
+ public PCEPNotificationMessage(final List<CompositeNotifyObject> notifications) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = 8359665614469883203L;
+
+ {
+ if (notifications != null)
+ for (final CompositeNotifyObject cno : notifications) {
+ this.addAll(cno.getCompositeAsList());
+ }
+ }
+ });
+
+ if (notifications == null || notifications.isEmpty())
+ throw new IllegalArgumentException("At least one CompositeNotifyObject is mandatory.");
+
+ this.notifications = notifications;
+ }
+
+ /**
+ * Gets list of {@link org.opendaylight.protocol.pcep.object.CompositeNotifyObject
+ * CompositeNotifyObjects}.
+ *
+ * @return List<CompositeNotifyObject>. Can't be null or empty.
+ */
+ public List<CompositeNotifyObject> getNotifications() {
+ return this.notifications;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.notifications == null) ? 0 : this.notifications.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPNotificationMessage other = (PCEPNotificationMessage) obj;
+ if (this.notifications == null) {
+ if (other.notifications != null)
+ return false;
+ } else if (!this.notifications.equals(other.notifications))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPNotificationMessage [notifications=");
+ builder.append(this.notifications);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Structure of Open Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.2">Open
+ * Message</a>
+ */
+public class PCEPOpenMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = -588927926753235030L;
+
+ private final PCEPOpenObject openObj;
+
+ /**
+ * Constructs new Open Message.
+ *
+ * @throws IllegalArgumentException
+ * if the PCEPOpenObject is null.
+ *
+ * @param openObj
+ * {@link PCEPOpenObject}. Can't be null.
+ */
+ public PCEPOpenMessage(final PCEPOpenObject openObj) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = -1339062869814655362L;
+
+ {
+ if (openObj != null)
+ this.add(openObj);
+ }
+ });
+
+ if (openObj == null)
+ throw new IllegalArgumentException("PCEPOpenObject is mandatory.");
+
+ this.openObj = openObj;
+ }
+
+ /**
+ * Gets {@link PCEPOpenObject}
+ *
+ * @return {@link PCEPOpenObject}. Can't be null.
+ */
+ public PCEPOpenObject getOpenObject() {
+ return this.openObj;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.openObj == null) ? 0 : this.openObj.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPOpenMessage other = (PCEPOpenMessage) obj;
+ if (this.openObj == null) {
+ if (other.openObj != null)
+ return false;
+ } else if (!this.openObj.equals(other.openObj))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPOpenMessage [openObj=");
+ builder.append(this.openObj);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeReplySvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+
+/**
+ * Structure for Reply Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.5">Reply
+ * Message</a>
+ */
+public class PCEPReplyMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = -4604680426345882626L;
+
+ private final List<CompositeReplySvecObject> svecList;
+
+ private final List<CompositeResponseObject> responses;
+
+ /**
+ * Constructs new Reply Message.
+ *
+ * @throws IllegalArgumentException
+ * if there is not even one {@link CompositeResponseObject} in
+ * the list.
+ *
+ * @param responses
+ * List<CompositeResponseObject>. Can't be empty or null.
+ */
+ public PCEPReplyMessage(final List<CompositeResponseObject> responses) {
+ this(responses, null);
+ }
+
+ /**
+ * Constructs {@link PCEPReplyMessage}.
+ *
+ * @throws IllegalArgumentException
+ * if there is not even one {@link CompositeResponseObject} in
+ * the list.
+ *
+ * @param svecList
+ * List<CompositeSvecObject>
+ * @param responses
+ * List<CompositeResponseObject>. Can't be empty or null.
+ */
+ public PCEPReplyMessage(final List<CompositeResponseObject> responses, final List<CompositeReplySvecObject> svecList) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = 4464502017081110298L;
+
+ {
+ if (svecList != null)
+ for (final CompositeReplySvecObject cno : svecList) {
+ this.addAll(cno.getCompositeAsList());
+ }
+ if (responses != null)
+ for (final CompositeResponseObject cno : responses) {
+ this.addAll(cno.getCompositeAsList());
+ }
+ }
+ });
+
+ if (responses == null || responses.isEmpty())
+ throw new IllegalArgumentException("At least one CompositeResponseObject is mandatory.");
+ this.responses = responses;
+
+ if (svecList != null)
+ this.svecList = svecList;
+ else
+ this.svecList = Collections.emptyList();
+ }
+
+ /**
+ * Gets list of {@link CompositeResponseObject}.
+ *
+ * @return List<CompositeResponseObject>. Can't be null or empty.
+ */
+ public List<CompositeResponseObject> getResponses() {
+ return this.responses;
+ }
+
+ /**
+ * Gets list of {@link CompositeReplySvecObject}.
+ *
+ * @return List<CompositeReplySvecObject>. Can't be null but may be empty.
+ */
+ public List<CompositeReplySvecObject> getSvecList() {
+ return this.svecList;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.responses == null) ? 0 : this.responses.hashCode());
+ result = prime * result + ((this.svecList == null) ? 0 : this.svecList.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPReplyMessage other = (PCEPReplyMessage) obj;
+ if (this.responses == null) {
+ if (other.responses != null)
+ return false;
+ } else if (!this.responses.equals(other.responses))
+ return false;
+ if (this.svecList == null) {
+ if (other.svecList != null)
+ return false;
+ } else if (!this.svecList.equals(other.svecList))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPReplyMessage [svecList=");
+ builder.append(this.svecList);
+ builder.append(", responses=");
+ builder.append(this.responses);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+
+/**
+ * Structure of Report Message
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.1">State
+ * Report Message</a>
+ */
+public class PCEPReportMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = -3319055709351802748L;
+
+ private final List<CompositeStateReportObject> reports;
+
+ /**
+ * Constructs {@link PCEPReportMessage}.
+ *
+ * @throws IllegalArgumentException
+ * if there is not even one {@link CompositeStateReportObject}
+ * in the list.
+ *
+ * @param reports
+ * List<CompositeStateReportObject>. Can't be empty or null.
+ */
+ public PCEPReportMessage(final List<CompositeStateReportObject> reports) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = 2785287687806615951L;
+
+ {
+ if (reports != null)
+ for (final CompositeStateReportObject csro : reports) {
+ this.addAll(csro.getCompositeAsList());
+ }
+ }
+ });
+ if (reports == null || reports.isEmpty())
+ throw new IllegalArgumentException("At least one CompositeStateReportObject is mandatory.");
+
+ this.reports = reports;
+ }
+
+ /**
+ * Gets list of {@link CompositeStateReportObject}.
+ *
+ * @return List<CompositeStateReportObject>. Can't be null or empty.
+ */
+ public List<CompositeStateReportObject> getStateReports() {
+ return this.reports;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.reports == null) ? 0 : this.reports.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPReportMessage other = (PCEPReportMessage) obj;
+ if (this.reports == null) {
+ if (other.reports != null)
+ return false;
+ } else if (!this.reports.equals(other.reports))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPReportMessage [reports=");
+ builder.append(this.reports);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestSvecObject;
+
+/**
+ * Structure of Request Message.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.4">Request
+ * Message</a>
+ */
+public class PCEPRequestMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = -1914670070018415483L;
+
+ private final List<CompositeRequestSvecObject> svecList;
+
+ private final List<CompositeRequestObject> requests;
+
+ /**
+ * Constructs new Request Message.
+ *
+ * @throws IllegalArgumentException
+ * if there is not even one {@link CompositeRequestObject} in
+ * the list.
+ *
+ * @param requests
+ * List<CompositeRequestObject>. Can't be empty or null.
+ */
+ public PCEPRequestMessage(final List<CompositeRequestObject> requests) {
+ this(null, requests);
+ }
+
+ /**
+ * Constructs new Request Message.
+ *
+ * @throws IllegalArgumentException
+ * if there is not even one {@link CompositeRequestObject} in
+ * the list.
+ *
+ * @param svecList
+ * List<CompositeSvecObject>
+ * @param requests
+ * List<CompositeRequestObject>. Can't be null or empty.
+ */
+ public PCEPRequestMessage(final List<CompositeRequestSvecObject> svecList, final List<CompositeRequestObject> requests) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = -6183368691183167076L;
+
+ {
+ if (svecList != null)
+ for (final CompositeRequestSvecObject cso : svecList) {
+ this.addAll(cso.getCompositeAsList());
+ }
+ if (requests != null)
+ for (final CompositeRequestObject cro : requests) {
+ this.addAll(cro.getCompositeAsList());
+ }
+ }
+ });
+ if (svecList != null)
+ this.svecList = svecList;
+ else
+ this.svecList = Collections.emptyList();
+
+ if (requests == null || requests.isEmpty())
+ throw new IllegalArgumentException("At least one CompositeRequestObject is mandatory.");
+ this.requests = requests;
+
+ }
+
+ /**
+ * Gets list of {@link CompositeRequestSvecObject}.
+ *
+ * @return List<CompositeSvecObject>. Can't be null, but may be empty.
+ */
+ public List<CompositeRequestSvecObject> getSvecObjects() {
+ return this.svecList;
+ }
+
+ /**
+ * Gets list of {@link CompositeRequestObject}.
+ *
+ * @return List<CompositeRequestObject>. Can't be null or empty.
+ */
+ public List<CompositeRequestObject> getRequests() {
+ return this.requests;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.requests == null) ? 0 : this.requests.hashCode());
+ result = prime * result + ((this.svecList == null) ? 0 : this.svecList.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPRequestMessage other = (PCEPRequestMessage) obj;
+ if (this.requests == null) {
+ if (other.requests != null)
+ return false;
+ } else if (!this.requests.equals(other.requests))
+ return false;
+ if (this.svecList == null) {
+ if (other.svecList != null)
+ return false;
+ } else if (!this.svecList.equals(other.svecList))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPRequestMessage [svecObjs=");
+ builder.append(this.svecList);
+ builder.append(", requests=");
+ builder.append(this.requests);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+
+/**
+ * Structure of Update Request Message.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.2">Update
+ * Request Message</a>
+ */
+public class PCEPUpdateRequestMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = 3577204028363946097L;
+
+ private final List<CompositeUpdateRequestObject> updateRequests;
+
+ /**
+ * Constructs new Update Request Message.
+ *
+ * @throws IllegalArgumentException
+ * if there is not even one {@link CompositeUpdateRequestObject}
+ * in the list.
+ *
+ * @param updateRequests
+ * List<CompositeUpdateRequestObject>. Can't be empty or null.
+ */
+ public PCEPUpdateRequestMessage(final List<CompositeUpdateRequestObject> updateRequests) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = 8591736379229064997L;
+
+ {
+ if (updateRequests != null)
+ for (final CompositeUpdateRequestObject curo : updateRequests) {
+ this.addAll(curo.getCompositeAsList());
+ }
+ }
+ });
+
+ if (updateRequests == null || updateRequests.isEmpty())
+ throw new IllegalArgumentException("At least one CompositeUpdateRequestObject is mandatory.");
+ this.updateRequests = updateRequests;
+ }
+
+ /**
+ * Gets list of {@link CompositeUpdateRequestObject}.
+ *
+ * @return List<CompositeUpdateRequestObject>. Can't be null or empty.
+ */
+ public List<CompositeUpdateRequestObject> getUpdateRequests() {
+ return this.updateRequests;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.updateRequests == null) ? 0 : this.updateRequests.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPUpdateRequestMessage other = (PCEPUpdateRequestMessage) obj;
+ if (this.updateRequests == null) {
+ if (other.updateRequests != null)
+ return false;
+ } else if (!this.updateRequests.equals(other.updateRequests))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPUpdateRequestMessage [updateRequests=");
+ builder.append(this.updateRequests);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+
+/**
+ * Add tunnel message for interop with EnXR PCC.
+ */
+public class PCEPXRAddTunnelMessage extends PCEPMessage {
+
+ //private final PCEPRequestParameterObject requestParameter;
+
+ private static final long serialVersionUID = -5832314519461628024L;
+
+ private final PCEPLspObject lsp;
+
+ private final PCEPEndPointsObject<?> endPoints;
+
+ private final PCEPExplicitRouteObject ero;
+
+ public PCEPXRAddTunnelMessage(final PCEPLspObject lsp,
+ final PCEPEndPointsObject<?> endPoints, final PCEPExplicitRouteObject ero) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = -1810245662746464028L;
+
+ {
+ //if (requestParameter != null)
+ // this.add(requestParameter);
+ if (lsp != null)
+ this.add(lsp);
+ if (endPoints != null)
+ this.add(endPoints);
+ if (ero != null)
+ this.add(ero);
+ }
+ });
+ if (lsp == null || endPoints == null || ero == null)
+ throw new IllegalArgumentException("All objects are mandatory. Can't be null.");
+ // this.requestParameter = requestParameter;
+ this.lsp = lsp;
+ this.endPoints = endPoints;
+ this.ero = ero;
+ }
+
+ /**
+ * @return the requestParameter
+ */
+// public PCEPRequestParameterObject getRequestParameter() {
+// return this.requestParameter;
+// }
+
+ /**
+ * @return the lsp
+ */
+ public PCEPLspObject getLsp() {
+ return this.lsp;
+ }
+
+ /**
+ * @return the endPoints
+ */
+ public PCEPEndPointsObject<?> getEndPoints() {
+ return this.endPoints;
+ }
+
+ /**
+ * @return the ero
+ */
+ public PCEPExplicitRouteObject getEro() {
+ return this.ero;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((this.endPoints == null) ? 0 : this.endPoints.hashCode());
+ result = prime * result + ((this.ero == null) ? 0 : this.ero.hashCode());
+ result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof PCEPXRAddTunnelMessage))
+ return false;
+ final PCEPXRAddTunnelMessage other = (PCEPXRAddTunnelMessage) obj;
+ if (this.endPoints == null) {
+ if (other.endPoints != null)
+ return false;
+ } else if (!this.endPoints.equals(other.endPoints))
+ return false;
+ if (this.ero == null) {
+ if (other.ero != null)
+ return false;
+ } else if (!this.ero.equals(other.ero))
+ return false;
+ if (this.lsp == null) {
+ if (other.lsp != null)
+ return false;
+ } else if (!this.lsp.equals(other.lsp))
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPXRAddTunnelMessage [lsp=");
+ builder.append(this.lsp);
+ builder.append(", endPoints=");
+ builder.append(this.endPoints);
+ builder.append(", ero=");
+ builder.append(this.ero);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.message;
+
+import java.util.ArrayList;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+
+/**
+ * Delete tunnel message for interop with EnXR PCC.
+ */
+public class PCEPXRDeleteTunnelMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = -8147187272108419351L;
+
+ private final PCEPLspObject lsp;
+
+ public PCEPXRDeleteTunnelMessage(final PCEPLspObject lsp) {
+ super(new ArrayList<PCEPObject>() {
+
+ private static final long serialVersionUID = 3374457164202667362L;
+
+ {
+ if (lsp != null)
+ this.add(lsp);
+ }
+ });
+ if (lsp == null)
+ throw new IllegalArgumentException("All objects are mandatory. Can't be null.");
+ this.lsp = lsp;
+ }
+
+ /**
+ * @return the lsp
+ */
+ public PCEPLspObject getLsp() {
+ return this.lsp;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+ return result;
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (!(obj instanceof PCEPXRDeleteTunnelMessage))
+ return false;
+ final PCEPXRDeleteTunnelMessage other = (PCEPXRDeleteTunnelMessage) obj;
+ if (this.lsp == null) {
+ if (other.lsp != null)
+ return false;
+ } else if (!this.lsp.equals(other.lsp))
+ return false;
+ return true;
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPXRDeleteTunnelMessage [lsp=");
+ builder.append(this.lsp);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.7">Error (PCErr)
+ * Message</a> - <error>
+ */
+public class CompositeErrorObject {
+
+ private List<PCEPRequestParameterObject> requestParameters;
+
+ private final List<PCEPErrorObject> errors;
+
+ public CompositeErrorObject(final PCEPRequestParameterObject requestParameter, final PCEPErrorObject error) {
+ this(new ArrayList<PCEPRequestParameterObject>() {
+ private static final long serialVersionUID = -3974192068960284132L;
+
+ {
+ if (requestParameter != null)
+ this.add(requestParameter);
+ }
+ }, new ArrayList<PCEPErrorObject>() {
+ private static final long serialVersionUID = -3976331879683713909L;
+
+ {
+ if (error != null)
+ this.add(error);
+ }
+ });
+ }
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param errors
+ * List<PCEPErrorObject>. Can't be null or empty.
+ */
+ public CompositeErrorObject(List<PCEPErrorObject> errors) {
+ this(null, errors);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param requestParameters
+ * List<PCEPRequestParameterObject>
+ * @param errors
+ * List<PCEPErrorObject>. Can't be null or empty.
+ */
+ public CompositeErrorObject(List<PCEPRequestParameterObject> requestParameters, List<PCEPErrorObject> errors) {
+
+ if (errors == null || errors.isEmpty())
+ throw new IllegalArgumentException("Error Object is mandatory.");
+ this.errors = errors;
+ if (requestParameters != null)
+ this.requestParameters = requestParameters;
+ else
+ this.requestParameters = Collections.emptyList();
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>. Can't be null or empty.
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ if (this.requestParameters != null && !this.requestParameters.isEmpty())
+ list.addAll(this.requestParameters);
+ list.addAll(this.errors);
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ *
+ * @param objects
+ * List<PCEPObject> list of PCEPObjects from whose this object
+ * should be created.
+ * @return CompositeErrorObject
+ */
+ public static CompositeErrorObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty())
+ throw new IllegalArgumentException("List cannot be null or empty.");
+
+ final List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+ final List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPRequestParameterObject) {
+ requestParameters.add((PCEPRequestParameterObject) obj);
+ state = 1;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPErrorObject) {
+ errors.add((PCEPErrorObject) obj);
+ state = 2;
+ break;
+ }
+ }
+
+ if (state == 3) {
+ break;
+ }
+
+ objects.remove(obj);
+ }
+
+ if (errors.isEmpty())
+ throw new IllegalArgumentException("Atleast one PCEPErrorObject is mandatory.");
+
+ return new CompositeErrorObject(requestParameters, errors);
+ }
+
+ /**
+ * Gets list of {@link PCEPRequestParameterObject}.
+ *
+ * @return List<PCEPRequestParameterObject>. Can't be null, but may be
+ * empty.
+ */
+ public List<PCEPRequestParameterObject> getRequestParameters() {
+ return this.requestParameters;
+ }
+
+ /**
+ * Gets list of {@link PCEPErrorObject}
+ *
+ * @return List<PCEPErrorObject>. Can't be null or empty.
+ */
+ public List<PCEPErrorObject> getErrors() {
+ return this.errors;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.errors == null) ? 0 : this.errors.hashCode());
+ result = prime * result + ((this.requestParameters == null) ? 0 : this.requestParameters.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositeErrorObject other = (CompositeErrorObject) obj;
+ if (this.errors == null) {
+ if (other.errors != null)
+ return false;
+ } else if (!this.errors.equals(other.errors))
+ return false;
+ if (this.requestParameters == null) {
+ if (other.requestParameters != null)
+ return false;
+ } else if (!this.requestParameters.equals(other.requestParameters))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeErrorObject [requestParameters=");
+ builder.append(this.requestParameters);
+ builder.append(", errors=");
+ builder.append(this.errors);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt">PCCreate Message</a>
+ */
+public class CompositeInstantiationObject {
+
+ private final PCEPEndPointsObject<?> endPoints;
+
+ private final PCEPLspaObject lspa;
+
+ private final PCEPExplicitRouteObject ero;
+
+ private final PCEPRequestedPathBandwidthObject bandwidth;
+
+ private final List<PCEPMetricObject> metrics;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param endPoints
+ * PCEPEndPointsObject<?>. Can't be null.
+ * @param lspa
+ * PCEPLspaObject. Can't be null.
+ */
+ public CompositeInstantiationObject(PCEPEndPointsObject<?> endPoints, PCEPLspaObject lspa) {
+ this(endPoints, lspa, null, null, null);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param endPoints
+ * PCEPEndPointsObject<?>. Can't be null.
+ * @param lspa
+ * PCEPLspaObject. Can't be null.
+ * @param ero
+ * PCEPExplicitRouteObject
+ * @param bandwidth
+ * PCEPRequestedPathBandwidthObject
+ * @param metrics
+ * List<PCEPMetricObject>
+ */
+ public CompositeInstantiationObject(PCEPEndPointsObject<?> endPoints, PCEPLspaObject lspa, PCEPExplicitRouteObject ero, PCEPRequestedPathBandwidthObject bandwidth, List<PCEPMetricObject> metrics) {
+ this.endPoints = endPoints;
+ this.lspa = lspa;
+ this.ero = ero;
+ this.bandwidth = bandwidth;
+ this.metrics = metrics;
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>. Can't be null or empty.
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.endPoints);
+ list.add(this.lspa);
+ if (this.ero != null)
+ list.add(this.ero);
+ if (this.bandwidth != null)
+ list.add(this.bandwidth);
+ if (this.metrics != null && !this.metrics.isEmpty())
+ list.addAll(this.metrics);
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ *
+ * @param objects
+ * List<PCEPObject> list of PCEPObjects from whose this object
+ * should be created.
+ * @return CompositeInstantiationObject
+ */
+ public static CompositeInstantiationObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+
+ PCEPEndPointsObject<?> endPoints = null;
+ if (objects.get(0) instanceof PCEPEndPointsObject<?>) {
+ endPoints = (PCEPEndPointsObject<?>) objects.get(0);
+ objects.remove(endPoints);
+ } else
+ throw new IllegalArgumentException("End Points object must be first.");
+
+ PCEPLspaObject lspa = null;
+ if (objects.get(0) instanceof PCEPLspaObject) {
+ lspa = (PCEPLspaObject) objects.get(0);
+ objects.remove(lspa);
+ } else
+ throw new IllegalArgumentException("LSPA object must be second.");
+
+ PCEPExplicitRouteObject ero = null;
+ PCEPRequestedPathBandwidthObject bandwidth = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPExplicitRouteObject) {
+ ero = (PCEPExplicitRouteObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 3;
+
+ break;
+ }
+ }
+
+ if (state == 4) {
+ break;
+ }
+
+ objects.remove(obj);
+ }
+
+ return new CompositeInstantiationObject(endPoints, lspa, ero, bandwidth, metrics);
+ }
+
+ /**
+ * @return the endPoints
+ */
+ public final PCEPEndPointsObject<?> getEndPoints() {
+ return this.endPoints;
+ }
+
+ /**
+ * @return the lspa
+ */
+ public final PCEPLspaObject getLspa() {
+ return this.lspa;
+ }
+
+ /**
+ * @return the ero
+ */
+ public final PCEPExplicitRouteObject getEro() {
+ return this.ero;
+ }
+
+ /**
+ * @return the bandwidth
+ */
+ public final PCEPRequestedPathBandwidthObject getBandwidth() {
+ return this.bandwidth;
+ }
+
+ /**
+ * @return the metrics
+ */
+ public final List<PCEPMetricObject> getMetrics() {
+ return this.metrics;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+ result = prime * result
+ + ((this.endPoints == null) ? 0 : this.endPoints.hashCode());
+ result = prime * result + ((this.ero == null) ? 0 : this.ero.hashCode());
+ result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+ result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof CompositeInstantiationObject))
+ return false;
+ final CompositeInstantiationObject other = (CompositeInstantiationObject) obj;
+ if (this.bandwidth == null) {
+ if (other.bandwidth != null)
+ return false;
+ } else if (!this.bandwidth.equals(other.bandwidth))
+ return false;
+ if (this.endPoints == null) {
+ if (other.endPoints != null)
+ return false;
+ } else if (!this.endPoints.equals(other.endPoints))
+ return false;
+ if (this.ero == null) {
+ if (other.ero != null)
+ return false;
+ } else if (!this.ero.equals(other.ero))
+ return false;
+ if (this.lspa == null) {
+ if (other.lspa != null)
+ return false;
+ } else if (!this.lspa.equals(other.lspa))
+ return false;
+ if (this.metrics == null) {
+ if (other.metrics != null)
+ return false;
+ } else if (!this.metrics.equals(other.metrics))
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeInstantiationObject [endPoints=");
+ builder.append(this.endPoints);
+ builder.append(", lspa=");
+ builder.append(this.lspa);
+ builder.append(", ero=");
+ builder.append(this.ero);
+ builder.append(", bandwidth=");
+ builder.append(this.bandwidth);
+ builder.append(", metrics=");
+ builder.append(this.metrics);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.6">Notification
+ * (PCNtf) Message</a> - <notify>
+ */
+public class CompositeNotifyObject {
+
+ private List<PCEPRequestParameterObject> requestParameters;
+
+ private final List<PCEPNotificationObject> notifications;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param notifications
+ * List<PCEPNotificationObject>. Can't be null or empty.
+ */
+ public CompositeNotifyObject(List<PCEPNotificationObject> notifications) {
+ this(null, notifications);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param requestParameters
+ * List<PCEPRequestParameterObject>
+ * @param notifications
+ * List<PCEPNotificationObject>. Can't be null or empty.
+ */
+ public CompositeNotifyObject(List<PCEPRequestParameterObject> requestParameters, List<PCEPNotificationObject> notifications) {
+ if (notifications == null || notifications.isEmpty())
+ throw new IllegalArgumentException("Notification Object is mandatory.");
+ if (requestParameters != null)
+ this.requestParameters = requestParameters;
+ else
+ this.requestParameters = Collections.emptyList();
+ this.notifications = notifications;
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ if (this.requestParameters != null && !this.requestParameters.isEmpty())
+ list.addAll(this.requestParameters);
+ list.addAll(this.notifications);
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ * @param objects List<PCEPObject> list of PCEPObjects from whose this
+ * object should be created.
+ * @return CompositeNotifyObject
+ */
+ public static CompositeNotifyObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty())
+ throw new IllegalArgumentException("List cannot be null or empty.");
+
+ final List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+ final List<PCEPNotificationObject> notifications = new ArrayList<PCEPNotificationObject>();
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPRequestParameterObject) {
+ requestParameters.add((PCEPRequestParameterObject) obj);
+ state = 1;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPNotificationObject) {
+ notifications.add((PCEPNotificationObject) obj);
+ state = 2;
+ break;
+ }
+ }
+
+ if (state == 3) {
+ break;
+ }
+
+ objects.remove(obj);
+ }
+
+ if (notifications.isEmpty())
+ return null;
+
+ return new CompositeNotifyObject(requestParameters, notifications);
+ }
+
+ /**
+ * Gets list of {@link PCEPRequestParameterObject}.
+ *
+ * @return List<PCEPRequestParameterObject>. Can't be null, but may be
+ * empty.
+ */
+ public List<PCEPRequestParameterObject> getRequestParameters() {
+ return this.requestParameters;
+ }
+
+ /**
+ * Gets list of {@link PCEPNotificationObject}.
+ *
+ * @return List<PCEPNotificationObject>. Can't be null or empty.
+ */
+ public List<PCEPNotificationObject> getNotificationObjects() {
+ return this.notifications;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.notifications == null) ? 0 : this.notifications.hashCode());
+ result = prime * result + ((this.requestParameters == null) ? 0 : this.requestParameters.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositeNotifyObject other = (CompositeNotifyObject) obj;
+ if (this.notifications == null) {
+ if (other.notifications != null)
+ return false;
+ } else if (!this.notifications.equals(other.notifications))
+ return false;
+ if (this.requestParameters == null) {
+ if (other.requestParameters != null)
+ return false;
+ } else if (!this.requestParameters.equals(other.requestParameters))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeNotifyObject [requestParameters=");
+ builder.append(this.requestParameters);
+ builder.append(", notifications=");
+ builder.append(this.notifications);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.5">Path
+ * Computation Reply (PCRep) Message</a> - <path></br> Same for every
+ * usage of path object.
+ */
+public class CompositePathObject {
+
+ private final PCEPExplicitRouteObject explicitRoute;
+
+ private final PCEPLspaObject lspa;
+
+ private final PCEPRequestedPathBandwidthObject bandwidth;
+
+ private List<PCEPMetricObject> metrics;
+
+ private final PCEPIncludeRouteObject includeRoute;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param explicitRoute
+ * PCEPExplicitRouteObject. Can't be null or empty.
+ */
+ public CompositePathObject(PCEPExplicitRouteObject explicitRoute) {
+ this(explicitRoute, null, null, null, null);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param explicitRoute
+ * PCEPExplicitRouteObject. Can't be null or empty.
+ * @param lspa
+ * PCEPLspaObject
+ * @param bandwidth
+ * PCEPRequestedPathBandwidthObject
+ * @param metrics
+ * List<PCEPMetricObject>
+ * @param includeRoute
+ * PCEPIncludeRouteObject
+ */
+ public CompositePathObject(PCEPExplicitRouteObject explicitRoute, PCEPLspaObject lspa, PCEPRequestedPathBandwidthObject bandwidth,
+ List<PCEPMetricObject> metrics, PCEPIncludeRouteObject includeRoute) {
+ if (explicitRoute == null)
+ throw new IllegalArgumentException("Explicit Route Object is mandatory.");
+ this.explicitRoute = explicitRoute;
+ this.lspa = lspa;
+ this.bandwidth = bandwidth;
+ if (metrics != null)
+ this.metrics = metrics;
+ else
+ this.metrics = Collections.emptyList();
+ this.includeRoute = includeRoute;
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>. Can't be null or empty.
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.explicitRoute);
+ if (this.lspa != null)
+ list.add(this.lspa);
+ if (this.bandwidth != null)
+ list.add(this.bandwidth);
+ if (this.metrics != null && !this.metrics.isEmpty())
+ list.addAll(this.metrics);
+ if (this.includeRoute != null)
+ list.add(this.includeRoute);
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ * @param objects List<PCEPObject> list of PCEPObjects from whose this
+ * object should be created.
+ * @return CompositePathObject
+ */
+ public static CompositePathObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+
+ PCEPExplicitRouteObject explicitRoute = null;
+ if (objects.get(0) instanceof PCEPExplicitRouteObject) {
+ explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+ objects.remove(explicitRoute);
+ } else
+ return null;
+
+ PCEPLspaObject lspa = null;
+ PCEPRequestedPathBandwidthObject bandwidth = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+ PCEPIncludeRouteObject iro = null;
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPLspaObject) {
+ lspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 3:
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 3;
+ break;
+ } else
+ state = 4;
+ case 4:
+ if (obj instanceof PCEPIncludeRouteObject) {
+ iro = (PCEPIncludeRouteObject) obj;
+ break;
+ }
+ state = 5;
+ }
+
+ if (state == 5) {
+ break;
+ }
+
+ objects.remove(obj);
+ }
+
+ return new CompositePathObject(explicitRoute, lspa, bandwidth, metrics, iro);
+ }
+
+ /**
+ * Gets {@link PCEPExplicitRouteObject}.
+ *
+ * @return PCEPExplicitRouteObject. Can't be null.
+ */
+ public PCEPExplicitRouteObject getExcludedRoute() {
+ return this.explicitRoute;
+ }
+
+ /**
+ * Gets {@link PCEPLspaObject}.
+ *
+ * @return PCEPLspaObject. May be null.
+ */
+ public PCEPLspaObject getLspa() {
+ return this.lspa;
+ }
+
+ /**
+ * Gets {@link PCEPBandwidthObject}.
+ *
+ * @return PCEPBandwidthObject. May be null.
+ */
+ public PCEPBandwidthObject getBandwidth() {
+ return this.bandwidth;
+ }
+
+ /**
+ * Gets list of {@link PCEPMetricObject}.
+ *
+ * @return List<PCEPMetricObject>. Can't be null, but may be empty.
+ */
+ public List<PCEPMetricObject> getMetrics() {
+ return this.metrics;
+ }
+
+ /**
+ * Gets {@link PCEPIncludeRouteObject}.
+ *
+ * @return PCEPIncludeRouteObject. May be null.
+ */
+ public PCEPIncludeRouteObject getIncludeRoute() {
+ return this.includeRoute;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+ result = prime * result + ((this.explicitRoute == null) ? 0 : this.explicitRoute.hashCode());
+ result = prime * result + ((this.includeRoute == null) ? 0 : this.includeRoute.hashCode());
+ result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+ result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositePathObject other = (CompositePathObject) obj;
+ if (this.bandwidth == null) {
+ if (other.bandwidth != null)
+ return false;
+ } else if (!this.bandwidth.equals(other.bandwidth))
+ return false;
+ if (this.explicitRoute == null) {
+ if (other.explicitRoute != null)
+ return false;
+ } else if (!this.explicitRoute.equals(other.explicitRoute))
+ return false;
+ if (this.includeRoute == null) {
+ if (other.includeRoute != null)
+ return false;
+ } else if (!this.includeRoute.equals(other.includeRoute))
+ return false;
+ if (this.lspa == null) {
+ if (other.lspa != null)
+ return false;
+ } else if (!this.lspa.equals(other.lspa))
+ return false;
+ if (this.metrics == null) {
+ if (other.metrics != null)
+ return false;
+ } else if (!this.metrics.equals(other.metrics))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositePathObject [explicitRoute=");
+ builder.append(this.explicitRoute);
+ builder.append(", lspa=");
+ builder.append(this.lspa);
+ builder.append(", bandwidth=");
+ builder.append(this.bandwidth);
+ builder.append(", metrics=");
+ builder.append(this.metrics);
+ builder.append(", includeRoute=");
+ builder.append(this.includeRoute);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+
+/**
+ * Composite SvecObject used in {@link PCEPReplyMessage}
+ */
+public class CompositeReplySvecObject {
+
+ private final PCEPSvecObject svec;
+ private final PCEPObjectiveFunctionObject objectiveFunction;
+ private final List<PCEPMetricObject> metrics;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param svec
+ * PCEPSvecObject
+ */
+ public CompositeReplySvecObject(PCEPSvecObject svec) {
+ this(svec, null, null);
+ }
+
+ /**
+ * Constructs composite object also with optional objects.
+ *
+ * @param svec
+ * PCEPSvecObject
+ * @param objectiveFunction
+ * PCEPObjectiveFunctionObject
+ * @param metrics
+ * list of PCEPMetricObject
+ */
+ public CompositeReplySvecObject(PCEPSvecObject svec, PCEPObjectiveFunctionObject objectiveFunction, List<PCEPMetricObject> metrics) {
+ if (svec == null)
+ throw new IllegalArgumentException("Svec object is mandatory.");
+ this.svec = svec;
+ this.objectiveFunction = objectiveFunction;
+ if (metrics != null)
+ this.metrics = metrics;
+ else
+ this.metrics = Collections.emptyList();
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>. Can't be null or empty.
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.svec);
+ if (this.objectiveFunction != null)
+ list.add(this.objectiveFunction);
+ if (this.metrics != null && !this.metrics.isEmpty())
+ list.addAll(this.metrics);
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ *
+ * @param objects
+ * List<PCEPObject> list of PCEPObjects from whose this object
+ * should be created.
+ * @return CompositePathObject
+ */
+ public static CompositeReplySvecObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+
+ PCEPSvecObject svec = null;
+ if (objects.get(0) instanceof PCEPSvecObject) {
+ svec = (PCEPSvecObject) objects.get(0);
+ objects.remove(svec);
+ } else
+ return null;
+
+ PCEPObjectiveFunctionObject of = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPObjectiveFunctionObject) {
+ of = (PCEPObjectiveFunctionObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 2;
+
+ break;
+ }
+ }
+
+ if (state == 3)
+ break;
+
+ objects.remove(obj);
+ }
+
+ return new CompositeReplySvecObject(svec, of, metrics);
+ }
+
+ /**
+ * Gets {@link PCEPSvecObject}
+ *
+ * @return PCEPSvecObject. Can't be null.
+ */
+ public PCEPSvecObject getSvec() {
+ return this.svec;
+ }
+
+ /**
+ * Gets {@link PCEPObjectiveFunctionObject}
+ *
+ * @return PCEPObjectiveFunctionObject. May be null.
+ */
+ public PCEPObjectiveFunctionObject getObjectiveFunction() {
+ return this.objectiveFunction;
+ }
+
+ /**
+ * @return the metrics
+ */
+ public List<PCEPMetricObject> getMetrics() {
+ return this.metrics;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeReplySvecObject [svec=");
+ builder.append(this.svec);
+ builder.append(", objectiveFunction=");
+ builder.append(this.objectiveFunction);
+ builder.append(", metrics=");
+ builder.append(this.metrics);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+ result = prime * result + ((this.objectiveFunction == null) ? 0 : this.objectiveFunction.hashCode());
+ result = prime * result + ((this.svec == null) ? 0 : this.svec.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositeReplySvecObject other = (CompositeReplySvecObject) obj;
+ if (this.metrics == null) {
+ if (other.metrics != null)
+ return false;
+ } else if (!this.metrics.equals(other.metrics))
+ return false;
+ if (this.objectiveFunction == null) {
+ if (other.objectiveFunction != null)
+ return false;
+ } else if (!this.objectiveFunction.equals(other.objectiveFunction))
+ return false;
+ if (this.svec == null) {
+ if (other.svec != null)
+ return false;
+ } else if (!this.svec.equals(other.svec))
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.4">Path
+ * Computation Request (PCReq) Message</a> - <request></br>
+ *
+ * @see <a href="tools.ietf.org/html/rfc5455#section-3.2">Path Computation
+ * Request Message with CLASSTYPE Object</a>
+ */
+public class CompositeRequestObject {
+
+ private final PCEPRequestParameterObject requestParameter;
+
+ private final PCEPEndPointsObject<?> endPoints;
+
+ private final PCEPClassTypeObject classType;
+
+ private final PCEPLspObject lsp;
+
+ private final PCEPLspaObject lspa;
+
+ private final PCEPRequestedPathBandwidthObject bandwidth;
+
+ private final List<PCEPMetricObject> metrics;
+
+ private final PCEPReportedRouteObject reportedRoute;
+
+ private final PCEPExistingPathBandwidthObject rroBandwidth;
+
+ private final PCEPIncludeRouteObject includeRoute;
+
+ private final PCEPLoadBalancingObject loadBalancing;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param requestParameter
+ * PCEPRequestParameterObject. Can't be null.
+ * @param endPoints
+ * PCEPEndPointsObject<?>. Can't be null.
+ */
+ public CompositeRequestObject(PCEPRequestParameterObject requestParameter, PCEPEndPointsObject<?> endPoints) {
+ this(requestParameter, endPoints, null, null, null, null, null, null, null, null, null);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param requestParameter
+ * PCEPRequestParameterObject. Can't be null.
+ * @param endPoints
+ * PCEPEndPointsObject<?>. Can't be null.
+ * @param classType
+ * PCEPClassTypeObject
+ * @param lsp
+ * PCEPLspObject
+ * @param lspa
+ * PCEPLspaObject
+ * @param bandwidth
+ * PCEPRequestedPathBandwidthObject
+ * @param metrics
+ * List<PCEPMetricObject>
+ * @param reportedRoute
+ * PCEPReportedRouteObject
+ * @param rroBandwidth
+ * PCEPExistingPathBandwidthObject
+ * @param includeRoute
+ * PCEPIncludeRouteObject
+ * @param loadBalancing
+ * PCEPLoadBalancingObject
+ */
+ public CompositeRequestObject(PCEPRequestParameterObject requestParameter, PCEPEndPointsObject<?> endPoints, PCEPClassTypeObject classType,
+ PCEPLspObject lsp, PCEPLspaObject lspa, PCEPRequestedPathBandwidthObject bandwidth, List<PCEPMetricObject> metrics,
+ PCEPReportedRouteObject reportedRoute, PCEPExistingPathBandwidthObject rroBandwidth, PCEPIncludeRouteObject includeRoute,
+ PCEPLoadBalancingObject loadBalancing) {
+ if (requestParameter == null)
+ throw new IllegalArgumentException("Request Parameter Object is mandatory.");
+ if (endPoints == null)
+ throw new IllegalArgumentException("End-Points Object is mandatory.");
+ this.requestParameter = requestParameter;
+ this.endPoints = endPoints;
+ this.classType = classType;
+ this.lsp = lsp;
+ this.lspa = lspa;
+ this.bandwidth = bandwidth;
+ if (metrics != null)
+ this.metrics = metrics;
+ else
+ this.metrics = Collections.emptyList();
+ this.reportedRoute = reportedRoute;
+ this.rroBandwidth = rroBandwidth;
+ this.includeRoute = includeRoute;
+ this.loadBalancing = loadBalancing;
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>. Can't be null or empty.
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.requestParameter);
+ list.add(this.endPoints);
+ if (this.classType != null)
+ list.add(this.classType);
+ if (this.lsp != null)
+ list.add(this.lsp);
+ if (this.lspa != null)
+ list.add(this.lspa);
+ if (this.bandwidth != null)
+ list.add(this.bandwidth);
+ if (this.metrics != null && !this.metrics.isEmpty())
+ list.addAll(this.metrics);
+ if (this.reportedRoute != null) {
+ list.add(this.reportedRoute);
+ if (this.rroBandwidth != null)
+ list.add(this.rroBandwidth);
+ }
+ if (this.includeRoute != null)
+ list.add(this.includeRoute);
+ if (this.loadBalancing != null)
+ list.add(this.loadBalancing);
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ *
+ * @param objects
+ * List<PCEPObject> list of PCEPObjects from whose this object
+ * should be created.
+ * @return CompositeRequestObject
+ */
+ public static CompositeRequestObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+ PCEPRequestParameterObject requestParameter = null;
+ if (objects.get(0) instanceof PCEPRequestParameterObject) {
+ requestParameter = (PCEPRequestParameterObject) objects.get(0);
+ objects.remove(requestParameter);
+ } else
+ return null;
+
+ PCEPEndPointsObject<?> endPoints = null;
+ if (objects.get(0) instanceof PCEPEndPointsObject<?>) {
+ endPoints = (PCEPEndPointsObject<?>) objects.get(0);
+ objects.remove(endPoints);
+ } else
+ throw new IllegalArgumentException("End Points object must be second.");
+
+ PCEPClassTypeObject classType = null;
+ PCEPLspObject lsp = null;
+ PCEPLspaObject lspa = null;
+ PCEPRequestedPathBandwidthObject bandwidth = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+ PCEPReportedRouteObject rro = null;
+ PCEPExistingPathBandwidthObject rroBandwidth = null;
+ PCEPIncludeRouteObject iro = null;
+ PCEPLoadBalancingObject loadBalancing = null;
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPClassTypeObject) {
+ classType = (PCEPClassTypeObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPLspObject) {
+ lsp = (PCEPLspObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPLspaObject) {
+ lspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 4:
+ state = 5;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 5:
+ state = 6;
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 5;
+
+ break;
+ }
+ case 6:
+ state = 8;
+ if (obj instanceof PCEPReportedRouteObject) {
+ rro = (PCEPReportedRouteObject) obj;
+ state = 7;
+ break;
+ }
+ case 7:
+ state = 8;
+ if (obj instanceof PCEPExistingPathBandwidthObject) {
+ rroBandwidth = (PCEPExistingPathBandwidthObject) obj;
+ break;
+ }
+ case 8:
+ state = 9;
+ if (obj instanceof PCEPIncludeRouteObject) {
+ iro = (PCEPIncludeRouteObject) obj;
+ break;
+ }
+ case 9:
+ if (obj instanceof PCEPLoadBalancingObject) {
+ loadBalancing = (PCEPLoadBalancingObject) obj;
+ break;
+ }
+ state = 10;
+ }
+
+ if (state == 10) {
+ break;
+ }
+
+ objects.remove(obj);
+ }
+
+ return new CompositeRequestObject(requestParameter, endPoints, classType, lsp, lspa, bandwidth, metrics, rro, rroBandwidth, iro, loadBalancing);
+ }
+
+ /**
+ * Gets {@link PCEPRequestParameterObject}.
+ *
+ * @return PCEPRequestParameterObject. Can't be null.
+ */
+ public PCEPRequestParameterObject getRequestParameter() {
+ return this.requestParameter;
+ }
+
+ /**
+ * Gets {@link PCEPEndPointsObject}.
+ *
+ * @return PCEPEndPointsObject<?>. Can't be null.
+ */
+ public PCEPEndPointsObject<?> getEndPoints() {
+ return this.endPoints;
+ }
+
+ /**
+ * Gets {@link PCEPClassTypeObject}.
+ *
+ * @return PCEPClassTypeObject. May be null.
+ */
+ public PCEPClassTypeObject getClassType() {
+ return this.classType;
+ }
+
+ /**
+ * Gets {@link PCEPLspObject}.
+ *
+ * @return PCEPLspObject. May be null.
+ */
+ public PCEPLspObject getLsp() {
+ return this.lsp;
+ }
+
+ /**
+ * Gets {@link PCEPLspaObject}.
+ *
+ * @return PCEPLspaObject. May be null.
+ */
+ public PCEPLspaObject getLspa() {
+ return this.lspa;
+ }
+
+ /**
+ * Gets {@link PCEPBandwidthObject}.
+ *
+ * @return PCEPBandwidthObject. May be null.
+ */
+ public PCEPBandwidthObject getBandwidth() {
+ return this.bandwidth;
+ }
+
+ /**
+ * Gets list of {@link PCEPMetricObject}.
+ *
+ * @return List<PCEPMetricObject>
+ */
+ public List<PCEPMetricObject> getMetrics() {
+ return this.metrics;
+ }
+
+ /**
+ * Gets {@link PCEPReportedRouteObject}.
+ *
+ * @return PCEPReportedRouteObject. May be null.
+ */
+ public PCEPReportedRouteObject getReportedRoute() {
+ return this.reportedRoute;
+ }
+
+ /**
+ * Gets {@link PCEPBandwidthObject}.
+ *
+ * @return PCEPBandwidthObject. May be null.
+ */
+ public PCEPBandwidthObject getRroBandwidth() {
+ return this.rroBandwidth;
+ }
+
+ /**
+ * Gets {@link PCEPIncludeRouteObject}.
+ *
+ * @return PCEPIncludeRouteObject. May be null.
+ */
+ public PCEPIncludeRouteObject getIncludeRoute() {
+ return this.includeRoute;
+ }
+
+ /**
+ * Gets {@link PCEPLoadBalancingObject}.
+ *
+ * @return PCEPLoadBalancingObject. May be null.
+ */
+ public PCEPLoadBalancingObject getLoadBalancing() {
+ return this.loadBalancing;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+ result = prime * result + ((this.classType == null) ? 0 : this.classType.hashCode());
+ result = prime * result + ((this.endPoints == null) ? 0 : this.endPoints.hashCode());
+ result = prime * result + ((this.includeRoute == null) ? 0 : this.includeRoute.hashCode());
+ result = prime * result + ((this.loadBalancing == null) ? 0 : this.loadBalancing.hashCode());
+ result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+ result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+ result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+ result = prime * result + ((this.reportedRoute == null) ? 0 : this.reportedRoute.hashCode());
+ result = prime * result + ((this.requestParameter == null) ? 0 : this.requestParameter.hashCode());
+ result = prime * result + ((this.rroBandwidth == null) ? 0 : this.rroBandwidth.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof CompositeRequestObject))
+ return false;
+ final CompositeRequestObject other = (CompositeRequestObject) obj;
+ if (this.bandwidth == null) {
+ if (other.bandwidth != null)
+ return false;
+ } else if (!this.bandwidth.equals(other.bandwidth))
+ return false;
+ if (this.classType == null) {
+ if (other.classType != null)
+ return false;
+ } else if (!this.classType.equals(other.classType))
+ return false;
+ if (this.endPoints == null) {
+ if (other.endPoints != null)
+ return false;
+ } else if (!this.endPoints.equals(other.endPoints))
+ return false;
+ if (this.includeRoute == null) {
+ if (other.includeRoute != null)
+ return false;
+ } else if (!this.includeRoute.equals(other.includeRoute))
+ return false;
+ if (this.loadBalancing == null) {
+ if (other.loadBalancing != null)
+ return false;
+ } else if (!this.loadBalancing.equals(other.loadBalancing))
+ return false;
+ if (this.lsp == null) {
+ if (other.lsp != null)
+ return false;
+ } else if (!this.lsp.equals(other.lsp))
+ return false;
+ if (this.lspa == null) {
+ if (other.lspa != null)
+ return false;
+ } else if (!this.lspa.equals(other.lspa))
+ return false;
+ if (this.metrics == null) {
+ if (other.metrics != null)
+ return false;
+ } else if (!this.metrics.equals(other.metrics))
+ return false;
+ if (this.reportedRoute == null) {
+ if (other.reportedRoute != null)
+ return false;
+ } else if (!this.reportedRoute.equals(other.reportedRoute))
+ return false;
+ if (this.requestParameter == null) {
+ if (other.requestParameter != null)
+ return false;
+ } else if (!this.requestParameter.equals(other.requestParameter))
+ return false;
+ if (this.rroBandwidth == null) {
+ if (other.rroBandwidth != null)
+ return false;
+ } else if (!this.rroBandwidth.equals(other.rroBandwidth))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeRequestObject [requestParameter=");
+ builder.append(this.requestParameter);
+ builder.append(", endPoints=");
+ builder.append(this.endPoints);
+ builder.append(", classType=");
+ builder.append(this.classType);
+ builder.append(", lsp=");
+ builder.append(this.lsp);
+ builder.append(", lspa=");
+ builder.append(this.lspa);
+ builder.append(", bandwidth=");
+ builder.append(this.bandwidth);
+ builder.append(", metrics=");
+ builder.append(this.metrics);
+ builder.append(", reportedRoute=");
+ builder.append(this.reportedRoute);
+ builder.append(", rroBandwidth=");
+ builder.append(this.rroBandwidth);
+ builder.append(", includeRoute=");
+ builder.append(this.includeRoute);
+ builder.append(", loadBalancing=");
+ builder.append(this.loadBalancing);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+
+/**
+ * Composite SvecObject used in {@link PCEPRequestMessage}
+ */
+public class CompositeRequestSvecObject {
+
+ private final PCEPSvecObject svec;
+ private final PCEPObjectiveFunctionObject objectiveFunction;
+ private final PCEPGlobalConstraintsObject globalConstraints;
+ private final PCEPExcludeRouteObject excludeRoute;
+ private final List<PCEPMetricObject> metrics;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param svec
+ * PCEPSvecObject
+ */
+ public CompositeRequestSvecObject(PCEPSvecObject svec) {
+ this(svec, null, null, null, null);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param svec
+ * PCEPSvecObject
+ * @param objectiveFunction
+ * PCEPObjectiveFunctionObject
+ * @param globalConstraints
+ * PCEPGlobalConstraints
+ * @param excludeRoute
+ * PCEPExcludeRouteObject
+ * @param metrics
+ * list of PCEPMetricObject
+ */
+ public CompositeRequestSvecObject(PCEPSvecObject svec, PCEPObjectiveFunctionObject objectiveFunction, PCEPGlobalConstraintsObject globalConstraints,
+ PCEPExcludeRouteObject excludeRoute, List<PCEPMetricObject> metrics) {
+ if (svec == null)
+ throw new IllegalArgumentException("Svec object is mandatory.");
+ this.svec = svec;
+ this.objectiveFunction = objectiveFunction;
+ this.globalConstraints = globalConstraints;
+ this.excludeRoute = excludeRoute;
+ if (metrics != null)
+ this.metrics = metrics;
+ else
+ this.metrics = Collections.emptyList();
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>. Can't be null or empty.
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.svec);
+ if (this.objectiveFunction != null)
+ list.add(this.objectiveFunction);
+ if (this.globalConstraints != null)
+ list.add(this.globalConstraints);
+ if (this.excludeRoute != null)
+ list.add(this.excludeRoute);
+ if (this.metrics != null && !this.metrics.isEmpty())
+ list.addAll(this.metrics);
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ *
+ * @param objects
+ * List<PCEPObject> list of PCEPObjects from whose this object
+ * should be created.
+ * @return CompositePathObject
+ */
+ public static CompositeRequestSvecObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+
+ PCEPSvecObject svec = null;
+ if (objects.get(0) instanceof PCEPSvecObject) {
+ svec = (PCEPSvecObject) objects.get(0);
+ objects.remove(svec);
+ } else
+ return null;
+
+ PCEPObjectiveFunctionObject of = null;
+ PCEPGlobalConstraintsObject gc = null;
+ PCEPExcludeRouteObject xro = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPObjectiveFunctionObject) {
+ of = (PCEPObjectiveFunctionObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPGlobalConstraintsObject) {
+ gc = (PCEPGlobalConstraintsObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPExcludeRouteObject) {
+ xro = (PCEPExcludeRouteObject) obj;
+ break;
+ }
+ case 4:
+ state = 5;
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 4;
+
+ break;
+ }
+ }
+
+ if (state == 5)
+ break;
+
+ objects.remove(obj);
+ }
+
+ return new CompositeRequestSvecObject(svec, of, gc, xro, metrics);
+ }
+
+ /**
+ * Gets {@link PCEPSvecObject}
+ *
+ * @return PCEPSvecObject. Can't be null.
+ */
+ public PCEPSvecObject getSvec() {
+ return this.svec;
+ }
+
+ /**
+ * Gets {@link PCEPObjectiveFunctionObject}
+ *
+ * @return PCEPObjectiveFunctionObject. May be null.
+ */
+ public PCEPObjectiveFunctionObject getObjectiveFunction() {
+ return this.objectiveFunction;
+ }
+
+ /**
+ * Gets {@link PCEPGlobalConstraintsObject}
+ *
+ * @return PCEPGlobalConstraints. May be null.
+ */
+ public PCEPGlobalConstraintsObject getGlobalConstraints() {
+ return this.globalConstraints;
+ }
+
+ /**
+ * Gets {@link PCEPExcludeRouteObject}
+ *
+ * @return PCEPExcludeRouteObject. May be null.
+ */
+ public PCEPExcludeRouteObject getExcludeRoute() {
+ return this.excludeRoute;
+ }
+
+ /**
+ * @return the metrics
+ */
+ public List<PCEPMetricObject> getMetrics() {
+ return this.metrics;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeSvecObject [svec=");
+ builder.append(this.svec);
+ builder.append(", objectiveFunction=");
+ builder.append(this.objectiveFunction);
+ builder.append(", globalConstraints=");
+ builder.append(this.globalConstraints);
+ builder.append(", excludeRoute=");
+ builder.append(this.excludeRoute);
+ builder.append(", metrics=");
+ builder.append(this.metrics);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.excludeRoute == null) ? 0 : this.excludeRoute.hashCode());
+ result = prime * result + ((this.globalConstraints == null) ? 0 : this.globalConstraints.hashCode());
+ result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+ result = prime * result + ((this.objectiveFunction == null) ? 0 : this.objectiveFunction.hashCode());
+ result = prime * result + ((this.svec == null) ? 0 : this.svec.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositeRequestSvecObject other = (CompositeRequestSvecObject) obj;
+ if (this.excludeRoute == null) {
+ if (other.excludeRoute != null)
+ return false;
+ } else if (!this.excludeRoute.equals(other.excludeRoute))
+ return false;
+ if (this.globalConstraints == null) {
+ if (other.globalConstraints != null)
+ return false;
+ } else if (!this.globalConstraints.equals(other.globalConstraints))
+ return false;
+ if (this.metrics == null) {
+ if (other.metrics != null)
+ return false;
+ } else if (!this.metrics.equals(other.metrics))
+ return false;
+ if (this.objectiveFunction == null) {
+ if (other.objectiveFunction != null)
+ return false;
+ } else if (!this.objectiveFunction.equals(other.objectiveFunction))
+ return false;
+ if (this.svec == null) {
+ if (other.svec != null)
+ return false;
+ } else if (!this.svec.equals(other.svec))
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-6.5">Path
+ * Computation Reply (PCRep) Message</a> - <response></br>
+ */
+public class CompositeResponseObject {
+
+ private final PCEPRequestParameterObject requestParameter;
+
+ private final PCEPNoPathObject noPath;
+
+ private final PCEPLspObject lsp;
+
+ private final PCEPLspaObject lspa;
+
+ private final PCEPRequestedPathBandwidthObject bandwidth;
+
+ private List<PCEPMetricObject> metrics;
+
+ private final PCEPIncludeRouteObject includeRoute;
+
+ private List<CompositePathObject> paths;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param requestParameter
+ * PCEPRequestParameterObject. Can't be null.
+ */
+ public CompositeResponseObject(PCEPRequestParameterObject requestParameter) {
+ this(requestParameter, null, null, null, null, null, null, null);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param requestParameter
+ * PCEPRequestParameterObject. Can't be null.
+ * @param noPath
+ * PCEPNoPathObject
+ * @param lsp
+ * PCEPLspObject
+ * @param lspa
+ * PCEPLspaObject
+ * @param bandwidth
+ * PCEPRequestedPathBandwidthObject
+ * @param metrics
+ * List<PCEPMetricObject>
+ * @param includeRoute
+ * PCEPIncludeRouteObject
+ * @param paths
+ * List<CompositePathObject>
+ */
+ public CompositeResponseObject(PCEPRequestParameterObject requestParameter, PCEPNoPathObject noPath, PCEPLspObject lsp, PCEPLspaObject lspa,
+ PCEPRequestedPathBandwidthObject bandwidth, List<PCEPMetricObject> metrics, PCEPIncludeRouteObject includeRoute, List<CompositePathObject> paths) {
+ if (requestParameter == null)
+ throw new IllegalArgumentException("Request Parameter Object is mandatory.");
+ this.requestParameter = requestParameter;
+ this.noPath = noPath;
+ this.lsp = lsp;
+ this.lspa = lspa;
+ this.bandwidth = bandwidth;
+ if (metrics != null)
+ this.metrics = metrics;
+ else
+ this.metrics = Collections.emptyList();
+ this.includeRoute = includeRoute;
+ if (paths != null)
+ this.paths = paths;
+ else
+ this.paths = Collections.emptyList();
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.requestParameter);
+ if (this.noPath != null)
+ list.add(this.noPath);
+ if (this.lsp != null)
+ list.add(this.lsp);
+ if (this.lspa != null)
+ list.add(this.lspa);
+ if (this.bandwidth != null)
+ list.add(this.bandwidth);
+ if (this.metrics != null && !this.metrics.isEmpty())
+ list.addAll(this.metrics);
+ if (this.includeRoute != null)
+ list.add(this.includeRoute);
+ if (this.paths != null && !this.paths.isEmpty())
+ for (final CompositePathObject cpo : this.paths)
+ list.addAll(cpo.getCompositeAsList());
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ * @param objects List<PCEPObject> list of PCEPObjects from whose this
+ * object should be created.
+ * @return CompositeResponseObject
+ */
+ public static CompositeResponseObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+ PCEPRequestParameterObject requestParameter = null;
+ if (objects.get(0) instanceof PCEPRequestParameterObject) {
+ requestParameter = (PCEPRequestParameterObject) objects.get(0);
+ objects.remove(requestParameter);
+ } else
+ return null;
+ PCEPNoPathObject noPath = null;
+ PCEPLspObject lsp = null;
+ PCEPLspaObject lspa = null;
+ PCEPRequestedPathBandwidthObject bandwidth = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+ PCEPIncludeRouteObject iro = null;
+ final List<CompositePathObject> paths = new ArrayList<CompositePathObject>();
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPNoPathObject) {
+ noPath = (PCEPNoPathObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPLspObject) {
+ lsp = (PCEPLspObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPLspaObject) {
+ lspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 4:
+ state = 5;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 5:
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 5;
+ break;
+ } else
+ state = 6;
+ case 6:
+ state = 8;
+ if (obj instanceof PCEPIncludeRouteObject) {
+ iro = (PCEPIncludeRouteObject) obj;
+ break;
+ }
+ state = 7;
+ }
+
+ if (state == 7) {
+ break;
+ }
+ objects.remove(obj);
+ if (state == 8) {
+ break;
+ }
+ }
+ if (!objects.isEmpty()) {
+ CompositePathObject path = CompositePathObject.getCompositeFromList(objects);
+ while (path != null) {
+ paths.add(path);
+ if (objects.isEmpty())
+ break;
+ path = CompositePathObject.getCompositeFromList(objects);
+ }
+ }
+ return new CompositeResponseObject(requestParameter, noPath, lsp, lspa, bandwidth, metrics, iro, paths);
+ }
+
+ /**
+ * Gets {@link PCEPRequestParameterObject}.
+ *
+ * @return PCEPRequestParameterObject. Can't be null.
+ */
+ public PCEPRequestParameterObject getRequestParameter() {
+ return this.requestParameter;
+ }
+
+ /**
+ * Gets {@link PCEPNoPathObject}.
+ *
+ * @return PCEPNoPathObject. May be null.
+ */
+ public PCEPNoPathObject getNoPath() {
+ return this.noPath;
+ }
+
+ /**
+ * Gets {@link PCEPLspObject}
+ *
+ * @return PCEPLspObject. May be null.
+ */
+ public PCEPLspObject getLsp() {
+ return this.lsp;
+ }
+
+ /**
+ * Gets {@link PCEPLspaObject}.
+ *
+ * @return PCEPLspaObject. May be null.
+ */
+ public PCEPLspaObject getLspa() {
+ return this.lspa;
+ }
+
+ /**
+ * Gets {@link PCEPBandwidthObject}.
+ *
+ * @return PCEPBandwidthObject. May be null.
+ */
+ public PCEPBandwidthObject getBandwidth() {
+ return this.bandwidth;
+ }
+
+ /**
+ * Gets list of {@link PCEPMetricObject}.
+ *
+ * @return List<PCEPMetricObject>. Can't be null, but may be empty.
+ */
+ public List<PCEPMetricObject> getMetrics() {
+ return this.metrics;
+ }
+
+ /**
+ * Gets list of {@link CompositePathObject}.
+ *
+ * @return PCEPIncludeRouteObject. Can't be null, but may be empty.
+ */
+ public PCEPIncludeRouteObject getIncludeRoute() {
+ return this.includeRoute;
+ }
+
+ /**
+ * Gets list of {@link CompositePathObject}.
+ *
+ * @return List<CompositePathObject>. Can't be null, but may be empty.
+ */
+ public List<CompositePathObject> getPaths() {
+ return this.paths;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+ result = prime * result + ((this.includeRoute == null) ? 0 : this.includeRoute.hashCode());
+ result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+ result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+ result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+ result = prime * result + ((this.noPath == null) ? 0 : this.noPath.hashCode());
+ result = prime * result + ((this.paths == null) ? 0 : this.paths.hashCode());
+ result = prime * result + ((this.requestParameter == null) ? 0 : this.requestParameter.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositeResponseObject other = (CompositeResponseObject) obj;
+ if (this.bandwidth == null) {
+ if (other.bandwidth != null)
+ return false;
+ } else if (!this.bandwidth.equals(other.bandwidth))
+ return false;
+ if (this.includeRoute == null) {
+ if (other.includeRoute != null)
+ return false;
+ } else if (!this.includeRoute.equals(other.includeRoute))
+ return false;
+ if (this.lsp == null) {
+ if (other.lsp != null)
+ return false;
+ } else if (!this.lsp.equals(other.lsp))
+ return false;
+ if (this.lspa == null) {
+ if (other.lspa != null)
+ return false;
+ } else if (!this.lspa.equals(other.lspa))
+ return false;
+ if (this.metrics == null) {
+ if (other.metrics != null)
+ return false;
+ } else if (!this.metrics.equals(other.metrics))
+ return false;
+ if (this.noPath == null) {
+ if (other.noPath != null)
+ return false;
+ } else if (!this.noPath.equals(other.noPath))
+ return false;
+ if (this.paths == null) {
+ if (other.paths != null)
+ return false;
+ } else if (!this.paths.equals(other.paths))
+ return false;
+ if (this.requestParameter == null) {
+ if (other.requestParameter != null)
+ return false;
+ } else if (!this.requestParameter.equals(other.requestParameter))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeResponseObject [requestParameter=");
+ builder.append(this.requestParameter);
+ builder.append(", noPath=");
+ builder.append(this.noPath);
+ builder.append(", lsp=");
+ builder.append(this.lsp);
+ builder.append(", lspa=");
+ builder.append(this.lspa);
+ builder.append(", bandwidth=");
+ builder.append(this.bandwidth);
+ builder.append(", metrics=");
+ builder.append(this.metrics);
+ builder.append(", includeRoute=");
+ builder.append(this.includeRoute);
+ builder.append(", paths=");
+ builder.append(this.paths);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.1">PCRpt
+ * Message</a>
+ */
+public class CompositeRptPathObject {
+ private final PCEPExplicitRouteObject explicitRoute;
+
+ private final PCEPLspaObject lspa;
+
+ private final PCEPExistingPathBandwidthObject bandwidth;
+
+ private final PCEPReportedRouteObject reportedRoute;
+
+ private List<PCEPMetricObject> metrics;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param explicitRoute
+ * PCEPExplicitRouteObject. Can't be null.
+ */
+ public CompositeRptPathObject(final PCEPExplicitRouteObject explicitRoute) {
+ this(explicitRoute, null, null, null, null);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param explicitRoute
+ * PCEPExplicitRouteObject. Can't be null.
+ * @param lspa
+ * PCEPLspaObject
+ * @param bandwidth
+ * PCEPRequestedPathBandwidthObject
+ * @param reportedRoute
+ * PCEPReportedRouteObject
+ * @param metrics
+ * List<PCEPMetricObject>
+ */
+ public CompositeRptPathObject(final PCEPExplicitRouteObject explicitRoute, final PCEPLspaObject lspa, final PCEPExistingPathBandwidthObject bandwidth,
+ final PCEPReportedRouteObject reportedRoute, final List<PCEPMetricObject> metrics) {
+ if (explicitRoute == null)
+ throw new IllegalArgumentException("Explicit Route Object is mandatory.");
+ this.explicitRoute = explicitRoute;
+ this.lspa = lspa;
+ this.bandwidth = bandwidth;
+ if (metrics != null)
+ this.metrics = metrics;
+ else
+ this.metrics = Collections.emptyList();
+ this.reportedRoute = reportedRoute;
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>. Can't be null or empty.
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.explicitRoute);
+ if (this.lspa != null)
+ list.add(this.lspa);
+ if (this.bandwidth != null)
+ list.add(this.bandwidth);
+ if (this.reportedRoute != null)
+ list.add(this.reportedRoute);
+ if (this.metrics != null && !this.metrics.isEmpty())
+ list.addAll(this.metrics);
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ * @param objects List<PCEPObject> list of PCEPObjects from whose this
+ * object should be created.
+ * @return CompositeRptPathObject
+ */
+ public static CompositeRptPathObject getCompositeFromList(final List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+
+ PCEPExplicitRouteObject explicitRoute = null;
+ if (objects.get(0) instanceof PCEPExplicitRouteObject) {
+ explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+ objects.remove(explicitRoute);
+ } else
+ return null;
+
+ PCEPLspaObject lspa = null;
+ PCEPExistingPathBandwidthObject bandwidth = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+ PCEPReportedRouteObject rro = null;
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPLspaObject) {
+ lspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPExistingPathBandwidthObject) {
+ bandwidth = (PCEPExistingPathBandwidthObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPReportedRouteObject) {
+ rro = (PCEPReportedRouteObject) obj;
+ break;
+ }
+ case 4:
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 4;
+ break;
+ } else
+ state = 5;
+ }
+
+ if (state == 5) {
+ break;
+ }
+
+ objects.remove(obj);
+ }
+
+ return new CompositeRptPathObject(explicitRoute, lspa, bandwidth, rro, metrics);
+ }
+
+ /**
+ * Gets {@link PCEPExplicitRouteObject}.
+ *
+ * @return PCEPExplicitRouteObject. Can't be null.
+ */
+ public PCEPExplicitRouteObject getExcludedRoute() {
+ return this.explicitRoute;
+ }
+
+ /**
+ * Gets {@link PCEPLspaObject}.
+ *
+ * @return PCEPLspaObject. May be null.
+ */
+ public PCEPLspaObject getLspa() {
+ return this.lspa;
+ }
+
+ /**
+ * Gets {@link PCEPBandwidthObject}.
+ *
+ * @return PCEPBandwidthObject. May be null.
+ */
+ public PCEPBandwidthObject getBandwidth() {
+ return this.bandwidth;
+ }
+
+ /**
+ * Gets list of {@link PCEPMetricObject}.
+ *
+ * @return List<PCEPMetricObject>. Can't be null, but may be empty.
+ */
+ public List<PCEPMetricObject> getMetrics() {
+ return this.metrics;
+ }
+
+ /**
+ * Gets {@link PCEPReportedRouteObject}.
+ *
+ * @return PCEPReportedRouteObject. May be null.
+ */
+ public PCEPReportedRouteObject getReportedRoute() {
+ return this.reportedRoute;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+ result = prime * result + ((this.explicitRoute == null) ? 0 : this.explicitRoute.hashCode());
+ result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+ result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+ result = prime * result + ((this.reportedRoute == null) ? 0 : this.reportedRoute.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositeRptPathObject other = (CompositeRptPathObject) obj;
+ if (this.bandwidth == null) {
+ if (other.bandwidth != null)
+ return false;
+ } else if (!this.bandwidth.equals(other.bandwidth))
+ return false;
+ if (this.explicitRoute == null) {
+ if (other.explicitRoute != null)
+ return false;
+ } else if (!this.explicitRoute.equals(other.explicitRoute))
+ return false;
+ if (this.lspa == null) {
+ if (other.lspa != null)
+ return false;
+ } else if (!this.lspa.equals(other.lspa))
+ return false;
+ if (this.metrics == null) {
+ if (other.metrics != null)
+ return false;
+ } else if (!this.metrics.equals(other.metrics))
+ return false;
+ if (this.reportedRoute == null) {
+ if (other.reportedRoute != null)
+ return false;
+ } else if (!this.reportedRoute.equals(other.reportedRoute))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeRptPathObject [explicitRoute=");
+ builder.append(this.explicitRoute);
+ builder.append(", lspa=");
+ builder.append(this.lspa);
+ builder.append(", bandwidth=");
+ builder.append(this.bandwidth);
+ builder.append(", reportedRoute=");
+ builder.append(this.reportedRoute);
+ builder.append(", metrics=");
+ builder.append(this.metrics);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.1">The
+ * PCRpt Message</a> - <state-report></br>
+ */
+public class CompositeStateReportObject {
+
+ private final PCEPLspObject lsp;
+
+ private List<CompositeRptPathObject> paths;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param lsp
+ * PCEPLspObject
+ */
+ public CompositeStateReportObject(PCEPLspObject lsp) {
+ this(lsp, null);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param lsp
+ * PCEPLspObject
+ * @param paths
+ * List<CompositeRptPathObject> Can't be null.
+ */
+ public CompositeStateReportObject(PCEPLspObject lsp, List<CompositeRptPathObject> paths) {
+ if (lsp == null)
+ throw new IllegalArgumentException("LSP Object is mandatory.");
+ this.lsp = lsp;
+ if (paths != null)
+ this.paths = paths;
+ else
+ this.paths = Collections.emptyList();
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ * @param objects List<PCEPObject> list of PCEPObjects from whose this
+ * object should be created.
+ * @return CompositeStateReportObject
+ */
+ public static CompositeStateReportObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List can not be null or empty.");
+ }
+
+ PCEPLspObject lsp = null;
+ if (objects.get(0) instanceof PCEPLspObject) {
+ lsp = (PCEPLspObject) objects.get(0);
+ objects.remove(lsp);
+ } else
+ return null;
+
+ final List<CompositeRptPathObject> paths = new ArrayList<CompositeRptPathObject>();
+
+ if (!objects.isEmpty()) {
+ CompositeRptPathObject path = CompositeRptPathObject.getCompositeFromList(objects);
+ while (path != null) {
+ paths.add(path);
+ if (objects.isEmpty())
+ break;
+ path = CompositeRptPathObject.getCompositeFromList(objects);
+ }
+ }
+
+ return new CompositeStateReportObject(lsp, paths);
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.lsp);
+ if (this.paths != null && !this.paths.isEmpty())
+ for (final CompositeRptPathObject cpo : this.paths)
+ list.addAll(cpo.getCompositeAsList());
+ return list;
+ }
+
+ /**
+ * Gets {@link PCEPLspObject}.
+ *
+ * @return PCEPLspObject. Can't be null.
+ */
+ public PCEPLspObject getLsp() {
+ return this.lsp;
+ }
+
+ /**
+ * Gets list of {@link CompositeRptPathObject}.
+ *
+ * @return List<CompositeRptPathObject>. May be null.
+ */
+ public List<CompositeRptPathObject> getPaths() {
+ return this.paths;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+ result = prime * result + ((this.paths == null) ? 0 : this.paths.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositeStateReportObject other = (CompositeStateReportObject) obj;
+ if (this.lsp == null) {
+ if (other.lsp != null)
+ return false;
+ } else if (!this.lsp.equals(other.lsp))
+ return false;
+ if (this.paths == null) {
+ if (other.paths != null)
+ return false;
+ } else if (!this.paths.equals(other.paths))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeStateReportObject [lsp=");
+ builder.append(this.lsp);
+ builder.append(", paths=");
+ builder.append(this.paths);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see draft-ietf-pce-stateful-pce-01 (sec. 6.2) - The PCUpd Message -
+ * <path></br>
+ */
+public class CompositeUpdPathObject {
+
+ private final PCEPExplicitRouteObject explicitRoute;
+
+ private final PCEPLspaObject lspa;
+
+ private final PCEPRequestedPathBandwidthObject bandwidth;
+
+ private List<PCEPMetricObject> metrics;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ * @param explicitRoute PCEPExplicitRouteObject
+ */
+ public CompositeUpdPathObject(PCEPExplicitRouteObject explicitRoute) {
+ this(explicitRoute, null, null, null);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ * @param explicitRoute PCEPExplicitRouteObject
+ * @param lspa PCEPLspaObject
+ * @param bandwidth PCEPRequestedPathBandwidthObject
+ * @param metrics List<PCEPMetricObject>
+ */
+ public CompositeUpdPathObject(PCEPExplicitRouteObject explicitRoute, PCEPLspaObject lspa, PCEPRequestedPathBandwidthObject bandwidth,
+ List<PCEPMetricObject> metrics) {
+ if (explicitRoute == null)
+ throw new IllegalArgumentException("Explicit Route Object is mandatory.");
+ this.explicitRoute = explicitRoute;
+ this.lspa = lspa;
+ this.bandwidth = bandwidth;
+ if (metrics != null)
+ this.metrics = metrics;
+ else
+ this.metrics = Collections.emptyList();
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ * @return List<PCEPObject>
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.explicitRoute);
+ if (this.lspa != null)
+ list.add(this.lspa);
+ if (this.bandwidth != null)
+ list.add(this.bandwidth);
+ if (this.metrics != null && !this.metrics.isEmpty())
+ list.addAll(this.metrics);
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ * @param objects List<PCEPObject> list of PCEPObjects from whose this
+ * object should be created.
+ * @return CompositeUpdPathObject constructed from objects
+ */
+ public static CompositeUpdPathObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+
+ PCEPExplicitRouteObject explicitRoute = null;
+ if (objects.get(0) instanceof PCEPExplicitRouteObject) {
+ explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+ objects.remove(explicitRoute);
+ } else
+ return null;
+
+ PCEPLspaObject lspa = null;
+ PCEPRequestedPathBandwidthObject bandwidth = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPLspaObject) {
+ lspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 3:
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 3;
+ break;
+ } else
+ state = 4;
+ }
+
+ if (state == 4) {
+ break;
+ }
+
+ objects.remove(obj);
+ }
+
+ return new CompositeUpdPathObject(explicitRoute, lspa, bandwidth, metrics);
+ }
+
+ /**
+ * Gets {@link PCEPExplicitRouteObject}
+ *
+ * @return PCEPExplicitRouteObject
+ */
+ public PCEPExplicitRouteObject getExcludedRoute() {
+ return this.explicitRoute;
+ }
+
+ /**
+ * Gets {@link PCEPLspaObject}
+ *
+ * @return PCEPLspaObject
+ */
+ public PCEPLspaObject getLspa() {
+ return this.lspa;
+ }
+
+ /**
+ * Gets bandwidth.
+ *
+ * @return PCEPBandwidthObject
+ */
+ public PCEPBandwidthObject getBandwidth() {
+ return this.bandwidth;
+ }
+
+ /**
+ * Gets list of {@link PCEPMetricObject}.
+ *
+ * @return List<PCEPMetricObject>
+ */
+ public List<PCEPMetricObject> getMetrics() {
+ return this.metrics;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+ result = prime * result + ((this.explicitRoute == null) ? 0 : this.explicitRoute.hashCode());
+ result = prime * result + ((this.lspa == null) ? 0 : this.lspa.hashCode());
+ result = prime * result + ((this.metrics == null) ? 0 : this.metrics.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositeUpdPathObject other = (CompositeUpdPathObject) obj;
+ if (this.bandwidth == null) {
+ if (other.bandwidth != null)
+ return false;
+ } else if (!this.bandwidth.equals(other.bandwidth))
+ return false;
+ if (this.explicitRoute == null) {
+ if (other.explicitRoute != null)
+ return false;
+ } else if (!this.explicitRoute.equals(other.explicitRoute))
+ return false;
+ if (this.lspa == null) {
+ if (other.lspa != null)
+ return false;
+ } else if (!this.lspa.equals(other.lspa))
+ return false;
+ if (this.metrics == null) {
+ if (other.metrics != null)
+ return false;
+ } else if (!this.metrics.equals(other.metrics))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeUpdPathObject [explicitRoute=");
+ builder.append(this.explicitRoute);
+ builder.append(", lspa=");
+ builder.append(this.lspa);
+ builder.append(", bandwidth=");
+ builder.append(this.bandwidth);
+ builder.append(", metrics=");
+ builder.append(this.metrics);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Structure that combines set of related objects.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-6.2">The
+ * PCRpt Message</a> - <update-request></br>
+ */
+public class CompositeUpdateRequestObject {
+
+ private final PCEPLspObject lsp;
+
+ private List<CompositeUpdPathObject> paths;
+
+ /**
+ * Constructs basic composite object only with mandatory objects.
+ *
+ * @param lsp
+ * PCEPLspObject. Can't be null.
+ */
+ public CompositeUpdateRequestObject(PCEPLspObject lsp) {
+ this(lsp, null);
+ }
+
+ /**
+ * Constructs composite object with optional objects.
+ *
+ * @param lsp
+ * PCEPLspObject. Can't be null.
+ * @param paths
+ * List<CompositeUpdPathObject>
+ */
+ public CompositeUpdateRequestObject(PCEPLspObject lsp, List<CompositeUpdPathObject> paths) {
+ if (lsp == null)
+ throw new IllegalArgumentException("LSP Object is mandatory.");
+ this.lsp = lsp;
+ if (paths != null)
+ this.paths = paths;
+ else
+ this.paths = Collections.emptyList();
+ }
+
+ /**
+ * Gets list of all objects, which are in appropriate order.
+ *
+ * @return List<PCEPObject>. Can't be null.
+ */
+ public List<PCEPObject> getCompositeAsList() {
+ final List<PCEPObject> list = new ArrayList<PCEPObject>();
+ list.add(this.lsp);
+ if (this.paths != null && !this.paths.isEmpty())
+ for (final CompositeUpdPathObject cpo : this.paths)
+ list.addAll(cpo.getCompositeAsList());
+ return list;
+ }
+
+ /**
+ * Creates this object from a list of PCEPObjects.
+ * @param objects List<PCEPObject> list of PCEPObjects from whose this
+ * object should be created.
+ * @return CompositeUpdateRequestObject
+ */
+ public static CompositeUpdateRequestObject getCompositeFromList(List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+
+ PCEPLspObject lsp = null;
+ if (objects.get(0) instanceof PCEPLspObject) {
+ lsp = (PCEPLspObject) objects.get(0);
+ objects.remove(lsp);
+ } else
+ return null;
+
+ final List<CompositeUpdPathObject> paths = new ArrayList<CompositeUpdPathObject>();
+
+ if (!objects.isEmpty()) {
+ CompositeUpdPathObject path = CompositeUpdPathObject.getCompositeFromList(objects);
+ while (path != null) {
+ paths.add(path);
+ if (objects.isEmpty())
+ break;
+ path = CompositeUpdPathObject.getCompositeFromList(objects);
+ }
+ }
+
+ return new CompositeUpdateRequestObject(lsp, paths);
+ }
+
+ /**
+ * Gets {@link PCEPLspObject}.
+ *
+ * @return PCEPLspObject. Can't be null.
+ */
+ public PCEPLspObject getLsp() {
+ return this.lsp;
+ }
+
+ /**
+ * Gets list of {@link CompositeUpdPathObject}.
+ *
+ * @return List<CompositeUpdPathObject>. Can't be null, but may be empty.
+ */
+ public List<CompositeUpdPathObject> getPaths() {
+ return this.paths;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.lsp == null) ? 0 : this.lsp.hashCode());
+ result = prime * result + ((this.paths == null) ? 0 : this.paths.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final CompositeUpdateRequestObject other = (CompositeUpdateRequestObject) obj;
+ if (this.lsp == null) {
+ if (other.lsp != null)
+ return false;
+ } else if (!this.lsp.equals(other.lsp))
+ return false;
+ if (this.paths == null) {
+ if (other.paths != null)
+ return false;
+ } else if (!this.paths.equals(other.paths))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("CompositeUpdateRequestObject [lsp=");
+ builder.append(this.lsp);
+ builder.append(", paths=");
+ builder.append(this.paths);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Basic structure of Bandwidth Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.7">PCEP Bandwidth
+ * Object</a>
+ */
+public abstract class PCEPBandwidthObject extends PCEPObject {
+
+ private final Bandwidth bandwidth;
+
+ /**
+ * Constructs basic Bandwidth Object.
+ *
+ * @param bandwidth
+ * Bandwidth
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPBandwidthObject(Bandwidth bandwidth, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ if (bandwidth == null)
+ this.bandwidth = new Bandwidth(0f);
+ else
+ this.bandwidth = bandwidth;
+ }
+
+ /**
+ * Gets {@link PCEPBandwidthObject}.
+ *
+ * @return Bandwidth. Can't be null.
+ */
+ public Bandwidth getBandwidth() {
+ return this.bandwidth;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.bandwidth == null) ? 0 : this.bandwidth.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPBandwidthObject other = (PCEPBandwidthObject) obj;
+ if (this.bandwidth == null) {
+ if (other.bandwidth != null)
+ return false;
+ } else if (!this.bandwidth.equals(other.bandwidth))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("bandwidth", this.bandwidth);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Structure of Branch Node list object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.11.1">Branch Node
+ * Object [RFC6006]</a>
+ */
+public class PCEPBranchNodeListObject extends PCEPBranchNodeObject {
+
+ /**
+ * Constructs Branch Node list object.
+ *
+ * @param subobjects
+ * List<ExplicitRouteSubobject>
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPBranchNodeListObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+ super(subobjects, processed, ignored);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ *
+ */
+public abstract class PCEPBranchNodeObject extends PCEPObject {
+
+ protected final List<ExplicitRouteSubobject> subobjects;
+
+ /**
+ * Constructs Branch Node list object.
+ *
+ * @param subobjects
+ * List<PCEPSubobject>
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPBranchNodeObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ if (subobjects == null || subobjects.isEmpty())
+ throw new IllegalArgumentException("Subobjects can't be null or empty.");
+ this.subobjects = subobjects;
+ }
+
+ /**
+ * Gets list of {@link ExplicitRouteSubobject}
+ *
+ * @return List<ExplicitRouteSubobject>. Can't be null or empty.
+ */
+ public List<ExplicitRouteSubobject> getSubobjects() {
+ return this.subobjects;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPBranchNodeObject other = (PCEPBranchNodeObject) obj;
+ if (this.subobjects == null) {
+ if (other.subobjects != null)
+ return false;
+ } else if (!this.subobjects.equals(other.subobjects))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("subobjects", this.subobjects);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of ClassType Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5455#section-5"> Object
+ * Definition</a>
+ */
+public class PCEPClassTypeObject extends PCEPObject {
+
+ private final short classType;
+
+ /**
+ * Constructs ClassType Object with given class type.
+ *
+ * @param classType
+ * short, must be positive and less than 8.
+ */
+ public PCEPClassTypeObject(short classType) {
+ super(true, false);
+ if (classType < 0 || classType > 7) {
+ throw new IllegalArgumentException("ClassType range overstepped.");
+ }
+ this.classType = classType;
+ }
+
+ /**
+ * Gets class type.
+ *
+ * @return class type
+ */
+ public short getClassType() {
+ return this.classType;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + this.classType;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (!(obj instanceof PCEPClassTypeObject))
+ return false;
+ final PCEPClassTypeObject other = (PCEPClassTypeObject) obj;
+ if (this.classType != other.classType)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("classType", this.classType);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Close Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.17">PCEP Close
+ * Object</a>
+ */
+public class PCEPCloseObject extends PCEPObject {
+
+ /**
+ * Constants for reasons of closing session.
+ */
+ public enum Reason {
+ UNKNOWN, EXP_DEADTIMER, MALFORMED_MSG, TOO_MANY_UNKNOWN_REQ_REP, TOO_MANY_UNKNOWN_MSG
+ }
+
+ private final Reason reason;
+
+ private List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs Close Object only with mandatory object.
+ *
+ * @param reason
+ * Reason. Can't be null.
+ */
+ public PCEPCloseObject(Reason reason) {
+ this(reason, null);
+ }
+
+ /**
+ * Constructs Close Object also with optional objects.
+ *
+ * @param reason
+ * Reason. Can't be null.
+ * @param tlvs
+ * List<PCEPTlv>
+ */
+ public PCEPCloseObject(Reason reason, List<PCEPTlv> tlvs) {
+ super(false, false);
+ if (reason == null)
+ throw new IllegalArgumentException("Reason is mandatory.");
+ this.reason = reason;
+
+ if (tlvs != null)
+ this.tlvs = tlvs;
+ else
+ this.tlvs = Collections.emptyList();
+ }
+
+ /**
+ * Gets {@link Reason}
+ *
+ * @return Reason. Can't be null.
+ */
+ public Reason getReason() {
+ return this.reason;
+ }
+
+ /**
+ * Gets list of {@link PCEPTlv}
+ *
+ * @return List<PCEPTlv>. Can't be null, but may be empty.
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.reason == null) ? 0 : this.reason.hashCode());
+ result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPCloseObject other = (PCEPCloseObject) obj;
+ if (this.reason != other.reason)
+ return false;
+ if (this.tlvs == null) {
+ if (other.tlvs != null)
+ return false;
+ } else if (!this.tlvs.equals(other.tlvs))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("reason", this.reason);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+public abstract class PCEPEndPoints extends PCEPObject {
+
+ protected PCEPEndPoints(boolean processed, boolean ignored) {
+ super(processed, ignored);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Parameterized structure of PCEP End Points Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.6">PCEP
+ * EndPointsObject</a>
+ * @param <T>
+ * subtype of NetworkAddress
+ */
+public class PCEPEndPointsObject<T extends NetworkAddress<T>> extends PCEPEndPoints {
+
+ private final T sourceAddress;
+
+ private final T destinationAddress;
+
+ /**
+ * Constructs Close Object with mandatory object.
+ *
+ * @param sourceAddress
+ * T. Cant't be null.
+ * @param destinationAddress
+ * T. Cant't be null.
+ */
+ public PCEPEndPointsObject(T sourceAddress, T destinationAddress) {
+ super(true, false);
+ if (sourceAddress == null)
+ throw new IllegalArgumentException("Source address is mantadory.");
+ this.sourceAddress = sourceAddress;
+ if (destinationAddress == null)
+ throw new IllegalArgumentException("Destination address is mantadory.");
+ this.destinationAddress = destinationAddress;
+ }
+
+ /**
+ * Gets source address of type T.
+ *
+ * @return T. Can't be null.
+ */
+ public T getSourceAddress() {
+ return this.sourceAddress;
+ }
+
+ /**
+ * Gets destination address of type T.
+ *
+ * @return T. Can't be null.
+ */
+ public T getDestinationAddress() {
+ return this.destinationAddress;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("sourceAddress", this.sourceAddress);
+ toStringHelper.add("destinationAddress", this.destinationAddress);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.destinationAddress == null) ? 0 : this.destinationAddress.hashCode());
+ result = prime * result + ((this.sourceAddress == null) ? 0 : this.sourceAddress.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (!(obj instanceof PCEPEndPointsObject))
+ return false;
+ final PCEPEndPointsObject<?> other = (PCEPEndPointsObject<?>) obj;
+ if (this.destinationAddress == null) {
+ if (other.destinationAddress != null)
+ return false;
+ } else if (!this.destinationAddress.equals(other.destinationAddress))
+ return false;
+ if (this.sourceAddress == null) {
+ if (other.sourceAddress != null)
+ return false;
+ } else if (!this.sourceAddress.equals(other.sourceAddress))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Error Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.15">PCEP Error
+ * Object</a>
+ */
+public class PCEPErrorObject extends PCEPObject {
+
+ private final PCEPErrors error;
+
+ private final List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs Error Object only with mandatory object.
+ *
+ * @param type
+ * PCEPErrors. Can't be null.
+ */
+ public PCEPErrorObject(PCEPErrors type) {
+ this(type, null);
+ }
+
+ /**
+ * Constructs Error Object also with optional objects.
+ *
+ * @param type
+ * PCEPErrors. Can't be null
+ * @param tlvs
+ * List<PCEPTlv>
+ */
+ public PCEPErrorObject(PCEPErrors type, List<PCEPTlv> tlvs) {
+ super(false, false);
+ this.error = type;
+ if (tlvs != null)
+ this.tlvs = tlvs;
+ else
+ this.tlvs = Collections.emptyList();
+ }
+
+ /**
+ * Gets {@link PCEPErrors}
+ *
+ * @return PCEPErrors. Can't be null.
+ */
+ public PCEPErrors getError() {
+ return this.error;
+ }
+
+ /**
+ * Gets list of {@link PCEPTlv}
+ *
+ * @return List<PCEPTlv>. Can't be null, but may be empty.
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.error == null) ? 0 : this.error.hashCode());
+ result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPErrorObject other = (PCEPErrorObject) obj;
+ if (this.error != other.error)
+ return false;
+ if (this.tlvs == null) {
+ if (other.tlvs != null)
+ return false;
+ } else if (!this.tlvs.equals(other.tlvs))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("error", this.error);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Provides a list of network resources that the PCE is requested to exclude
+ * from the path that it computes. Flags associated with each list member
+ * instruct the PCE as to whether the network resources must be excluded from
+ * the computed path, or whether the PCE should make best efforts to exclude the
+ * resources from the computed path.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1"> Exclude
+ * Route Object definition</a>
+ */
+public class PCEPExcludeRouteObject extends PCEPObject {
+
+ private final boolean fail;
+
+ private final List<ExcludeRouteSubobject> subobjects;
+
+ /**
+ * Constructs Exclude Route Object.
+ *
+ * @param subobjects
+ * List<PCEPXROSubobject>. Can't be null or empty.
+ * @param fail
+ * boolean
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPExcludeRouteObject(List<ExcludeRouteSubobject> subobjects, boolean fail, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ if (subobjects == null || subobjects.isEmpty())
+ throw new IllegalArgumentException("Subobjects can't be null or empty.");
+
+ this.fail = fail;
+ this.subobjects = subobjects;
+ }
+
+ /**
+ * Gets list of sub-objects
+ *
+ * @return List<PCEPXROSubobject>. Can't be null or empty.
+ */
+ public List<ExcludeRouteSubobject> getSubobjects() {
+ return this.subobjects;
+ }
+
+ /**
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1"> Exclude
+ * Route Object definition</a>
+ *
+ * @return if returns true, the requesting PCC requires the computation of a
+ * new path for an existing TE LSP that has failed
+ */
+ public boolean isFail() {
+ return this.fail;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("fail", this.fail);
+ toStringHelper.add("subobjects", this.subobjects);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPExcludeRouteObject other = (PCEPExcludeRouteObject) obj;
+ if (this.subobjects == null) {
+ if (other.subobjects != null)
+ return false;
+ } else if (!this.subobjects.equals(other.subobjects))
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+
+/**
+ * Structure of specific Bandwidth. Used in Composite Requested Object to refer
+ * to bandwidth of existing path.
+ */
+public class PCEPExistingPathBandwidthObject extends PCEPBandwidthObject {
+
+ /**
+ * Constructs Existing Path Bandwidth.
+ *
+ * @param bandwidth
+ * Bandwidth. Can't be null.
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPExistingPathBandwidthObject(Bandwidth bandwidth, boolean processed, boolean ignored) {
+ super(bandwidth, processed, ignored);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Explicit Route Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.9">PCEP Explicit
+ * Route Object</a>
+ */
+public class PCEPExplicitRouteObject extends PCEPObject {
+
+ private final List<ExplicitRouteSubobject> subobjects;
+
+ /**
+ * Constructs Explicit Route Object.
+ *
+ * @param subobjects
+ * List<ExplicitRouteSubobject>. Can't be null or empty.
+ * @param ignored
+ * boolean
+ */
+ public PCEPExplicitRouteObject(List<ExplicitRouteSubobject> subobjects, boolean ignored) {
+ super(false, ignored);
+ if (subobjects == null || subobjects.isEmpty())
+ throw new IllegalArgumentException("Subobjects can't be null or empty.");
+ this.subobjects = subobjects;
+ }
+
+ /**
+ * Gets list of {@link ExplicitRouteSubobject}
+ *
+ * @return List<ExplicitRouteSubobject>. Can't be null or empty.
+ */
+ public List<ExplicitRouteSubobject> getSubobjects() {
+ return this.subobjects;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("subobjects", this.subobjects);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPExplicitRouteObject other = (PCEPExplicitRouteObject) obj;
+ if (this.subobjects == null) {
+ if (other.subobjects != null)
+ return false;
+ } else if (!this.subobjects.equals(other.subobjects))
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * The GLOBAL CONSTRAINTS Object is used in a PCReq message to specify the
+ * necessary global constraints that should be applied to all individual path
+ * computations for a global concurrent path optimization request.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5557#section-5.5">GLOBAL
+ * CONSTRAINTS (GC) Object</a>
+ */
+public class PCEPGlobalConstraintsObject extends PCEPObject {
+
+ private final short maxHop;
+ private final short maxUtilization;
+ private final short minUtilization;
+ private final short overBookingFactor;
+
+ private List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs Global Constraints Object with all mandatory fields.
+ *
+ * @param maxhop
+ * 8-bit integer
+ * @param maxUtilization
+ * 8-bit integer between 0 and 100
+ * @param minUtilization
+ * 8-bit integer between 0 and 100
+ * @param overBookingFactor
+ * 8-bit integer
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPGlobalConstraintsObject(short maxhop, short maxUtilization, short minUtilization, short overBookingFactor, boolean processed, boolean ignored) {
+ this(maxhop, maxUtilization, minUtilization, overBookingFactor, null, processed, ignored);
+ }
+
+ /**
+ * Constructs Global Constraints Object with all mandatory fields and
+ * optional list of tlvs.
+ *
+ * @param maxhop
+ * 8-bit integer
+ * @param maxUtilization
+ * 8-bit integer between 0 and 100
+ * @param minUtilization
+ * 8-bit integer between 0 and 100
+ * @param overBookingFactor
+ * 8-bit integer
+ * @param tlvs
+ * list of tlvs
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPGlobalConstraintsObject(short maxhop, short maxUtilization, short minUtilization, short overBookingFactor, List<PCEPTlv> tlvs,
+ boolean processed, boolean ignored) {
+ super(processed, ignored);
+ this.maxHop = maxhop;
+
+ if (maxUtilization < 0 || maxUtilization > 100)
+ throw new IllegalArgumentException("Maximu utilization can be only between 0 and 100. Passed: " + maxUtilization);
+ this.maxUtilization = maxUtilization;
+
+ if (minUtilization < 0 || minUtilization > 100)
+ throw new IllegalArgumentException("Minimum utilization can be only between 0 and 100. Passed: " + minUtilization);
+ this.minUtilization = minUtilization;
+
+ this.overBookingFactor = overBookingFactor;
+
+ if (tlvs == null)
+ this.tlvs = Collections.emptyList();
+ else
+ this.tlvs = tlvs;
+ }
+
+ /**
+ * Gets the maximum hop count for all the TE LSPs
+ *
+ * @return the maximum hop count
+ */
+ public short getMaxHop() {
+ return this.maxHop;
+ }
+
+ /**
+ * Gets the maximum utilization percentage by which all links should be
+ * bound
+ *
+ * @return the maximum utilization percentage
+ */
+ public short getMaxUtilization() {
+ return this.maxUtilization;
+ }
+
+ /**
+ * Gets the minimum utilization percentage by which all links should be
+ * bound
+ *
+ * @return the maximum utilization percentage
+ */
+ public short getMinUtilization() {
+ return this.minUtilization;
+ }
+
+ /**
+ * Gets the over booking factor percentage that allows the reserved
+ * bandwidth to be overbooked on each link beyond its physical capacity
+ * limit
+ *
+ * @return the over booking factor percentage
+ */
+ public short getOverBookingFactor() {
+ return this.overBookingFactor;
+ }
+
+ /**
+ * Gets the list of optional tlvs
+ *
+ * @return List<PCEPTlv>. Can be empty but not null.
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("maxHop", this.maxHop);
+ toStringHelper.add("maxUtilization", this.maxUtilization);
+ toStringHelper.add("minUtilization", this.minUtilization);
+ toStringHelper.add("overBookingFactor", this.overBookingFactor);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + this.maxHop;
+ result = prime * result + this.maxUtilization;
+ result = prime * result + this.minUtilization;
+ result = prime * result + this.overBookingFactor;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPGlobalConstraintsObject other = (PCEPGlobalConstraintsObject) obj;
+ if (this.maxHop != other.maxHop)
+ return false;
+ if (this.maxUtilization != other.maxUtilization)
+ return false;
+ if (this.minUtilization != other.minUtilization)
+ return false;
+ if (this.overBookingFactor != other.overBookingFactor)
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Explicit Route Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.12">PCEP Include
+ * Route Object</a>
+ */
+public class PCEPIncludeRouteObject extends PCEPObject {
+
+ private final List<ExplicitRouteSubobject> subobjects;
+
+ /**
+ * Constructs Include Route Object.
+ *
+ * @param subobjects
+ * List<ExplicitRouteSubobject>
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPIncludeRouteObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ if (subobjects == null || subobjects.isEmpty())
+ throw new IllegalArgumentException("Subobjects can't be null or empty.");
+ this.subobjects = subobjects;
+ }
+
+ /**
+ * Gets list of {@link ExplicitRouteSubobject}
+ *
+ * @return List<ExplicitRouteSubobject>. Can't be null or empty.
+ */
+ public List<ExplicitRouteSubobject> getSubobjects() {
+ return this.subobjects;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPIncludeRouteObject other = (PCEPIncludeRouteObject) obj;
+ if (this.subobjects == null) {
+ if (other.subobjects != null)
+ return false;
+ } else if (!this.subobjects.equals(other.subobjects))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("subobjects", this.subobjects);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure for PCEP Load Balancing Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.16">PCEP Load
+ * Balancing Object</a>
+ */
+public class PCEPLoadBalancingObject extends PCEPObject {
+
+ private final int maxLSP;
+
+ private final Bandwidth minBandwidth;
+
+ /**
+ * Constructs Load Balancing Object.
+ *
+ * @param maxLSP
+ * int
+ * @param minBandwidth
+ * Bandwidth
+ * @param processed
+ * boolean
+ */
+ public PCEPLoadBalancingObject(int maxLSP, Bandwidth minBandwidth, boolean processed) {
+ super(processed, false);
+ this.maxLSP = maxLSP;
+ this.minBandwidth = minBandwidth;
+ }
+
+ /**
+ * Gets Maximum LSP.
+ *
+ * @return int
+ */
+ public int getMaxLSP() {
+ return this.maxLSP;
+ }
+
+ /**
+ * Gets Minimal bandwidth.
+ *
+ * @return Bandwidth
+ */
+ public Bandwidth getMinBandwidth() {
+ return this.minBandwidth;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + this.maxLSP;
+ result = prime * result + ((this.minBandwidth == null) ? 0 : this.minBandwidth.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPLoadBalancingObject other = (PCEPLoadBalancingObject) obj;
+ if (this.maxLSP != other.maxLSP)
+ return false;
+ if (this.minBandwidth == null) {
+ if (other.minBandwidth != null)
+ return false;
+ } else if (!this.minBandwidth.equals(other.minBandwidth))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("maxLSP", this.maxLSP);
+ toStringHelper.add("minBandwidth", this.minBandwidth);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP LSP Object.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-8.3">PCEP
+ * LSP Object</a>
+ */
+public class PCEPLspObject extends PCEPObject {
+
+ private final int lspID;
+
+ private final boolean delegate;
+
+ private final boolean sync;
+
+ private final boolean operational;
+
+ private final boolean remove;
+
+ private final List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs PCEP LSP Object only with mandatory values.
+ *
+ * @param lspID
+ * int
+ * @param delegate
+ * boolean
+ * @param sync
+ * boolean
+ * @param operational
+ * boolean
+ * @param remove
+ * boolean
+ */
+ public PCEPLspObject(int lspID, boolean delegate, boolean sync, boolean operational, boolean remove) {
+ this(lspID, delegate, sync, operational, remove, null);
+ }
+
+ /**
+ * Constructs PCEP LSP Object also with optional Objects.
+ *
+ * @param lspID
+ * int
+ * @param delegate
+ * boolean
+ * @param sync
+ * boolean
+ * @param operational
+ * boolean
+ * @param remove
+ * boolean
+ * @param tlvs
+ * List<PCEPTlv>
+ */
+ public PCEPLspObject(int lspID, boolean delegate, boolean sync, boolean operational, boolean remove, List<PCEPTlv> tlvs) {
+ super(false, false);
+ this.lspID = lspID;
+ this.delegate = delegate;
+ this.sync = sync;
+ this.operational = operational;
+ this.remove = remove;
+ if (tlvs != null)
+ this.tlvs = tlvs;
+ else
+ this.tlvs = Collections.emptyList();
+ }
+
+ /**
+ * Gets integer representation of LSP ID.
+ *
+ * @return int
+ */
+ public int getLspID() {
+ return this.lspID;
+ }
+
+ /**
+ * Gets Delegate flag.
+ *
+ * @return boolean
+ */
+ public boolean isDelegate() {
+ return this.delegate;
+ }
+
+ /**
+ * Gets Sync flag.
+ *
+ * @return boolean
+ */
+ public boolean isSync() {
+ return this.sync;
+ }
+
+ /**
+ * Gets Operational flag.
+ *
+ * @return boolean
+ */
+ public boolean isOperational() {
+ return this.operational;
+ }
+
+ /**
+ * Gets Remove flag.
+ *
+ * @return boolean
+ */
+ public boolean isRemove() {
+ return this.remove;
+ }
+
+ /**
+ * Gets list of {@link PCEPTlv}
+ *
+ * @return List<PCEPTlv>. Can't be null, but may be empty.
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (this.delegate ? 1231 : 1237);
+ result = prime * result + this.lspID;
+ result = prime * result + (this.operational ? 1231 : 1237);
+ result = prime * result + (this.remove ? 1231 : 1237);
+ result = prime * result + (this.sync ? 1231 : 1237);
+ result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPLspObject other = (PCEPLspObject) obj;
+ if (this.delegate != other.delegate)
+ return false;
+ if (this.lspID != other.lspID)
+ return false;
+ if (this.operational != other.operational)
+ return false;
+ if (this.remove != other.remove)
+ return false;
+ if (this.sync != other.sync)
+ return false;
+ if (this.tlvs == null) {
+ if (other.tlvs != null)
+ return false;
+ } else if (!this.tlvs.equals(other.tlvs))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("lspID", this.lspID);
+ toStringHelper.add("delegate", this.delegate);
+ toStringHelper.add("sync", this.sync);
+ toStringHelper.add("operational", this.operational);
+ toStringHelper.add("remove", this.remove);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure for PCEP LSPA Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.11">PCEP LSPA
+ * Object</a>
+ * @see <a
+ * href="http://tools.ietf.org/html/rfc3209#section-4.7">SessionAttribute
+ * Object</a>
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-protection-00#section-4.1">
+ * The Standby flag in the LSPA object</a>
+ */
+public class PCEPLspaObject extends PCEPObject {
+
+ private final long excludedAny;
+
+ private final long includeAny;
+
+ private final long includeAll;
+
+ private final short setupPriority;
+
+ private final short holdingPriority;
+
+ private final boolean standByPath;
+
+ private final boolean localProtected;
+
+ private final List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs object only with mandatory objects.
+ *
+ * @param excludedAny
+ * long
+ * @param includeAny
+ * long
+ * @param includeAll
+ * long
+ * @param setupPriority
+ * short
+ * @param holdingPriority
+ * short
+ * @param standByPath
+ * boolean
+ * @param localProtected
+ * boolean
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPLspaObject(long excludedAny, long includeAny, long includeAll, short setupPriority, short holdingPriority, boolean standByPath,
+ boolean localProtected, boolean processed, boolean ignored) {
+ this(excludedAny, includeAny, includeAll, setupPriority, holdingPriority, standByPath, localProtected, null, processed, ignored);
+ }
+
+ /**
+ * Constructs object also with optional objects.
+ *
+ * @param excludedAny
+ * long
+ * @param includeAny
+ * long
+ * @param includeAll
+ * long
+ * @param setupPriority
+ * short
+ * @param holdingPriority
+ * short
+ * @param localProtected
+ * boolean
+ * @param tlvs
+ * List<PCEPTlv>
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPLspaObject(long excludedAny, long includeAny, long includeAll, short setupPriority, short holdingPriority, boolean standByPath,
+ boolean localProtected, List<PCEPTlv> tlvs, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ this.excludedAny = excludedAny;
+ this.includeAny = includeAny;
+ this.includeAll = includeAll;
+ this.setupPriority = setupPriority;
+ this.holdingPriority = holdingPriority;
+ this.standByPath = standByPath;
+ this.localProtected = localProtected;
+ if (tlvs != null)
+ this.tlvs = tlvs;
+ else
+ this.tlvs = Collections.emptyList();
+ }
+
+ /**
+ * A 32-bit vector representing a set of attribute filters associated with a
+ * tunnel any of which renders a link unacceptable.
+ *
+ * @return long
+ */
+ public long getExcludeAny() {
+ return this.excludedAny;
+ }
+
+ /**
+ * A 32-bit vector representing a set of attribute filters associated with a
+ * tunnel any of which renders a link acceptable (with respect to this
+ * test). A null set (all bits set to zero) automatically passes.
+ *
+ * @return long
+ */
+ public long getIncludeAny() {
+ return this.includeAny;
+ }
+
+ /**
+ * A 32-bit vector representing a set of attribute filters associated with a
+ * tunnel all of which must be present for a link to be acceptable (with
+ * respect to this test). A null set (all bits set to zero) automatically
+ * passes.
+ *
+ * @return long
+ */
+ public long getIncludeAll() {
+ return this.includeAll;
+ }
+
+ /**
+ * The priority of TE LSP with respect to taking resources, in the range of
+ * 0 to 7 (validation not included). The value 0 is the highest priority.
+ * The Setup Priority is used in deciding whether this session can preempt
+ * another session.
+ *
+ * @return short
+ */
+ public short getSetupPriority() {
+ return this.setupPriority;
+ }
+
+ /**
+ * The priority of TE LSP with respect to holding resources, in the range of
+ * 0 to 7 (validation not included). The value 0 is the highest priority.
+ * Holding Priority is used in deciding whether this session can be
+ * preempted by another session.
+ *
+ * @return short
+ */
+ public short getHoldingPriority() {
+ return this.holdingPriority;
+ }
+
+ /**
+ * Corresponds to the "Local Protection Desired" bit ([RFC3209]) of
+ * SESSION-ATTRIBUTE Object. When set, this means that the computed path
+ * must include links protected with Fast REroute as defined in [RFC4090].
+ *
+ * @return boolean
+ */
+ public boolean isLocalProtected() {
+ return this.localProtected;
+ }
+
+ /**
+ * The protection path setup regimen (standby or not) is specified in the
+ * path using a new per-path flag in the LSPA object, the S (standby) flag
+ *
+ * @return boolean
+ */
+ public boolean isStandByPath() {
+ return this.standByPath;
+ }
+
+ /**
+ * Gets list of {@link PCEPTlv}
+ *
+ * @return List<PCEPTlv>. Can't be null, but may be empty.
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (int) (this.excludedAny ^ (this.excludedAny >>> 32));
+ result = prime * result + this.holdingPriority;
+ result = prime * result + (int) (this.includeAll ^ (this.includeAll >>> 32));
+ result = prime * result + (int) (this.includeAny ^ (this.includeAny >>> 32));
+ result = prime * result + (this.localProtected ? 1231 : 1237);
+ result = prime * result + this.setupPriority;
+ result = prime * result + (this.standByPath ? 1231 : 1237);
+ result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (!(obj instanceof PCEPLspaObject))
+ return false;
+ final PCEPLspaObject other = (PCEPLspaObject) obj;
+ if (this.excludedAny != other.excludedAny)
+ return false;
+ if (this.holdingPriority != other.holdingPriority)
+ return false;
+ if (this.includeAll != other.includeAll)
+ return false;
+ if (this.includeAny != other.includeAny)
+ return false;
+ if (this.localProtected != other.localProtected)
+ return false;
+ if (this.setupPriority != other.setupPriority)
+ return false;
+ if (this.standByPath != other.standByPath)
+ return false;
+ if (this.tlvs == null) {
+ if (other.tlvs != null)
+ return false;
+ } else if (!this.tlvs.equals(other.tlvs))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("excludedAny", this.excludedAny);
+ toStringHelper.add("includeAny", this.includeAny);
+ toStringHelper.add("includeAll", this.includeAll);
+ toStringHelper.add("setupPriority", this.setupPriority);
+ toStringHelper.add("holdingPriority", this.holdingPriority);
+ toStringHelper.add("standByPath", this.standByPath);
+ toStringHelper.add("localProtected", this.localProtected);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Metric Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.8">PCEP Metric
+ * Object</a>
+ */
+public class PCEPMetricObject extends PCEPObject {
+
+ private final boolean bound;
+
+ private final boolean computedMetric;
+
+ private final AbstractMetric<?> metric;
+
+ /**
+ * Constructs PCEP Metric Object.
+ *
+ * @param bound
+ * boolean
+ * @param computedMetric
+ * boolean
+ * @param metric
+ * cannot be null
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPMetricObject(boolean bound, boolean computedMetric, AbstractMetric<?> metric, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ this.bound = bound;
+ this.computedMetric = computedMetric;
+ if (metric == null)
+ throw new IllegalArgumentException("Mandatory parameter metric cannot be null.");
+ this.metric = metric;
+ }
+
+ /**
+ * Gets Bound flag.
+ *
+ * @return boolean
+ */
+ public boolean isBound() {
+ return this.bound;
+ }
+
+ /**
+ * Gets Computed Metric flag.
+ *
+ * @return boolean
+ */
+ public boolean isComputedMetric() {
+ return this.computedMetric;
+ }
+
+ /**
+ * Gets {@link AbstractMetric<?>}.
+ *
+ * @return AbstractMetric<?>
+ */
+ public AbstractMetric<?> getMetric() {
+ return this.metric;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (this.bound ? 1231 : 1237);
+ result = prime * result + (this.computedMetric ? 1231 : 1237);
+ result = prime * result + ((this.metric == null) ? 0 : this.metric.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPMetricObject other = (PCEPMetricObject) obj;
+ if (this.bound != other.bound)
+ return false;
+ if (this.computedMetric != other.computedMetric)
+ return false;
+ if (this.metric == null) {
+ if (other.metric != null)
+ return false;
+ } else if (!this.metric.equals(other.metric))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("bound", this.bound);
+ toStringHelper.add("computedMetric", this.computedMetric);
+ toStringHelper.add("metric", this.metric);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP No Path Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.5">PCEP No Path
+ * Object</a>
+ */
+public class PCEPNoPathObject extends PCEPObject {
+
+ private final short natureOfIssue;
+
+ private final boolean constrained;
+
+ private final List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs PCEP No Path Object only with mandatory values.
+ *
+ * @param natureOfIssue
+ * short
+ * @param constrained
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPNoPathObject(short natureOfIssue, boolean constrained, boolean ignored) {
+ this(natureOfIssue, constrained, null, ignored);
+ }
+
+ /**
+ * Constructs PCEP No Path Object also with optional Objects.
+ *
+ * @param natureOfIssue
+ * short
+ * @param constrained
+ * boolean
+ * @param tlvs
+ * List<PCEPTlv>
+ * @param ignored
+ * boolean
+ */
+ public PCEPNoPathObject(short natureOfIssue, boolean constrained, List<PCEPTlv> tlvs, boolean ignored) {
+ super(false, ignored);
+ this.natureOfIssue = natureOfIssue;
+ this.constrained = constrained;
+ if (tlvs != null)
+ this.tlvs = tlvs;
+ else
+ this.tlvs = Collections.emptyList();
+ }
+
+ /**
+ * Returns short representation of Nature of issue.
+ *
+ * @return short
+ */
+ public short getNatureOfIssue() {
+ return this.natureOfIssue;
+ }
+
+ /**
+ * Gets Constrained flag.
+ *
+ * @return boolean
+ */
+ public boolean isConstrained() {
+ return this.constrained;
+ }
+
+ /**
+ * Gets list of {@link PCEPTlv}
+ *
+ * @return List<PCEPTlv>. Can't be null, but may be empty.
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (this.constrained ? 1231 : 1237);
+ result = prime * result + this.natureOfIssue;
+ result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPNoPathObject other = (PCEPNoPathObject) obj;
+ if (this.constrained != other.constrained)
+ return false;
+ if (this.natureOfIssue != other.natureOfIssue)
+ return false;
+ if (this.tlvs == null) {
+ if (other.tlvs != null)
+ return false;
+ } else if (!this.tlvs.equals(other.tlvs))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("natureOfIssue", this.natureOfIssue);
+ toStringHelper.add("constrained", this.constrained);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Structure of Non-Branch Node list object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.11.1">Branch Node
+ * Object [RFC6006]</a>
+ */
+public class PCEPNonBranchNodeListObject extends PCEPBranchNodeObject {
+
+ /**
+ * Constructs Non-Branch Node list object.
+ *
+ * @param subobjects
+ * List<ExplicitRouteSubobject>
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPNonBranchNodeListObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+ super(subobjects, processed, ignored);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Notification Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.14">PCEP
+ * Notification Object</a>
+ */
+public class PCEPNotificationObject extends PCEPObject {
+
+ private final short type;
+
+ private final short value;
+
+ private List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs PCEP Notification Object only with mandatory values.
+ *
+ * @param type
+ * short
+ * @param value
+ * short
+ */
+ public PCEPNotificationObject(short type, short value) {
+ this(type, value, null);
+ }
+
+ /**
+ * Constructs PCEP Notification Object also with optional Objects.
+ *
+ * @param type
+ * short
+ * @param value
+ * short
+ * @param tlvs
+ * List<PCEPTlv>
+ */
+ public PCEPNotificationObject(short type, short value, List<PCEPTlv> tlvs) {
+ super(false, false);
+ this.type = type;
+ this.value = value;
+ if (tlvs != null)
+ this.tlvs = tlvs;
+ else
+ this.tlvs = Collections.emptyList();
+ }
+
+ /**
+ * Returns short representation of Type.
+ *
+ * @return short
+ */
+ public short getType() {
+ return this.type;
+ }
+
+ /**
+ * Returns short value.
+ *
+ * @return short
+ */
+ public short getValue() {
+ return this.value;
+ }
+
+ /**
+ * Gets list of {@link PCEPTlv}
+ *
+ * @return List<PCEPTlv>. Can't be null, but may be empty.
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+ result = prime * result + this.type;
+ result = prime * result + this.value;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPNotificationObject other = (PCEPNotificationObject) obj;
+ if (this.tlvs == null) {
+ if (other.tlvs != null)
+ return false;
+ } else if (!this.tlvs.equals(other.tlvs))
+ return false;
+ if (this.type != other.type)
+ return false;
+ if (this.value != other.value)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("type", this.type);
+ toStringHelper.add("value", this.value);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Indicates the desired/required objective function to be applied by the PCE
+ * during path computation or within a PCRep message so as to indicate the
+ * objective function that was used by the PCE during path computation.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5541#section-3.1">OF Object</a>
+ */
+public class PCEPObjectiveFunctionObject extends PCEPObject {
+
+ private final PCEPOFCodes code;
+
+ private final List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs objective function object only with mandatory objects.
+ *
+ * @param code
+ * PCEPOFCodes
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPObjectiveFunctionObject(PCEPOFCodes code, boolean processed, boolean ignored) {
+ this(code, null, processed, ignored);
+ }
+
+ /**
+ * Constructs objective function object also with optional objects.
+ *
+ * @param code
+ * PCEPOFCodes
+ * @param tlvs
+ * the list of tlvs
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPObjectiveFunctionObject(PCEPOFCodes code, List<PCEPTlv> tlvs, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ this.code = code;
+
+ if (tlvs == null)
+ this.tlvs = Collections.emptyList();
+ else
+ this.tlvs = tlvs;
+ }
+
+ /**
+ * Gets the objective function code
+ *
+ * @return the PCEPOFCodes
+ */
+ public PCEPOFCodes getCode() {
+ return this.code;
+ }
+
+ /**
+ * Gets the list of tlvs
+ *
+ * @return the list of tlvs
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("code", this.code);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.code == null) ? 0 : this.code.hashCode());
+ result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPObjectiveFunctionObject other = (PCEPObjectiveFunctionObject) obj;
+ if (this.code != other.code)
+ return false;
+ if (this.tlvs == null) {
+ if (other.tlvs != null)
+ return false;
+ } else if (!this.tlvs.equals(other.tlvs))
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Open Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.3">PCEP Open
+ * Object</a>
+ */
+public class PCEPOpenObject extends PCEPObject {
+
+ public static final int PCEP_VERSION = 1;
+
+ private final int keepAliveTimerValue;
+
+ private final int deadTimerValue;
+
+ private final int sessionId;
+
+ private final List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs PCEP Open Object also with optional Objects.
+ *
+ * @param keepAliveTimerValue
+ * int
+ * @param deadTimerValue
+ * int
+ * @param sessionId
+ * int
+ * @param tlvs
+ * List<PCEPTlv>
+ */
+ public PCEPOpenObject(int keepAliveTimerValue, int deadTimerValue, int sessionId, List<PCEPTlv> tlvs) {
+ super(false, false);
+ this.keepAliveTimerValue = keepAliveTimerValue;
+ this.deadTimerValue = deadTimerValue;
+ this.sessionId = sessionId;
+ if (tlvs != null)
+ this.tlvs = tlvs;
+ else
+ this.tlvs = Collections.emptyList();
+ }
+
+ /**
+ * Constructs PCEP Open Object only with mandatory values.
+ *
+ * @param keepAliveTimerValue
+ * int
+ * @param deadTimerValue
+ * int
+ * @param sessionId
+ * int
+ */
+ public PCEPOpenObject(int keepAliveTimerValue, int deadTimerValue, int sessionId) {
+ this(keepAliveTimerValue, deadTimerValue, sessionId, Collections.<PCEPTlv> emptyList());
+ }
+
+ /**
+ * Returns integer representation of Keep Alive Timer.
+ *
+ * @return int
+ */
+ public int getKeepAliveTimerValue() {
+ return this.keepAliveTimerValue;
+ }
+
+ /**
+ * Returns integer representation of Dead Timer.
+ *
+ * @return int
+ */
+ public int getDeadTimerValue() {
+ return this.deadTimerValue;
+ }
+
+ /**
+ * Returns integer representation of Session ID.
+ *
+ * @return int
+ */
+ public int getSessionId() {
+ return this.sessionId;
+ }
+
+ /**
+ * Gets list of {@link PCEPTlv}.
+ *
+ * @return List<PCEPTlv>
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.deadTimerValue;
+ result = prime * result + this.keepAliveTimerValue;
+ result = prime * result + this.sessionId;
+ result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPOpenObject other = (PCEPOpenObject) obj;
+ if (this.deadTimerValue != other.deadTimerValue)
+ return false;
+ if (this.keepAliveTimerValue != other.keepAliveTimerValue)
+ return false;
+ if (this.sessionId != other.sessionId)
+ return false;
+ if (this.tlvs == null) {
+ if (other.tlvs != null)
+ return false;
+ } else if (!this.tlvs.equals(other.tlvs))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("keepAliveTimerValue", this.keepAliveTimerValue);
+ toStringHelper.add("deadTimerValue", this.deadTimerValue);
+ toStringHelper.add("sessionId", this.sessionId);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import com.google.common.base.Objects.ToStringHelper;
+
+public class PCEPP2MPEndPointsObject<T extends NetworkAddress<T>> extends PCEPEndPoints {
+
+ private final long leafType;
+
+ private final T sourceAddress;
+
+ private final List<T> destinationAddresses;
+
+ public PCEPP2MPEndPointsObject(long leafType, T sourceAddress, List<T> destinationAddresses, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ this.leafType = leafType;
+ this.sourceAddress = sourceAddress;
+ if (destinationAddresses == null || destinationAddresses.isEmpty())
+ throw new IllegalArgumentException("At least one destination have to be specified.");
+
+ this.destinationAddresses = destinationAddresses;
+ }
+
+ /**
+ * @return the leafType
+ */
+ public long getLeafType() {
+ return this.leafType;
+ }
+
+ /**
+ * @return the sourceAddress
+ */
+ public T getSourceAddress() {
+ return this.sourceAddress;
+ }
+
+ /**
+ * @return the destinationAddresses
+ */
+ public List<T> getDestinationAddresses() {
+ return this.destinationAddresses;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.destinationAddresses == null) ? 0 : this.destinationAddresses.hashCode());
+ result = prime * result + (int) (this.leafType ^ (this.leafType >>> 32));
+ result = prime * result + ((this.sourceAddress == null) ? 0 : this.sourceAddress.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPP2MPEndPointsObject<?> other = (PCEPP2MPEndPointsObject<?>) obj;
+ if (this.destinationAddresses == null) {
+ if (other.destinationAddresses != null)
+ return false;
+ } else if (!this.destinationAddresses.equals(other.destinationAddresses))
+ return false;
+ if (this.leafType != other.leafType)
+ return false;
+ if (this.sourceAddress == null) {
+ if (other.sourceAddress != null)
+ return false;
+ } else if (!this.sourceAddress.equals(other.sourceAddress))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("leafType", this.leafType);
+ toStringHelper.add("sourceAddress", this.sourceAddress);
+ toStringHelper.add("destinationAddresses", this.destinationAddresses);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Reported Route Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.10">PCEP Reported
+ * Route Object</a>
+ */
+public class PCEPReportedRouteObject extends PCEPObject {
+
+ private final List<ReportedRouteSubobject> subobjects;
+
+ /**
+ * Constructs PCEP Reported Route Object.
+ *
+ * @param subobjects
+ * List<ReportedRouteSubobject>. Can't be null or empty.
+ * @param processed
+ * boolean
+ */
+ public PCEPReportedRouteObject(List<ReportedRouteSubobject> subobjects, boolean processed) {
+ super(processed, false);
+ if (subobjects == null || subobjects.isEmpty())
+ throw new IllegalArgumentException("Subobjects can't be null or empty.");
+ this.subobjects = subobjects;
+ }
+
+ /**
+ * Gets list of {@link ReportedRouteSubobject}.
+ *
+ * @return List<PCEPSubobject>. Can't be null or empty.
+ */
+ public List<ReportedRouteSubobject> getSubobjects() {
+ return this.subobjects;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("subobjects", this.subobjects);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPReportedRouteObject other = (PCEPReportedRouteObject) obj;
+ if (this.subobjects == null) {
+ if (other.subobjects != null)
+ return false;
+ } else if (!this.subobjects.equals(other.subobjects))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP Requested Parameter Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.4">PCEP Request
+ * Parameter Object [RFC5440]</a>
+ * @see <a href="http://tools.ietf.org/html/rfc5541#section-6.2.4">RP Object
+ * Flag [RFC5541]</a>
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.3.1">The Extension
+ * of the RP Object [RFC6006]</a>
+ */
+public class PCEPRequestParameterObject extends PCEPObject {
+
+ private final boolean loose;
+
+ private final boolean bidirectional;
+
+ private final boolean reoptimized;
+
+ private final boolean makeBeforeBreak;
+
+ private final boolean reportRequestOrder;
+
+ private final boolean suplyOFOnResponse;
+
+ /*
+ * RFC6006 flags
+ */
+ private final boolean fragmentation;
+
+ private final boolean p2mp;
+
+ private final boolean eroCompression;
+
+ // End of flags
+
+ private final short priority;
+
+ private final long requestID;
+
+ private final List<PCEPTlv> tlvs;
+
+ /**
+ * Constructs PCEP Requested Parameter Object only with mandatory values.
+ *
+ * @param loose
+ * boolean
+ * @param bidirectional
+ * boolean
+ * @param reoptimized
+ * boolean
+ * @param makeBeforeBreak
+ * boolean
+ * @param suplyOFOnResponse
+ * boolean
+ * @param priority
+ * short
+ * @param requestID
+ * long
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean;
+ */
+ public PCEPRequestParameterObject(boolean loose, boolean bidirectional, boolean reoptimized, boolean makeBeforeBreak, boolean suplyOFOnResponse,
+ boolean fragmentation, boolean p2mp, boolean eroCompression, short priority, long requestID, boolean processed, boolean ignored) {
+ this(loose, bidirectional, reoptimized, makeBeforeBreak, false, suplyOFOnResponse, fragmentation, p2mp, eroCompression, priority, requestID, null,
+ processed, ignored);
+ }
+
+ /**
+ * Constructs PCEP Requested Parameter Object also with optional Objects.
+ *
+ * @param loose
+ * boolean
+ * @param bidirectional
+ * boolean
+ * @param reoptimized
+ * boolean
+ * @param makeBeforeBreak
+ * boolean
+ * @param reportRequestOrder
+ * boolean
+ * @param suplyOFOnResponse
+ * boolean
+ * @param priority
+ * short
+ * @param requestID
+ * long
+ * @param tlvs
+ * List<PCEPTlv>
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPRequestParameterObject(boolean loose, boolean bidirectional, boolean reoptimized, boolean makeBeforeBreak, boolean reportRequestOrder,
+ boolean suplyOFOnResponse, boolean fragmentation, boolean p2mp, boolean eroCompression, short priority, long requestID, List<PCEPTlv> tlvs,
+ boolean processed, boolean ignored) {
+ super(processed, ignored);
+ this.loose = loose;
+ this.bidirectional = bidirectional;
+ this.reoptimized = reoptimized;
+ this.makeBeforeBreak = makeBeforeBreak;
+ this.reportRequestOrder = reportRequestOrder;
+ this.suplyOFOnResponse = suplyOFOnResponse;
+ this.fragmentation = fragmentation;
+ this.p2mp = p2mp;
+ this.eroCompression = eroCompression;
+
+ this.priority = priority;
+ this.requestID = requestID;
+ if (tlvs != null)
+ this.tlvs = tlvs;
+ else
+ this.tlvs = Collections.emptyList();
+
+ if (makeBeforeBreak && !reoptimized)
+ throw new IllegalArgumentException("M (make-before-break) can be set only if R (reoptimied) flag is set too.");
+
+ if (reportRequestOrder && !this.validateOrderTlv())
+ throw new IllegalArgumentException("D (report request order) flag is set, but missing OrderTlv.");
+ }
+
+ /**
+ * Gets Loose flag.
+ *
+ * @return boolean
+ */
+ public boolean isLoose() {
+ return this.loose;
+ }
+
+ /**
+ * Gets Bidirectional flag.
+ *
+ * @return boolean
+ */
+ public boolean isBidirectional() {
+ return this.bidirectional;
+ }
+
+ /**
+ * Gets Reoptimization flag.
+ *
+ * @return boolean
+ */
+ public boolean isReoptimized() {
+ return this.reoptimized;
+ }
+
+ /**
+ * Gets make-before-break flag
+ *
+ * @return boolean
+ */
+ public boolean isMakeBeforeBreak() {
+ return this.makeBeforeBreak;
+ }
+
+ /**
+ * Gets report requested order flag
+ *
+ * @return boolean
+ */
+ public boolean isReportRequestOrder() {
+ return this.reportRequestOrder;
+ }
+
+ /**
+ * Gets report supply objective function on response flag
+ *
+ * @return boolean
+ */
+ public boolean isSuplyOFOnResponse() {
+ return this.suplyOFOnResponse;
+ }
+
+ /**
+ * @return the fragmentation
+ */
+ public boolean isFragmentation() {
+ return this.fragmentation;
+ }
+
+ /**
+ * @return the p2mp
+ */
+ public boolean isP2mp() {
+ return this.p2mp;
+ }
+
+ /**
+ * @return the eroCompression
+ */
+ public boolean isEroCompression() {
+ return this.eroCompression;
+ }
+
+ /**
+ * Returns short representation of Priority.
+ *
+ * @return short
+ */
+ public short getPriority() {
+ return this.priority;
+ }
+
+ /**
+ * Returns long representation of Requested ID.
+ *
+ * @return long
+ */
+ public long getRequestID() {
+ return this.requestID;
+ }
+
+ /**
+ * Gets list of {@link PCEPTlv}
+ *
+ * @return List<PCEPTlv>. Can't be null, but may be empty.
+ */
+ public List<PCEPTlv> getTlvs() {
+ return this.tlvs;
+ }
+
+ private boolean validateOrderTlv() {
+ for (final PCEPTlv tlv : this.tlvs) {
+ if (tlv instanceof OrderTlv)
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (this.bidirectional ? 1231 : 1237);
+ result = prime * result + (this.eroCompression ? 1231 : 1237);
+ result = prime * result + (this.fragmentation ? 1231 : 1237);
+ result = prime * result + (this.loose ? 1231 : 1237);
+ result = prime * result + (this.makeBeforeBreak ? 1231 : 1237);
+ result = prime * result + (this.p2mp ? 1231 : 1237);
+ result = prime * result + this.priority;
+ result = prime * result + (this.reoptimized ? 1231 : 1237);
+ result = prime * result + (this.reportRequestOrder ? 1231 : 1237);
+ result = prime * result + (int) (this.requestID ^ (this.requestID >>> 32));
+ result = prime * result + (this.suplyOFOnResponse ? 1231 : 1237);
+ result = prime * result + ((this.tlvs == null) ? 0 : this.tlvs.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPRequestParameterObject other = (PCEPRequestParameterObject) obj;
+ if (this.bidirectional != other.bidirectional)
+ return false;
+ if (this.eroCompression != other.eroCompression)
+ return false;
+ if (this.fragmentation != other.fragmentation)
+ return false;
+ if (this.loose != other.loose)
+ return false;
+ if (this.makeBeforeBreak != other.makeBeforeBreak)
+ return false;
+ if (this.p2mp != other.p2mp)
+ return false;
+ if (this.priority != other.priority)
+ return false;
+ if (this.reoptimized != other.reoptimized)
+ return false;
+ if (this.reportRequestOrder != other.reportRequestOrder)
+ return false;
+ if (this.requestID != other.requestID)
+ return false;
+ if (this.suplyOFOnResponse != other.suplyOFOnResponse)
+ return false;
+ if (this.tlvs == null) {
+ if (other.tlvs != null)
+ return false;
+ } else if (!this.tlvs.equals(other.tlvs))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("loose", this.loose);
+ toStringHelper.add("bidirectional", this.bidirectional);
+ toStringHelper.add("reoptimized", this.reoptimized);
+ toStringHelper.add("makeBeforeBreak", this.makeBeforeBreak);
+ toStringHelper.add("reportRequestOrder", this.reportRequestOrder);
+ toStringHelper.add("suplyOFOnResponse", this.suplyOFOnResponse);
+ toStringHelper.add("fragmentation", this.fragmentation);
+ toStringHelper.add("p2mp", this.p2mp);
+ toStringHelper.add("eroCompression", this.eroCompression);
+ toStringHelper.add("priority", this.priority);
+ toStringHelper.add("requestID", this.requestID);
+ toStringHelper.add("tlvs", this.tlvs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+
+/**
+ * Structure of specific Bandwidth. Used for example in Composite Requested
+ * Object to request specific bandwidth.
+ */
+public class PCEPRequestedPathBandwidthObject extends PCEPBandwidthObject {
+
+ /**
+ * Constructs Requested Path Bandwidth.
+ *
+ * @param bandwidth
+ * Bandwidth. Can't be null.
+ * @param processed
+ * boolean
+ * @param ignored
+ * boolean
+ */
+ public PCEPRequestedPathBandwidthObject(Bandwidth bandwidth, boolean processed, boolean ignored) {
+ super(bandwidth, processed, ignored);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * @author miroslav
+ *
+ * May 2012
+ *
+ * Copyright (c) 2012 by Cisco Systems, Inc. All rights reserved.
+ */
+
+public class PCEPSecondaryExplicitRouteObject extends PCEPObject {
+
+ private final List<ExplicitRouteSubobject> subobjects;
+
+ /**
+ * Constructs Secondary Explicit Route Object.
+ *
+ * @param subobjects
+ * List<ExplicitRouteSubobject>. Can't be null or empty.
+ * @param ignored
+ * boolean
+ */
+ public PCEPSecondaryExplicitRouteObject(List<ExplicitRouteSubobject> subobjects, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ if (subobjects == null || subobjects.isEmpty())
+ throw new IllegalArgumentException("Subobjects can't be null or empty.");
+ this.subobjects = subobjects;
+ }
+
+ /**
+ * Gets list of {@link ExplicitRouteSubobject}
+ *
+ * @return List<ExplicitRouteSubobject>. Can't be null or empty.
+ */
+ public List<ExplicitRouteSubobject> getSubobjects() {
+ return this.subobjects;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("subobjects", this.subobjects);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPSecondaryExplicitRouteObject other = (PCEPSecondaryExplicitRouteObject) obj;
+ if (this.subobjects == null) {
+ if (other.subobjects != null)
+ return false;
+ } else if (!this.subobjects.equals(other.subobjects))
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.base.Objects.ToStringHelper;
+
+public class PCEPSecondaryRecordRouteObject extends PCEPObject {
+
+ private final List<ReportedRouteSubobject> subobjects;
+
+ /**
+ * Constructs Secondary Record Route Object.
+ *
+ * @param subobjects
+ * List<ReportedRouteSubobject>. Can't be null or empty.
+ * @param ignored
+ * boolean
+ */
+ public PCEPSecondaryRecordRouteObject(List<ReportedRouteSubobject> subobjects, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ if (subobjects == null || subobjects.isEmpty())
+ throw new IllegalArgumentException("Subobjects can't be null or empty.");
+ this.subobjects = subobjects;
+ }
+
+ /**
+ * Gets list of {@link ReportedRouteSubobject}
+ *
+ * @return List<ReportedRouteSubobject>. Can't be null or empty.
+ */
+ public List<ReportedRouteSubobject> getSubobjects() {
+ return this.subobjects;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("subobjects", this.subobjects);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.subobjects == null) ? 0 : this.subobjects.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPSecondaryRecordRouteObject other = (PCEPSecondaryRecordRouteObject) obj;
+ if (this.subobjects == null) {
+ if (other.subobjects != null)
+ return false;
+ } else if (!this.subobjects.equals(other.subobjects))
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of PCEP SVEC Object.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.13">PCEP SVEC
+ * Object</a>
+ * @see <a
+ * href="http://tools.ietf.org/html/rfc6006#section-3.12">Synchronization
+ * of P2MP TE Path Computation Requests [RFC6006]</a>
+ */
+public class PCEPSvecObject extends PCEPObject {
+
+ private final boolean linkDiversed;
+
+ private final boolean nodeDiversed;
+
+ private final boolean srlgDiversed;
+
+ private final boolean paritialPathDiversed;
+
+ private final boolean linkDirectionDiversed;
+
+ private final List<Long> requestIDs;
+
+ /**
+ * Constructs PCEP SVEC Object.
+ *
+ * @param linkDiversed
+ * boolean
+ * @param nodeDiversed
+ * boolean
+ * @param srlgDiversed
+ * boolean
+ * @param requestIDs
+ * List<Long>. Can't be null or empty.
+ * @param processed
+ * boolean
+ */
+ public PCEPSvecObject(boolean linkDiversed, boolean nodeDiversed, boolean srlgDiversed, boolean partialPathDiversed, boolean linkDirectionDiversed,
+ List<Long> requestIDs, boolean processed) {
+ super(processed, false);
+ this.linkDiversed = linkDiversed;
+ this.nodeDiversed = nodeDiversed;
+ this.srlgDiversed = srlgDiversed;
+ this.paritialPathDiversed = partialPathDiversed;
+ this.linkDirectionDiversed = linkDirectionDiversed;
+
+ if (requestIDs == null || requestIDs.isEmpty())
+ throw new IllegalArgumentException("RequestIDs can't be null or empty.");
+ this.requestIDs = requestIDs;
+ }
+
+ /**
+ * Gets Link Diversed flag.
+ *
+ * @return boolean
+ */
+ public boolean isLinkDiversed() {
+ return this.linkDiversed;
+ }
+
+ /**
+ * Gets Node Diversed flag.
+ *
+ * @return boolean
+ */
+ public boolean isNodeDiversed() {
+ return this.nodeDiversed;
+ }
+
+ /**
+ * Gets Srlg Diversed flag.
+ *
+ * @return boolean
+ */
+ public boolean isSrlgDiversed() {
+ return this.srlgDiversed;
+ }
+
+ public boolean isParitialPathDiversed() {
+ return this.paritialPathDiversed;
+ }
+
+ public boolean isLinkDirectionDiversed() {
+ return this.linkDirectionDiversed;
+ }
+
+ /**
+ * Gets list of Long representations of RequestIDs.
+ *
+ * @return List<Long>. Can't be null or empty.
+ */
+ public List<Long> getRequestIDs() {
+ return this.requestIDs;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (this.linkDiversed ? 1231 : 1237);
+ result = prime * result + (this.nodeDiversed ? 1231 : 1237);
+ result = prime * result + ((this.requestIDs == null) ? 0 : this.requestIDs.hashCode());
+ result = prime * result + (this.srlgDiversed ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPSvecObject other = (PCEPSvecObject) obj;
+ if (this.linkDiversed != other.linkDiversed)
+ return false;
+ if (this.nodeDiversed != other.nodeDiversed)
+ return false;
+ if (this.requestIDs == null) {
+ if (other.requestIDs != null)
+ return false;
+ } else if (!this.requestIDs.equals(other.requestIDs))
+ return false;
+ if (this.srlgDiversed != other.srlgDiversed)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("linkDiversed", this.linkDiversed);
+ toStringHelper.add("nodeDiversed", this.nodeDiversed);
+ toStringHelper.add("srlgDiversed", this.srlgDiversed);
+ toStringHelper.add("paritialPathDiversed", this.paritialPathDiversed);
+ toStringHelper.add("linkDirectionDiversed", this.linkDirectionDiversed);
+ toStringHelper.add("requestIDs", this.requestIDs);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import com.google.common.base.Objects.ToStringHelper;
+
+public class PCEPUnreachedDestinationObject<T extends NetworkAddress<T>> extends PCEPObject {
+
+ private final List<T> unreachedDestinations;
+
+ public PCEPUnreachedDestinationObject(List<T> unreachedDestinations, boolean processed, boolean ignored) {
+ super(processed, ignored);
+ if (unreachedDestinations == null || unreachedDestinations.isEmpty())
+ throw new IllegalArgumentException("At least one destination have to be specified.");
+
+ this.unreachedDestinations = unreachedDestinations;
+ }
+
+ public List<T> getUnreachedDestinations() {
+ return this.unreachedDestinations;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.unreachedDestinations == null) ? 0 : this.unreachedDestinations.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPUnreachedDestinationObject<?> other = (PCEPUnreachedDestinationObject<?>) obj;
+ if (this.unreachedDestinations == null) {
+ if (other.unreachedDestinations != null)
+ return false;
+ } else if (!this.unreachedDestinations.equals(other.unreachedDestinations))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("unreachedDestinations", this.unreachedDestinations);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Autonomous System Number Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3.3.4">Section
+ * 4.3.3.4.: Subobject 32: Autonomous System Number</a>
+ */
+public class EROAsNumberSubobject extends ExplicitRouteSubobject {
+
+ private final ASNumber asnumber;
+
+ /**
+ * Constructs new ASNumber Subobject.
+ *
+ * @param asnumber
+ * ASNumber
+ * @param loose
+ * boolean
+ */
+ public EROAsNumberSubobject(ASNumber asnumber, boolean loose) {
+ super(loose);
+ this.asnumber = asnumber;
+ }
+
+ /**
+ * Gets {@link ASNumber}.
+ *
+ * @return ASNumber
+ */
+ public ASNumber getASNumber() {
+ return this.asnumber;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.asnumber == null) ? 0 : this.asnumber.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROAsNumberSubobject other = (EROAsNumberSubobject) obj;
+ if (this.asnumber == null) {
+ if (other.asnumber != null)
+ return false;
+ } else if (!this.asnumber.equals(other.asnumber))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("asnumber", this.asnumber);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import java.util.List;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROExplicitExclusionRouteSubobject extends ExplicitRouteSubobject {
+ private final List<ExcludeRouteSubobject> xroSubobjets;
+
+ public EROExplicitExclusionRouteSubobject(List<ExcludeRouteSubobject> xroSubobjets) {
+ super();
+ this.xroSubobjets = xroSubobjets;
+ }
+
+ public List<ExcludeRouteSubobject> getXroSubobjets() {
+ return this.xroSubobjets;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.xroSubobjets == null) ? 0 : this.xroSubobjets.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROExplicitExclusionRouteSubobject other = (EROExplicitExclusionRouteSubobject) obj;
+ if (this.xroSubobjets == null) {
+ if (other.xroSubobjets != null)
+ return false;
+ } else if (!this.xroSubobjets.equals(other.xroSubobjets))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("xroSubobjets", this.xroSubobjets);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Generalized Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3471#section-3.2">3.2.
+ * Generalized Label</a>
+ */
+public class EROGeneralizedLabelSubobject extends EROLabelSubobject {
+
+ private final byte[] label;
+
+ public EROGeneralizedLabelSubobject(byte[] label, boolean upStream, boolean loose) {
+ super(upStream);
+
+ if (label.length % 4 != 0)
+ throw new IllegalArgumentException("Length of label is not multiple of 4.");
+
+ this.label = label;
+ }
+
+ public byte[] getLabel() {
+ return this.label;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + Arrays.hashCode(this.label);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROGeneralizedLabelSubobject other = (EROGeneralizedLabelSubobject) obj;
+ if (!Arrays.equals(this.label, other.label))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("label", this.label);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.Prefix;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Parametrized structure of IP Prefix Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3.3.2">Section
+ * 4.3.3.2.: Subobject 1: IPv4 prefix</a> and <a
+ * href="http://tools.ietf.org/html/rfc3209#section-4.3.3.3">Section
+ * 4.3.3.2.: Subobject 2: IPv6 prefix</a>
+ *
+ * @param <T>
+ * subtype of Prefix
+ */
+public class EROIPPrefixSubobject<T extends Prefix<?>> extends ExplicitRouteSubobject {
+
+ private final T prefix;
+
+ /**
+ * Constructs IPPrefix Subobject.
+ *
+ * @param prefix
+ * T
+ * @param loose
+ * boolean
+ */
+ public EROIPPrefixSubobject(T prefix, boolean loose) {
+ super(loose);
+ this.prefix = prefix;
+ }
+
+ /**
+ * Gets specific {@link Prefix}.
+ *
+ * @return prefix T
+ */
+ public T getPrefix() {
+ return this.prefix;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.prefix == null) ? 0 : this.prefix.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROIPPrefixSubobject<?> other = (EROIPPrefixSubobject<?>) obj;
+ if (this.prefix == null) {
+ if (other.prefix != null)
+ return false;
+ } else if (!this.prefix.equals(other.prefix))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("prefix", this.prefix);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Label subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3473#section-5.1">Label ERO
+ * subobject</a>
+ */
+
+public abstract class EROLabelSubobject extends ExplicitRouteSubobject {
+
+ private final boolean upStream;
+
+ /**
+ * Constructs new Label subobject.
+ *
+ * @param upStream
+ * if set label is upstream
+ * @param label
+ * Label
+ * @param loose
+ * boolean
+ */
+ public EROLabelSubobject(boolean upStream) {
+ super(false);
+ this.upStream = upStream;
+ }
+
+ public boolean isUpStream() {
+ return this.upStream;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (this.upStream ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROLabelSubobject other = (EROLabelSubobject) obj;
+ if (this.upStream != other.upStream)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("upStream", this.upStream);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROPathKeyWith128PCEIDSubobject extends ExplicitRouteSubobject {
+
+ private final int pathKey;
+
+ private final byte[] pceId;
+
+ public EROPathKeyWith128PCEIDSubobject(int pathKey, byte[] pceId, boolean loose) {
+ super(loose);
+ this.pathKey = pathKey;
+ if (pceId == null)
+ throw new IllegalArgumentException("PCE ID can't be null.");
+
+ if (pceId.length != 16)
+ throw new IllegalArgumentException("PCE ID is not 16 bytes long.");
+
+ this.pceId = pceId;
+ }
+
+ public int getPathKey() {
+ return this.pathKey;
+ }
+
+ public byte[] getPceId() {
+ return this.pceId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + this.pathKey;
+ result = prime * result + Arrays.hashCode(this.pceId);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROPathKeyWith128PCEIDSubobject other = (EROPathKeyWith128PCEIDSubobject) obj;
+ if (this.pathKey != other.pathKey)
+ return false;
+ if (!Arrays.equals(this.pceId, other.pceId))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("pathKey", this.pathKey);
+ toStringHelper.add("pceId", this.pceId);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROPathKeyWith32PCEIDSubobject extends ExplicitRouteSubobject {
+
+ private final int pathKey;
+
+ private final byte[] pceId;
+
+ public EROPathKeyWith32PCEIDSubobject(int pathKey, byte[] pceId, boolean loose) {
+ super(loose);
+ this.pathKey = pathKey;
+ if (pceId == null)
+ throw new IllegalArgumentException("PCE ID can't be null.");
+
+ if (pceId.length != 4)
+ throw new IllegalArgumentException("PCE ID is not 4 bytes long.");
+
+ this.pceId = pceId;
+ }
+
+ public int getPathKey() {
+ return this.pathKey;
+ }
+
+ public byte[] getPceId() {
+ return this.pceId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + this.pathKey;
+ result = prime * result + Arrays.hashCode(this.pceId);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROPathKeyWith32PCEIDSubobject other = (EROPathKeyWith32PCEIDSubobject) obj;
+ if (this.pathKey != other.pathKey)
+ return false;
+ if (!Arrays.equals(this.pceId, other.pceId))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("pathKey", this.pathKey);
+ toStringHelper.add("pceId", this.pceId);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+public abstract class EROProtectionSubobject extends ExplicitRouteSubobject {
+ public EROProtectionSubobject(boolean loose) {
+ super(loose);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROProtectionType1Subobject extends EROProtectionSubobject {
+
+ private final boolean secondary;
+
+ private final byte linkFlags;
+
+ /**
+ * @param secondary
+ * @param linkFlags
+ */
+ public EROProtectionType1Subobject(boolean secondary, byte linkFlags, boolean loose) {
+ super(loose);
+ this.secondary = secondary;
+ this.linkFlags = linkFlags;
+ }
+
+ /**
+ * @return the secondary
+ */
+ public boolean isSecondary() {
+ return this.secondary;
+ }
+
+ /**
+ * @return the linkFlags
+ */
+ public byte getLinkFlags() {
+ return this.linkFlags;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + this.linkFlags;
+ result = prime * result + (this.secondary ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROProtectionType1Subobject other = (EROProtectionType1Subobject) obj;
+ if (this.linkFlags != other.linkFlags)
+ return false;
+ if (this.secondary != other.secondary)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("secondary", this.secondary);
+ toStringHelper.add("linkFlags", this.linkFlags);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public class EROProtectionType2Subobject extends EROProtectionSubobject {
+ private final boolean secondaryLsp;
+
+ private final boolean protectionLsp;
+
+ private final boolean notification;
+
+ private final boolean operational;
+
+ private final byte lspFlags;
+
+ private final byte linkFlags;
+
+ private final boolean inPlace;
+
+ private final boolean required;
+
+ private final byte segFlags;
+
+ /**
+ * @param secondaryLsp
+ * @param protectionLsp
+ * @param notification
+ * @param operational
+ * @param lspFlags
+ * @param linkFlags
+ * @param inPlace
+ * @param required
+ * @param segFlags
+ */
+ public EROProtectionType2Subobject(boolean secondaryLsp, boolean protectionLsp, boolean notification, boolean operational, byte lspFlags, byte linkFlags,
+ boolean inPlace, boolean required, byte segFlags, boolean loose) {
+ super(loose);
+ this.secondaryLsp = secondaryLsp;
+ this.protectionLsp = protectionLsp;
+ this.notification = notification;
+ this.operational = operational;
+ this.lspFlags = lspFlags;
+ this.linkFlags = linkFlags;
+ this.inPlace = inPlace;
+ this.required = required;
+ this.segFlags = segFlags;
+ }
+
+ /**
+ * @return the secondaryLsp
+ */
+ public boolean isSecondaryLsp() {
+ return this.secondaryLsp;
+ }
+
+ /**
+ * @return the protectionLsp
+ */
+ public boolean isProtectionLsp() {
+ return this.protectionLsp;
+ }
+
+ /**
+ * @return the notification
+ */
+ public boolean isNotification() {
+ return this.notification;
+ }
+
+ /**
+ * @return the operational
+ */
+ public boolean isOperational() {
+ return this.operational;
+ }
+
+ /**
+ * @return the lspFlags
+ */
+ public byte getLspFlags() {
+ return this.lspFlags;
+ }
+
+ /**
+ * @return the linkFlags
+ */
+ public byte getLinkFlags() {
+ return this.linkFlags;
+ }
+
+ /**
+ * @return the inPlace
+ */
+ public boolean isInPlace() {
+ return this.inPlace;
+ }
+
+ /**
+ * @return the required
+ */
+ public boolean isRequired() {
+ return this.required;
+ }
+
+ /**
+ * @return the segFlags
+ */
+ public byte getSegFlags() {
+ return this.segFlags;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (this.inPlace ? 1231 : 1237);
+ result = prime * result + this.linkFlags;
+ result = prime * result + this.lspFlags;
+ result = prime * result + (this.notification ? 1231 : 1237);
+ result = prime * result + (this.operational ? 1231 : 1237);
+ result = prime * result + (this.protectionLsp ? 1231 : 1237);
+ result = prime * result + (this.required ? 1231 : 1237);
+ result = prime * result + (this.secondaryLsp ? 1231 : 1237);
+ result = prime * result + this.segFlags;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROProtectionType2Subobject other = (EROProtectionType2Subobject) obj;
+ if (this.inPlace != other.inPlace)
+ return false;
+ if (this.linkFlags != other.linkFlags)
+ return false;
+ if (this.lspFlags != other.lspFlags)
+ return false;
+ if (this.notification != other.notification)
+ return false;
+ if (this.operational != other.operational)
+ return false;
+ if (this.protectionLsp != other.protectionLsp)
+ return false;
+ if (this.required != other.required)
+ return false;
+ if (this.secondaryLsp != other.secondaryLsp)
+ return false;
+ if (this.segFlags != other.segFlags)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("secondaryLsp", this.secondaryLsp);
+ toStringHelper.add("protectionLsp", this.protectionLsp);
+ toStringHelper.add("notification", this.notification);
+ toStringHelper.add("operational", this.operational);
+ toStringHelper.add("lspFlags", this.lspFlags);
+ toStringHelper.add("linkFlags", this.linkFlags);
+ toStringHelper.add("inPlace", this.inPlace);
+ toStringHelper.add("required", this.required);
+ toStringHelper.add("segFlags", this.segFlags);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Type 1 Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.1">4.1. Label
+ * Object</a>
+ */
+public class EROType1LabelSubobject extends EROLabelSubobject {
+
+ private final long label;
+
+ public EROType1LabelSubobject(long label, boolean upStream, boolean loose) {
+ super(upStream);
+ this.label = label;
+ }
+
+ public long getLabel() {
+ return this.label;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (int) (this.label ^ (this.label >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROType1LabelSubobject other = (EROType1LabelSubobject) obj;
+ if (this.label != other.label)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("label", this.label);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of unnumbered Iterface Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3477">Section 4: Signalling
+ * Unnumbered Links in EROs</a>
+ */
+public class EROUnnumberedInterfaceSubobject extends ExplicitRouteSubobject {
+ private final UnnumberedInterfaceIdentifier interfaceID;
+ private final IPv4Address routerID;
+
+ /**
+ * Constructs new Unnumbered Interface Subobject.
+ *
+ * @param routerID
+ * IPv4Address
+ * @param interfaceID
+ * UnnumberedInterfaceIdentifier
+ * @param loose
+ * boolean
+ */
+ public EROUnnumberedInterfaceSubobject(final IPv4Address routerID, final UnnumberedInterfaceIdentifier interfaceID, boolean loose) {
+ super(loose);
+ this.routerID = routerID;
+ this.interfaceID = interfaceID;
+ }
+
+ /**
+ * Gets {@link IPv4Address} representation of router ID.
+ *
+ * @return IPv4Address
+ */
+ public IPv4Address getRouterID() {
+ return this.routerID;
+ }
+
+ /**
+ * Gets {@link UnnumberedInterfaceIdentifier} representation of Interface
+ * ID.
+ *
+ * @return UnnumberedInterfaceIdentifier
+ */
+ public UnnumberedInterfaceIdentifier getInterfaceID() {
+ return this.interfaceID;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.interfaceID == null) ? 0 : this.interfaceID.hashCode());
+ result = prime * result + ((this.routerID == null) ? 0 : this.routerID.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROUnnumberedInterfaceSubobject other = (EROUnnumberedInterfaceSubobject) obj;
+ if (this.interfaceID == null) {
+ if (other.interfaceID != null)
+ return false;
+ } else if (!this.interfaceID.equals(other.interfaceID))
+ return false;
+ if (this.routerID == null) {
+ if (other.routerID != null)
+ return false;
+ } else if (!this.routerID.equals(other.routerID))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("EROUnnumberedInterfaceSubobject [interfaceID=");
+ builder.append(this.interfaceID);
+ builder.append(", routerID=");
+ builder.append(this.routerID);
+ builder.append(", loose=");
+ builder.append(this.loose);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("interfaceID", this.interfaceID);
+ toStringHelper.add("routerID", this.routerID);
+ toStringHelper.add("loose", this.loose);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Generalized Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3473#section-2.4">2.4. Waveband
+ * Switching Object </a>
+ */
+public class EROWavebandSwitchingLabelSubobject extends EROLabelSubobject {
+
+ private final long wavebandId;
+
+ private final long startLabel;
+
+ private final long endLabel;
+
+ public EROWavebandSwitchingLabelSubobject(long wavebandId, long startLabel, long endLabel, boolean upStream, boolean loose) {
+ super(upStream);
+ this.wavebandId = wavebandId;
+ this.startLabel = startLabel;
+ this.endLabel = endLabel;
+ }
+
+ public long getWavebandId() {
+ return this.wavebandId;
+ }
+
+ public long getStartLabel() {
+ return this.startLabel;
+ }
+
+ public long getEndLabel() {
+ return this.endLabel;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (int) (this.endLabel ^ (this.endLabel >>> 32));
+ result = prime * result + (int) (this.startLabel ^ (this.startLabel >>> 32));
+ result = prime * result + (int) (this.wavebandId ^ (this.wavebandId >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final EROWavebandSwitchingLabelSubobject other = (EROWavebandSwitchingLabelSubobject) obj;
+ if (this.endLabel != other.endLabel)
+ return false;
+ if (this.startLabel != other.startLabel)
+ return false;
+ if (this.wavebandId != other.wavebandId)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("wavebandId", this.wavebandId);
+ toStringHelper.add("startLabel", this.startLabel);
+ toStringHelper.add("endLabel", this.endLabel);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+public abstract class ExcludeRouteSubobject {
+
+ protected final boolean mandatory;
+
+ public ExcludeRouteSubobject(boolean mandatory) {
+ this.mandatory = mandatory;
+ }
+
+ public boolean isMandatory() {
+ return this.mandatory;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.mandatory ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final ExcludeRouteSubobject other = (ExcludeRouteSubobject) obj;
+ if (this.mandatory != other.mandatory)
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Base class for Explicit route subobjects.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3">4.3. Explicit
+ * Route Object</a>
+ */
+public abstract class ExplicitRouteSubobject {
+ protected final boolean loose;
+
+ protected ExplicitRouteSubobject() {
+ this.loose = false;
+ }
+
+ protected ExplicitRouteSubobject(boolean loose) {
+ this.loose = loose;
+ }
+
+ /**
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3.3.1">Strict
+ * and Loose Subobjects</a>
+ *
+ * @return true if L flag is set and false if is not.
+ */
+ public boolean isLoose() {
+ return this.loose;
+ }
+
+ @Override
+ public String toString(){
+ return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("loose", this.loose);
+ return toStringHelper;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.loose ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final ExplicitRouteSubobject other = (ExplicitRouteSubobject) obj;
+ if (this.loose != other.loose)
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * Structure of Autonomous System Number Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.3.3.4">Section
+ * 4.3.3.4.: Subobject 32: Autonomous System Number</a>
+ */
+public class RROAsNumberSubobject extends ReportedRouteSubobject {
+
+ private final ASNumber asnumber;
+
+ /**
+ * Constructs new ASNumber Subobject.
+ *
+ * @param asnumber
+ * ASNumber
+ */
+ public RROAsNumberSubobject(ASNumber asnumber) {
+ super();
+ this.asnumber = asnumber;
+ }
+
+ /**
+ * Gets {@link ASNumber}.
+ *
+ * @return ASNumber
+ */
+ public ASNumber getASNumber() {
+ return this.asnumber;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.asnumber == null) ? 0 : this.asnumber.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROAsNumberSubobject other = (RROAsNumberSubobject) obj;
+ if (this.asnumber == null) {
+ if (other.asnumber != null)
+ return false;
+ } else if (!this.asnumber.equals(other.asnumber))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("RROAsNumberSubobject [asnumber=");
+ builder.append(this.asnumber);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import java.util.Arrays;
+
+public class RROAttributesSubobject extends ReportedRouteSubobject {
+
+ private final byte[] attributes;
+
+ public RROAttributesSubobject(byte[] attributes) {
+ super();
+
+ if (attributes.length % 4 != 0)
+ throw new IllegalArgumentException("Attributes have to be multiple of 4.");
+
+ this.attributes = attributes;
+ }
+
+ public byte[] getAttributes() {
+ return this.attributes;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(this.attributes);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROAttributesSubobject other = (RROAttributesSubobject) obj;
+ if (!Arrays.equals(this.attributes, other.attributes))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("RROAttributesSubobject [attributes=");
+ builder.append(Arrays.toString(this.attributes));
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import java.util.Arrays;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Generalized Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3471#section-3.2">3.2.
+ * Generalized Label</a>
+ */
+public class RROGeneralizedLabelSubobject extends RROLabelSubobject {
+
+ private final byte[] label;
+
+ public RROGeneralizedLabelSubobject(byte[] label, boolean upStream) {
+ super(upStream);
+
+ if (label.length % 4 != 0)
+ throw new IllegalArgumentException("Length of label is not multiple of 4.");
+
+ this.label = label;
+ }
+
+ public byte[] getLabel() {
+ return this.label;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + Arrays.hashCode(this.label);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROGeneralizedLabelSubobject other = (RROGeneralizedLabelSubobject) obj;
+ if (!Arrays.equals(this.label, other.label))
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("label", this.label);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ * Parametrized structure of RRO IP Address Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.4.1.1">Section
+ * 4.4.1.1: Subobject 1: IPv4 address</a> and <a
+ * href="http://tools.ietf.org/html/rfc3209#section-4.4.1.2">Section
+ * 4.4.1.2: Subobject 2: IPv6 address</a>
+ *
+ * @param <T>
+ * subtype of Prefix
+ */
+public class RROIPAddressSubobject<T extends Prefix<?>> extends ReportedRouteSubobject {
+
+ private final T prefix;
+
+ /**
+ * Local protection available
+ */
+ private final boolean localProtectionAvailable;
+
+ /**
+ * Local protection in use
+ */
+ private final boolean localProtectionInUse;
+
+ /**
+ * Constructs IPPrefix Subobject.
+ *
+ * @param prefix
+ * T
+ * @param localProtectionAvailable
+ * boolean
+ * @param localProtectionInUse
+ * boolean
+ */
+ public RROIPAddressSubobject(T prefix, boolean localProtectionAvailable, boolean localProtectionInUse) {
+ super();
+ this.prefix = prefix;
+ this.localProtectionAvailable = localProtectionAvailable;
+ this.localProtectionInUse = localProtectionInUse;
+ }
+
+ /**
+ * Gets specific {@link Prefix}.
+ *
+ * @return prefix T
+ */
+ public T getPrefix() {
+ return this.prefix;
+ }
+
+ /**
+ * Returns tru if local protection is available.
+ *
+ * @return boolean
+ */
+ public boolean isLocalProtectionAvailable() {
+ return this.localProtectionAvailable;
+ }
+
+ /**
+ * Returns true if local protection is in use
+ *
+ * @return boolean
+ */
+ public boolean isLocalProtectionInUse() {
+ return this.localProtectionInUse;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.localProtectionAvailable ? 1231 : 1237);
+ result = prime * result + (this.localProtectionInUse ? 1231 : 1237);
+ result = prime * result + ((this.prefix == null) ? 0 : this.prefix.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROIPAddressSubobject<?> other = (RROIPAddressSubobject<?>) obj;
+ if (this.localProtectionAvailable != other.localProtectionAvailable)
+ return false;
+ if (this.localProtectionInUse != other.localProtectionInUse)
+ return false;
+ if (this.prefix == null) {
+ if (other.prefix != null)
+ return false;
+ } else if (!this.prefix.equals(other.prefix))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("RROIPAddressSubobject [prefix=");
+ builder.append(this.prefix);
+ builder.append(", lpa=");
+ builder.append(this.localProtectionAvailable);
+ builder.append(", lpiu=");
+ builder.append(this.localProtectionInUse);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Label subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3473#section-5.1">Label ERO
+ * subobject</a>
+ */
+public abstract class RROLabelSubobject extends ReportedRouteSubobject {
+
+ private final boolean upStream;
+
+ /**
+ * Constructs new Label subobject.
+ *
+ * @param upStream
+ * if set label is upstream
+ * @param label
+ * Label
+ * @param loose
+ * boolean
+ */
+ public RROLabelSubobject(boolean upStream) {
+ this.upStream = upStream;
+ }
+
+ public boolean isUpStream() {
+ return this.upStream;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (this.upStream ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROLabelSubobject other = (RROLabelSubobject) obj;
+ if (this.upStream != other.upStream)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString(){
+ return this.addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("upStream", this.upStream);
+ return toStringHelper;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import java.util.Arrays;
+
+public class RROPathKeyWith128PCEIDSubobject extends ReportedRouteSubobject {
+
+ private final int pathKey;
+
+ private final byte[] pceId;
+
+ public RROPathKeyWith128PCEIDSubobject(int pathKey, byte[] pceId) {
+ super();
+ this.pathKey = pathKey;
+ if (pceId == null)
+ throw new IllegalArgumentException("PCE ID can't be null.");
+
+ if (pceId.length != 16)
+ throw new IllegalArgumentException("PCE ID is not 16 bytes long.");
+
+ this.pceId = pceId;
+ }
+
+ public int getPathKey() {
+ return this.pathKey;
+ }
+
+ public byte[] getPceId() {
+ return this.pceId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.pathKey;
+ result = prime * result + Arrays.hashCode(this.pceId);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROPathKeyWith128PCEIDSubobject other = (RROPathKeyWith128PCEIDSubobject) obj;
+ if (this.pathKey != other.pathKey)
+ return false;
+ if (!Arrays.equals(this.pceId, other.pceId))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("RROPathKeyWith128PCEIDSubobject [pathKey=");
+ builder.append(this.pathKey);
+ builder.append(", pceId=");
+ builder.append(Arrays.toString(this.pceId));
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import java.util.Arrays;
+
+public class RROPathKeyWith32PCEIDSubobject extends ReportedRouteSubobject {
+
+ private final int pathKey;
+
+ private final byte[] pceId;
+
+ public RROPathKeyWith32PCEIDSubobject(int pathKey, byte[] pceId) {
+ super();
+ this.pathKey = pathKey;
+ if (pceId == null)
+ throw new IllegalArgumentException("PCE ID can't be null.");
+
+ if (pceId.length != 4)
+ throw new IllegalArgumentException("PCE ID is not 4 bytes long.");
+
+ this.pceId = pceId;
+ }
+
+ public int getPathKey() {
+ return this.pathKey;
+ }
+
+ public byte[] getPceId() {
+ return this.pceId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.pathKey;
+ result = prime * result + Arrays.hashCode(this.pceId);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROPathKeyWith32PCEIDSubobject other = (RROPathKeyWith32PCEIDSubobject) obj;
+ if (this.pathKey != other.pathKey)
+ return false;
+ if (!Arrays.equals(this.pceId, other.pceId))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("RROPathKeyWith32PCEIDSubobject [pathKey=");
+ builder.append(this.pathKey);
+ builder.append(", pceId=");
+ builder.append(Arrays.toString(this.pceId));
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+public abstract class RROProtectionSubobject extends ReportedRouteSubobject {
+ public RROProtectionSubobject() {
+ super();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+
+public class RROProtectionType1Subobject extends RROProtectionSubobject {
+
+ private final boolean secondary;
+
+ private final byte linkFlags;
+
+ /**
+ * @param secondary
+ * @param linkFlags
+ */
+ public RROProtectionType1Subobject(boolean secondary, byte linkFlags) {
+ super();
+ this.secondary = secondary;
+ this.linkFlags = linkFlags;
+ }
+
+ /**
+ * @return the secondary
+ */
+ public boolean isSecondary() {
+ return this.secondary;
+ }
+
+ /**
+ * @return the linkFlags
+ */
+ public byte getLinkFlags() {
+ return this.linkFlags;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.linkFlags;
+ result = prime * result + (this.secondary ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROProtectionType1Subobject other = (RROProtectionType1Subobject) obj;
+ if (this.linkFlags != other.linkFlags)
+ return false;
+ if (this.secondary != other.secondary)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("ProtectionType1Subobject [secondary=");
+ builder.append(this.secondary);
+ builder.append(", linkFlags=");
+ builder.append(this.linkFlags);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+public class RROProtectionType2Subobject extends RROProtectionSubobject {
+ private final boolean secondaryLsp;
+
+ private final boolean protectionLsp;
+
+ private final boolean notification;
+
+ private final boolean operational;
+
+ private final byte lspFlags;
+
+ private final byte linkFlags;
+
+ private final boolean inPlace;
+
+ private final boolean required;
+
+ private final byte segFlags;
+
+ /**
+ * @param secondaryLsp
+ * @param protectionLsp
+ * @param notification
+ * @param operational
+ * @param lspFlags
+ * @param linkFlags
+ * @param inPlace
+ * @param required
+ * @param segFlags
+ */
+ public RROProtectionType2Subobject(boolean secondaryLsp, boolean protectionLsp, boolean notification, boolean operational, byte lspFlags, byte linkFlags,
+ boolean inPlace, boolean required, byte segFlags) {
+ super();
+ this.secondaryLsp = secondaryLsp;
+ this.protectionLsp = protectionLsp;
+ this.notification = notification;
+ this.operational = operational;
+ this.lspFlags = lspFlags;
+ this.linkFlags = linkFlags;
+ this.inPlace = inPlace;
+ this.required = required;
+ this.segFlags = segFlags;
+ }
+
+ /**
+ * @return the secondaryLsp
+ */
+ public boolean isSecondaryLsp() {
+ return this.secondaryLsp;
+ }
+
+ /**
+ * @return the protectionLsp
+ */
+ public boolean isProtectionLsp() {
+ return this.protectionLsp;
+ }
+
+ /**
+ * @return the notification
+ */
+ public boolean isNotification() {
+ return this.notification;
+ }
+
+ /**
+ * @return the operational
+ */
+ public boolean isOperational() {
+ return this.operational;
+ }
+
+ /**
+ * @return the lspFlags
+ */
+ public byte getLspFlags() {
+ return this.lspFlags;
+ }
+
+ /**
+ * @return the linkFlags
+ */
+ public byte getLinkFlags() {
+ return this.linkFlags;
+ }
+
+ /**
+ * @return the inPlace
+ */
+ public boolean isInPlace() {
+ return this.inPlace;
+ }
+
+ /**
+ * @return the required
+ */
+ public boolean isRequired() {
+ return this.required;
+ }
+
+ /**
+ * @return the segFlags
+ */
+ public byte getSegFlags() {
+ return this.segFlags;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.inPlace ? 1231 : 1237);
+ result = prime * result + this.linkFlags;
+ result = prime * result + this.lspFlags;
+ result = prime * result + (this.notification ? 1231 : 1237);
+ result = prime * result + (this.operational ? 1231 : 1237);
+ result = prime * result + (this.protectionLsp ? 1231 : 1237);
+ result = prime * result + (this.required ? 1231 : 1237);
+ result = prime * result + (this.secondaryLsp ? 1231 : 1237);
+ result = prime * result + this.segFlags;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROProtectionType2Subobject other = (RROProtectionType2Subobject) obj;
+ if (this.inPlace != other.inPlace)
+ return false;
+ if (this.linkFlags != other.linkFlags)
+ return false;
+ if (this.lspFlags != other.lspFlags)
+ return false;
+ if (this.notification != other.notification)
+ return false;
+ if (this.operational != other.operational)
+ return false;
+ if (this.protectionLsp != other.protectionLsp)
+ return false;
+ if (this.required != other.required)
+ return false;
+ if (this.secondaryLsp != other.secondaryLsp)
+ return false;
+ if (this.segFlags != other.segFlags)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("ProtectionType1Subobject [secondaryLsp=");
+ builder.append(this.secondaryLsp);
+ builder.append(", protectionLsp=");
+ builder.append(this.protectionLsp);
+ builder.append(", notification=");
+ builder.append(this.notification);
+ builder.append(", operational=");
+ builder.append(this.operational);
+ builder.append(", lspFlags=");
+ builder.append(this.lspFlags);
+ builder.append(", linkFlags=");
+ builder.append(this.linkFlags);
+ builder.append(", inPlace=");
+ builder.append(this.inPlace);
+ builder.append(", required=");
+ builder.append(this.required);
+ builder.append(", segFlags=");
+ builder.append(this.segFlags);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Type 1 Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3209#section-4.1">4.1. Label
+ * Object</a>
+ */
+public class RROType1LabelSubobject extends RROLabelSubobject {
+
+ private final long label;
+
+ public RROType1LabelSubobject(long label, boolean upStream) {
+ super(upStream);
+ this.label = label;
+ }
+
+ public long getLabel() {
+ return this.label;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (int) (this.label ^ (this.label >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROType1LabelSubobject other = (RROType1LabelSubobject) obj;
+ if (this.label != other.label)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("label", this.label);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+
+/**
+ * Structure of unnumbered Iterface Subobject.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3477">Section 4: Signalling
+ * Unnumbered Links in EROs</a>
+ */
+public class RROUnnumberedInterfaceSubobject extends ReportedRouteSubobject {
+ private final UnnumberedInterfaceIdentifier interfaceID;
+ private final IPv4Address routerID;
+
+ /**
+ * Constructs new Unnumbered Interface Subobject.
+ *
+ * @param routerID
+ * IPv4Address
+ * @param interfaceID
+ * UnnumberedInterfaceIdentifier
+ */
+ public RROUnnumberedInterfaceSubobject(final IPv4Address routerID, final UnnumberedInterfaceIdentifier interfaceID) {
+ super();
+ this.routerID = routerID;
+ this.interfaceID = interfaceID;
+ }
+
+ /**
+ * Gets {@link IPv4Address} representation of router ID.
+ *
+ * @return IPv4Address
+ */
+ public IPv4Address getRouterID() {
+ return this.routerID;
+ }
+
+ /**
+ * Gets {@link UnnumberedInterfaceIdentifier} representation of Interface
+ * ID.
+ *
+ * @return UnnumberedInterfaceIdentifier
+ */
+ public UnnumberedInterfaceIdentifier getInterfaceID() {
+ return this.interfaceID;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.interfaceID == null) ? 0 : this.interfaceID.hashCode());
+ result = prime * result + ((this.routerID == null) ? 0 : this.routerID.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROUnnumberedInterfaceSubobject other = (RROUnnumberedInterfaceSubobject) obj;
+ if (this.interfaceID == null) {
+ if (other.interfaceID != null)
+ return false;
+ } else if (!this.interfaceID.equals(other.interfaceID))
+ return false;
+ if (this.routerID == null) {
+ if (other.routerID != null)
+ return false;
+ } else if (!this.routerID.equals(other.routerID))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("RROUnnumberedInterfaceSubobject [interfaceID=");
+ builder.append(this.interfaceID);
+ builder.append(", routerID=");
+ builder.append(this.routerID);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Structure of Generalized Label subobject
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3473#section-2.4">2.4. Waveband
+ * Switching Object </a>
+ */
+public class RROWavebandSwitchingLabelSubobject extends RROLabelSubobject {
+
+ private final long wavebandId;
+
+ private final long startLabel;
+
+ private final long endLabel;
+
+ public RROWavebandSwitchingLabelSubobject(long wavebandId, long startLabel, long endLabel, boolean upStream) {
+ super(upStream);
+ this.wavebandId = wavebandId;
+ this.startLabel = startLabel;
+ this.endLabel = endLabel;
+ }
+
+ public long getWavebandId() {
+ return this.wavebandId;
+ }
+
+ public long getStartLabel() {
+ return this.startLabel;
+ }
+
+ public long getEndLabel() {
+ return this.endLabel;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (int) (this.endLabel ^ (this.endLabel >>> 32));
+ result = prime * result + (int) (this.startLabel ^ (this.startLabel >>> 32));
+ result = prime * result + (int) (this.wavebandId ^ (this.wavebandId >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RROWavebandSwitchingLabelSubobject other = (RROWavebandSwitchingLabelSubobject) obj;
+ if (this.endLabel != other.endLabel)
+ return false;
+ if (this.startLabel != other.startLabel)
+ return false;
+ if (this.wavebandId != other.wavebandId)
+ return false;
+ return true;
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("wavebandId", this.wavebandId);
+ toStringHelper.add("startLabel", this.startLabel);
+ toStringHelper.add("endLabel", this.endLabel);
+ return super.addToStringAttributes(toStringHelper);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+public abstract class ReportedRouteSubobject {
+ protected ReportedRouteSubobject() {
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ return prime;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+
+/**
+ * Structure of Autonomous System Number Subobject. Defined in RFC5521.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ * Object definition</a>
+ */
+public class XROAsNumberSubobject extends ExcludeRouteSubobject {
+
+ private final ASNumber asnumber;
+
+ /**
+ * Constructs new ASNumber Subobject.
+ *
+ * @param asnumber
+ * ASNumber
+ * @param mandatory
+ * boolean
+ */
+ public XROAsNumberSubobject(ASNumber asnumber, boolean mandatory) {
+ super(mandatory);
+ this.asnumber = asnumber;
+ }
+
+ /**
+ * Gets {@link ASNumber}.
+ *
+ * @return ASNumber
+ */
+ public ASNumber getASNumber() {
+ return this.asnumber;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.asnumber == null) ? 0 : this.asnumber.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final XROAsNumberSubobject other = (XROAsNumberSubobject) obj;
+ if (this.asnumber == null) {
+ if (other.asnumber != null)
+ return false;
+ } else if (!this.asnumber.equals(other.asnumber))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("XROAsNumberSubobject [asnumber=");
+ builder.append(this.asnumber);
+ builder.append(", mandatory=");
+ builder.append(this.mandatory);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.Prefix;
+
+/**
+ * Parametrized structure of IP Prefix Subobject. Defined in RFC5521.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ * Object definition</a>
+ *
+ * @param <T>
+ * subtype of Prefix
+ */
+public class XROIPPrefixSubobject<T extends Prefix<?>> extends ExcludeRouteSubobject {
+
+ private final XROSubobjectAttribute attribute;
+
+ private final T prefix;
+
+ /**
+ * Constructs IPPrefix Subobject.
+ *
+ * @param prefix
+ * T
+ * @param mandatory
+ * boolean
+ * @param attribute
+ * XROSubobjectAttribute
+ */
+ public XROIPPrefixSubobject(T prefix, boolean mandatory, XROSubobjectAttribute attribute) {
+ super(mandatory);
+ this.attribute = attribute;
+ this.prefix = prefix;
+ }
+
+ /**
+ * Gets specific {@link Prefix}.
+ *
+ * @return prefix T
+ */
+ public T getPrefix() {
+ return this.prefix;
+ }
+
+ /**
+ * Gets the attribute of the subobject
+ *
+ * @return the attribute
+ */
+ public XROSubobjectAttribute getAttribute() {
+ return this.attribute;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.attribute == null) ? 0 : this.attribute.hashCode());
+ result = prime * result + ((this.prefix == null) ? 0 : this.prefix.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final XROIPPrefixSubobject<?> other = (XROIPPrefixSubobject<?>) obj;
+ if (this.attribute != other.attribute)
+ return false;
+ if (this.prefix == null) {
+ if (other.prefix != null)
+ return false;
+ } else if (!this.prefix.equals(other.prefix))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("XROIPPrefixSubobject [attribute=");
+ builder.append(this.attribute);
+ builder.append(", prefix=");
+ builder.append(this.prefix);
+ builder.append(", mandatory=");
+ builder.append(this.mandatory);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+
+/**
+ * Structure of Shared Risk Link Group Subobject. Defined in RFC5521.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ * Object definition</a>
+ */
+public class XROSRLGSubobject extends ExcludeRouteSubobject {
+
+ private final XROSubobjectAttribute attribute;
+
+ private final SharedRiskLinkGroup srlgId;
+
+ /**
+ * Constructs new Shared Risk Link Group Subobject.
+ *
+ * @param srlgId
+ * SharedRiskLinkGroup
+ * @param mandatory
+ * boolean
+ */
+ public XROSRLGSubobject(SharedRiskLinkGroup srlgId, boolean mandatory) {
+ super(mandatory);
+ this.attribute = XROSubobjectAttribute.SRLG;
+ this.srlgId = srlgId;
+ }
+
+ /**
+ * Gets the Shared Risk Link Group.
+ *
+ * @return SharedRiskLinkGroup
+ */
+ public SharedRiskLinkGroup getSrlgId() {
+ return this.srlgId;
+ }
+
+ /**
+ * Gets the attribute of the subobject
+ *
+ * @return the attribute
+ */
+ public XROSubobjectAttribute getAttribute() {
+ return this.attribute;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("XROSRLGSubobject [attribute=");
+ builder.append(this.attribute);
+ builder.append(", srlgId=");
+ builder.append(this.srlgId.getValue());
+ builder.append(", mandatory=");
+ builder.append(this.mandatory);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.attribute == null) ? 0 : this.attribute.hashCode());
+ result = prime * result + ((this.srlgId == null) ? 0 : this.srlgId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final XROSRLGSubobject other = (XROSRLGSubobject) obj;
+ if (this.attribute != other.attribute)
+ return false;
+ if (this.srlgId == null) {
+ if (other.srlgId != null)
+ return false;
+ } else if (!this.srlgId.equals(other.srlgId))
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+/**
+ * Enumerable for attributes of subobjects. Defined in 5521.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ * Object definition</a>
+ */
+public enum XROSubobjectAttribute {
+ /**
+ * The subobject is to be interpreted as an interface or set of interfaces.
+ */
+ INTERFACE,
+ /**
+ * The subobject is to be interpreted as a node or set of nodes.
+ */
+ NODE,
+ /**
+ * The subobject identifies an SRLG explicitly or indicates all of the SRLGs
+ * associated with the resource or resources identified by the subobject.
+ */
+ SRLG;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.subobject;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+
+/**
+ * Structure of unnumbered Iterface Subobject. Defined in RFC5521.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5521#section-2.1.1">Exclude Route
+ * Object definition</a>
+ */
+public class XROUnnumberedInterfaceSubobject extends ExcludeRouteSubobject {
+
+ private final XROSubobjectAttribute attribute;
+
+ private final UnnumberedInterfaceIdentifier interfaceID;
+
+ private final IPv4Address routerID;
+
+ /**
+ * Constructs new Unnumbered Interface Subobject.
+ *
+ * @param routerID
+ * IPv4Address
+ * @param interfaceID
+ * UnnumberedInterfaceIdentifier
+ * @param mandatory
+ * boolean
+ * @param attribute
+ * XROSubobjectAttribute
+ */
+ public XROUnnumberedInterfaceSubobject(final IPv4Address routerID, final UnnumberedInterfaceIdentifier interfaceID, boolean mandatory,
+ XROSubobjectAttribute attribute) {
+ super(mandatory);
+ this.attribute = attribute;
+ this.routerID = routerID;
+ this.interfaceID = interfaceID;
+ }
+
+ /**
+ * Gets the attribute of the subobject
+ *
+ * @return the attribute
+ */
+ public XROSubobjectAttribute getAttribute() {
+ return this.attribute;
+ }
+
+ /**
+ * Gets {@link IPv4Address} representation of router ID.
+ *
+ * @return IPv4Address
+ */
+ public IPv4Address getRouterID() {
+ return this.routerID;
+ }
+
+ /**
+ * Gets {@link UnnumberedInterfaceIdentifier} representation of Interface
+ * ID.
+ *
+ * @return UnnumberedInterfaceIdentifier
+ */
+ public UnnumberedInterfaceIdentifier getInterfaceID() {
+ return this.interfaceID;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((this.attribute == null) ? 0 : this.attribute.hashCode());
+ result = prime * result + ((this.interfaceID == null) ? 0 : this.interfaceID.hashCode());
+ result = prime * result + ((this.routerID == null) ? 0 : this.routerID.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final XROUnnumberedInterfaceSubobject other = (XROUnnumberedInterfaceSubobject) obj;
+ if (this.attribute != other.attribute)
+ return false;
+ if (this.interfaceID == null) {
+ if (other.interfaceID != null)
+ return false;
+ } else if (!this.interfaceID.equals(other.interfaceID))
+ return false;
+ if (this.routerID == null) {
+ if (other.routerID != null)
+ return false;
+ } else if (!this.routerID.equals(other.routerID))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("XROUnnumberedInterfaceSubobject [attribute=");
+ builder.append(this.attribute);
+ builder.append(", interfaceID=");
+ builder.append(this.interfaceID);
+ builder.append(", routerID=");
+ builder.append(this.routerID);
+ builder.append(", mandatory=");
+ builder.append(this.mandatory);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.pcep.concepts.ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+
+/**
+ * Basic structure of LSP Identifiers TLV.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ * Identifiers TLVs</a>
+ * @param <T>
+ */
+public abstract class AbstractLSPIdentifiersTlv<T extends NetworkAddress<T>> implements LSPIdentifiersTlv<T> {
+ private static final long serialVersionUID = 2386922658825295806L;
+
+ private final T senderAddress;
+
+ private final LSPIdentifier lspID;
+
+ private final TunnelIdentifier tunnelID;
+
+ private final ExtendedTunnelIdentifier<T> extendedTunnelID;
+
+ /**
+ * Construct LSP Identifier TLV with mandatory objects.
+ *
+ * @param senderAddress
+ * @param lspID
+ * @param tunnelID
+ * @param extendedTunnelID
+ */
+ protected AbstractLSPIdentifiersTlv(T senderAddress, LSPIdentifier lspID, TunnelIdentifier tunnelID, ExtendedTunnelIdentifier<T> extendedTunnelID) {
+ if (senderAddress == null)
+ throw new IllegalArgumentException("SenderAdress is mandatory.");
+ this.senderAddress = senderAddress;
+
+ if (lspID == null)
+ throw new IllegalArgumentException("LspID is mandatory.");
+ this.lspID = lspID;
+
+ if (tunnelID == null)
+ throw new IllegalArgumentException("TunnelID is mandatory.");
+ this.tunnelID = tunnelID;
+
+ if (extendedTunnelID == null)
+ throw new IllegalArgumentException("ExtendedTunnelID is mandatory.");
+ this.extendedTunnelID = extendedTunnelID;
+ }
+
+ @Override
+ public T getSenderAddress() {
+ return this.senderAddress;
+ }
+
+ @Override
+ public LSPIdentifier getLspID() {
+ return this.lspID;
+ }
+
+ @Override
+ public TunnelIdentifier getTunnelID() {
+ return this.tunnelID;
+ }
+
+ @Override
+ public ExtendedTunnelIdentifier<T> getExtendedTunnelID() {
+ return this.extendedTunnelID;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.extendedTunnelID == null) ? 0 : this.extendedTunnelID.hashCode());
+ result = prime * result + ((this.lspID == null) ? 0 : this.lspID.hashCode());
+ result = prime * result + ((this.senderAddress == null) ? 0 : this.senderAddress.hashCode());
+ result = prime * result + ((this.tunnelID == null) ? 0 : this.tunnelID.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final AbstractLSPIdentifiersTlv<?> other = (AbstractLSPIdentifiersTlv<?>) obj;
+ if (this.extendedTunnelID == null) {
+ if (other.extendedTunnelID != null)
+ return false;
+ } else if (!this.extendedTunnelID.equals(other.extendedTunnelID))
+ return false;
+ if (this.lspID == null) {
+ if (other.lspID != null)
+ return false;
+ } else if (!this.lspID.equals(other.lspID))
+ return false;
+ if (this.senderAddress == null) {
+ if (other.senderAddress != null)
+ return false;
+ } else if (!this.senderAddress.equals(other.senderAddress))
+ return false;
+ if (this.tunnelID == null) {
+ if (other.tunnelID != null)
+ return false;
+ } else if (!this.tunnelID.equals(other.tunnelID))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("AbstractLSPIdentifiersTlv [senderAddress=");
+ builder.append(this.senderAddress);
+ builder.append(", lspID=");
+ builder.append(this.lspID);
+ builder.append(", tunnelID=");
+ builder.append(this.tunnelID);
+ builder.append(", extendedTunnelID=");
+ builder.append(this.extendedTunnelID);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of No Path Vector TLV.
+ *
+ * @see <a href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-protection-00#section-4.3"
+ * Bypass Tlv</a>
+ */
+public class ByPassTlv implements PCEPTlv {
+
+ private static final long serialVersionUID = 5879892226322401651L;
+
+ private final boolean nodeProtection;
+
+ private final boolean localProtectionInUse;
+
+ private final IPv4Address bypassAddress;
+
+ /**
+ * Constructs ByPass Tlv.
+ *
+ * @param nodeProtection
+ * boolean
+ * @param localProtectionInUse
+ * boolean
+ * @param bypassAddress
+ * IPv4Address
+ */
+ public ByPassTlv(final boolean nodeProtection, final boolean localProtectionInUse,
+ final IPv4Address bypassAddress) {
+ this.nodeProtection = nodeProtection;
+ this.localProtectionInUse = localProtectionInUse;
+ this.bypassAddress = bypassAddress;
+ }
+
+ /**
+ * The N Flag indicates whether the Bypass is used for node-protection.
+ * If the N flag is set to 1, the Bypass is used for node-protection.
+ * If the N flag is 0, the Bypass is used for link-protection.
+ *
+ * @return the nodeProtection
+ */
+ public final boolean isNodeProtection() {
+ return this.nodeProtection;
+ }
+
+ /**
+ * The I Flag indicates that local repair mechanism is in use.
+ *
+ * @return the localProtectionInUse
+ */
+ public final boolean isLocalProtectionInUse() {
+ return this.localProtectionInUse;
+ }
+
+ /**
+ * For link protection, the Bypass IPv4 Address is
+ * the nexthop address of the protected link in the paths of the
+ * protected LSPs. For node protection, the Bypass IPv4 Address is
+ * the node addresses of the protected node.
+ *
+ * @return the bypassAddress
+ */
+ public final IPv4Address getBypassAddress() {
+ return this.bypassAddress;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("ByPassTlv [nodeProtection=");
+ builder.append(this.nodeProtection);
+ builder.append(", localProtectionInUse=");
+ builder.append(this.localProtectionInUse);
+ builder.append(", bypassAddress=");
+ builder.append(this.bypassAddress);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((this.bypassAddress == null) ? 0 : this.bypassAddress.hashCode());
+ result = prime * result + (this.localProtectionInUse ? 1231 : 1237);
+ result = prime * result + (this.nodeProtection ? 1231 : 1237);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof ByPassTlv))
+ return false;
+ final ByPassTlv other = (ByPassTlv) obj;
+ if (this.bypassAddress == null) {
+ if (other.bypassAddress != null)
+ return false;
+ } else if (!this.bypassAddress.equals(other.bypassAddress))
+ return false;
+ if (this.localProtectionInUse != other.localProtectionInUse)
+ return false;
+ if (this.nodeProtection != other.nodeProtection)
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.concepts.ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+
+/**
+ * Specific structure for IPv4 LSP Identifier TLV.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ * Identifiers TLVs</a>
+ */
+public final class IPv4LSPIdentifiersTlv extends AbstractLSPIdentifiersTlv<IPv4Address> {
+ private static final long serialVersionUID = -8249620306610957898L;
+
+ /**
+ * Constructs new IPv4 LSP Identifiers TLV.
+ *
+ * @param senderAddress
+ * {@link IPv4Address}
+ * @param lspID
+ * {@link LSPIdentifier}
+ * @param tunnelID
+ * {@link TunnelIdentifier}
+ * @param extendedTunnelID
+ * {@link ExtendedTunnelIdentifier}
+ */
+ public IPv4LSPIdentifiersTlv(IPv4Address senderAddress, LSPIdentifier lspID, TunnelIdentifier tunnelID,
+ ExtendedTunnelIdentifier<IPv4Address> extendedTunnelID) {
+ super(senderAddress, lspID, tunnelID, extendedTunnelID);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.concepts.ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+
+/**
+ * Specific structure of IPv6 LSP Identifier TLV.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ * Identifiers TLVs</a>
+ */
+public final class IPv6LSPIdentifiersTlv extends AbstractLSPIdentifiersTlv<IPv6Address> {
+ private static final long serialVersionUID = 4188840025844510894L;
+
+ /**
+ * Constructs new IPv6 LSP Identifiers TLV.
+ *
+ * @param senderAddress
+ * {@link IPv6Address}
+ * @param lspID
+ * {@link LSPIdentifier}
+ * @param tunnelID
+ * {@link TunnelIdentifier}
+ * @param extendedTunnelID
+ * {@link ExtendedTunnelIdentifier}
+ */
+ public IPv6LSPIdentifiersTlv(IPv6Address senderAddress, LSPIdentifier lspID, TunnelIdentifier tunnelID,
+ ExtendedTunnelIdentifier<IPv6Address> extendedTunnelID) {
+ super(senderAddress, lspID, tunnelID, extendedTunnelID);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of LSP Cleanup Tlv
+ *
+ * @see <a href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt#section-6.2.1">LSP-CLEANUP TLV</a>
+ */
+public class LSPCleanupTlv implements PCEPTlv {
+
+ private static final long serialVersionUID = -2540695596612553355L;
+
+ private final int timeout;
+
+ /**
+ * Creates new LSP Cleanup Tlv.
+ *
+ */
+ public LSPCleanupTlv(int timeout) {
+ if (timeout < 0 || timeout > Integer.MAX_VALUE)
+ throw new IllegalArgumentException("Timeout (" + timeout + ") cannot be negative or bigger than 2^31 -1.");
+ this.timeout = timeout;
+ }
+
+ /**
+ * @return the timeout
+ */
+ public final int getTimeout() {
+ return this.timeout;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.timeout;
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof LSPCleanupTlv))
+ return false;
+ final LSPCleanupTlv other = (LSPCleanupTlv) obj;
+ if (this.timeout != other.timeout)
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("LSPCleanupTlv [timeout=");
+ builder.append(this.timeout);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+
+/**
+ * Interface defining basic LSPIdentifiersTLV.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.2">LSP
+ * Identifiers TLVs</a>
+ * @param <T>
+ */
+public interface LSPIdentifiersTlv<T extends NetworkAddress<T>> extends PCEPTlv {
+
+ /**
+ * Gets specific senders {@link NetworkAddress}.
+ *
+ * @return T sender network address
+ */
+ public T getSenderAddress();
+
+ /**
+ * Gets {@link LSPIdentifier}.
+ *
+ * @return LSPIdentifier
+ */
+ public LSPIdentifier getLspID();
+
+ /**
+ * Gets {@link TunnelIdentifier}.
+ *
+ * @return TunnelIdentifier
+ */
+ public TunnelIdentifier getTunnelID();
+
+ /**
+ * Gets specific {@link ExtendedTunnelIdentifier}.
+ *
+ *
+ * @return ExtendedTunnelIdentifier
+ */
+ public ExtendedTunnelIdentifier<T> getExtendedTunnelID();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of LSP State DB Version TLV.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.1.2">LSP
+ * State Database Version TLV</a>
+ */
+public class LSPStateDBVersionTlv implements PCEPTlv {
+ private static final long serialVersionUID = 3165807743418210453L;
+ private final long dbVersion;
+
+ /**
+ * Construct new LSP State DB Version TLV.
+ *
+ * @param dbVersion
+ * long
+ */
+ public LSPStateDBVersionTlv(long dbVersion) {
+ this.dbVersion = dbVersion;
+ }
+
+ /**
+ * Gets long representation of DB Version.
+ *
+ * @return long
+ */
+ public long getDbVersion() {
+ return this.dbVersion;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (this.dbVersion ^ (this.dbVersion >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final LSPStateDBVersionTlv other = (LSPStateDBVersionTlv) obj;
+ if (this.dbVersion != other.dbVersion)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("LSPStateDBVersionTlv [dbVersion=");
+ builder.append(this.dbVersion);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+
+/**
+ * Structure of LSP Symbolic Name Tlv.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.1">The
+ * LSP Symbolic Name TLV</a>
+ */
+public class LSPSymbolicNameTlv implements PCEPTlv {
+ private static final long serialVersionUID = 2525226814028262452L;
+ private final LSPSymbolicName symbolicName;
+
+ /**
+ * Constructs new LSP Symbolic Name TLV.
+ *
+ * @param symbolicName
+ * LSPSymbolicName
+ */
+ public LSPSymbolicNameTlv(LSPSymbolicName symbolicName) {
+ this.symbolicName = symbolicName;
+ }
+
+ /**
+ * Gets {@link LSPSymbolicName}.
+ *
+ * @return LSPSymbolicName
+ */
+ public LSPSymbolicName getSymbolicName() {
+ return this.symbolicName;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.symbolicName == null) ? 0 : this.symbolicName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final LSPSymbolicNameTlv other = (LSPSymbolicNameTlv) obj;
+ if (this.symbolicName == null) {
+ if (other.symbolicName != null)
+ return false;
+ } else if (!this.symbolicName.equals(other.symbolicName))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("LSPSymbolicNameTlv [symbolicName=");
+ builder.append(this.symbolicName);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of LSP Update Error TLV.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-7.2.3">LSP
+ * Update Error Code TLV</a>
+ */
+public class LSPUpdateErrorTlv implements PCEPTlv {
+ private static final long serialVersionUID = -6919035417806059716L;
+ private final byte[] errorCode;
+
+ /**
+ * Constructs new LSP Update Error Tlv.
+ *
+ * @param errorCode
+ * byte[]. Size has to be 4 bytes.
+ */
+ public LSPUpdateErrorTlv(byte[] errorCode) {
+ if (errorCode.length != 4)
+ throw new IllegalArgumentException("Update error code has wrong size.");
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * TBD
+ *
+ * @return error code as byte[]
+ */
+ public byte[] getErrorCode() {
+ return this.errorCode;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(this.errorCode);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final LSPUpdateErrorTlv other = (LSPUpdateErrorTlv) obj;
+ if (!Arrays.equals(this.errorCode, other.errorCode))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("LSPUpdateErrorTlv [errorCode=");
+ builder.append(Arrays.toString(this.errorCode));
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of No Path Vector TLV. Extended to conform RFC5557.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.5">NO-PATH Object
+ * [RFC5440]</a> - defined in text
+ * @see <a href="http://tools.ietf.org/html/rfc5557#section-5.7">NO-PATH
+ * Indicator [RFC5557]</a>
+ */
+public class NoPathVectorTlv implements PCEPTlv {
+
+ private static final long serialVersionUID = -4993945476359800826L;
+
+ private final boolean pceUnavailable;
+
+ private final boolean unknownDest;
+
+ private final boolean unknownSrc;
+
+ private final boolean noGCOSolution;
+
+ private final boolean noGCOMigrationPath;
+
+ private final boolean reachablityProblem;
+
+ /**
+ * Constructs new No Path Vector Tlv.
+ *
+ * @param pceUnavailable
+ * boolean
+ * @param unknownDest
+ * boolean
+ * @param unknownSrc
+ * boolean
+ * @param noGCOSolution
+ * boolean
+ * @param noGCOMigrationPath
+ * boolean
+ */
+ public NoPathVectorTlv(boolean pceUnavailable, boolean unknownDest, boolean unknownSrc, boolean noGCOSolution, boolean noGCOMigrationPath,
+ boolean reachabilityProblem) {
+ super();
+ this.pceUnavailable = pceUnavailable;
+ this.unknownDest = unknownDest;
+ this.unknownSrc = unknownSrc;
+ this.noGCOSolution = noGCOSolution;
+ this.noGCOMigrationPath = noGCOMigrationPath;
+ this.reachablityProblem = reachabilityProblem;
+ }
+
+ /**
+ * Returns true if PCE currently unavailable
+ *
+ * @return boolean
+ */
+ public boolean isPceUnavailable() {
+ return this.pceUnavailable;
+ }
+
+ /**
+ * Returns true if unknown destination
+ *
+ * @return boolean
+ */
+ public boolean isUnknownDest() {
+ return this.unknownDest;
+ }
+
+ /**
+ * Returns true if unknown source
+ *
+ * @return boolean
+ */
+ public boolean isUnknownSrc() {
+ return this.unknownSrc;
+ }
+
+ /**
+ * If returns true the PCE indicates that no migration path was found.
+ *
+ * @return boolean
+ */
+ public boolean isNoGCOSolution() {
+ return this.noGCOSolution;
+ }
+
+ /**
+ * If returns true the PCE indicates no feasible solution was found that
+ * meets all the constraints associated with global concurrent path
+ * optimization in the PCRep message
+ *
+ * @return boolean
+ */
+ public boolean isNoGCOMigrationPath() {
+ return this.noGCOMigrationPath;
+ }
+
+ /**
+ * @return the reachablityProblem
+ */
+ public boolean isReachablityProblem() {
+ return this.reachablityProblem;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.noGCOMigrationPath ? 1231 : 1237);
+ result = prime * result + (this.noGCOSolution ? 1231 : 1237);
+ result = prime * result + (this.pceUnavailable ? 1231 : 1237);
+ result = prime * result + (this.reachablityProblem ? 1231 : 1237);
+ result = prime * result + (this.unknownDest ? 1231 : 1237);
+ result = prime * result + (this.unknownSrc ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final NoPathVectorTlv other = (NoPathVectorTlv) obj;
+ if (this.noGCOMigrationPath != other.noGCOMigrationPath)
+ return false;
+ if (this.noGCOSolution != other.noGCOSolution)
+ return false;
+ if (this.pceUnavailable != other.pceUnavailable)
+ return false;
+ if (this.reachablityProblem != other.reachablityProblem)
+ return false;
+ if (this.unknownDest != other.unknownDest)
+ return false;
+ if (this.unknownSrc != other.unknownSrc)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("NoPathVectorTlv [pceUnavailable=");
+ builder.append(this.pceUnavailable);
+ builder.append(", unknownDest=");
+ builder.append(this.unknownDest);
+ builder.append(", unknownSrc=");
+ builder.append(this.unknownSrc);
+ builder.append(", noGCOSolution=");
+ builder.append(this.noGCOSolution);
+ builder.append(", noGCOMigrationPath=");
+ builder.append(this.noGCOMigrationPath);
+ builder.append(", reachablityProblem=");
+ builder.append(this.reachablityProblem);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of Node Identifier TLV.
+ *
+ * @see draft-ietf-pce-stateful-pce-01 (sec. 7.1.3) - NODE_IDENTIFIER_TLV
+ */
+public class NodeIdentifierTlv implements PCEPTlv {
+ private static final long serialVersionUID = -7959631526276210055L;
+ private final byte[] value;
+
+ /**
+ * Constructs new Node Identifier TLV.
+ *
+ * @param value
+ * byte[]
+ */
+ public NodeIdentifierTlv(byte[] value) {
+ if (value == null)
+ throw new IllegalArgumentException("Value is mandatory.");
+ if (value.length == 0)
+ throw new IllegalArgumentException("Value has to be long at least 1 byte.");
+
+ this.value = value;
+ }
+
+ /**
+ * Gets value of Node Identifier TLV as Bytes Array.
+ *
+ * @return byte[]
+ */
+ public byte[] getValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(this.value);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final NodeIdentifierTlv other = (NodeIdentifierTlv) obj;
+ if (!Arrays.equals(this.value, other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("NodeIdentifierTlv [value=");
+ try {
+ builder.append(Charset.forName("UTF-8").newDecoder().decode(ByteBuffer.wrap(this.value)).toString());
+ } catch (final CharacterCodingException e) {
+ builder.append(Arrays.toString(this.value));
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * It MAY be carried within an OPEN object sent by a PCE in an Open message to a
+ * PCEP peer so as to indicate the list of supported objective functions.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5541#section-2.1">OF-List TLV</a>
+ */
+public class OFListTlv implements PCEPTlv {
+ private static final long serialVersionUID = 3409582385994162451L;
+
+ private final List<PCEPOFCodes> ofCodes;
+
+ /**
+ * Constructs new objective functions list tlv
+ *
+ * @param ofCodes
+ * lit of objective functions
+ */
+ public OFListTlv(List<PCEPOFCodes> ofCodes) {
+ super();
+ this.ofCodes = ofCodes;
+ }
+
+ /**
+ * Gets list of objective functions
+ *
+ * @return list of objective functions
+ */
+ public List<PCEPOFCodes> getOfCodes() {
+ return this.ofCodes;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.ofCodes == null) ? 0 : this.ofCodes.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final OFListTlv other = (OFListTlv) obj;
+ if (this.ofCodes == null) {
+ if (other.ofCodes != null)
+ return false;
+ } else if (!this.ofCodes.equals(other.ofCodes))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("OFListTlv [ofCodes=");
+ builder.append(this.ofCodes);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * The Order TLV is an optional TLV in the RP object, that indicates the order
+ * in which the old TE LSP must be removed and the new TE LSP must be setup
+ * during a reoptimization. It is carried in the PCRep message in response to a
+ * reoptimization request.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5557#section-5.4">The Order
+ * Response [RFC5557]</a>
+ */
+public class OrderTlv implements PCEPTlv {
+
+ private static final long serialVersionUID = 4275350142878198146L;
+
+ private final long deleteOrder;
+ private final long setupOrder;
+
+ /**
+ * Constructs new Order tlv with all mandatory objects.
+ *
+ * @param deleteOrder
+ * 32-bit integer
+ * @param setupOrder
+ * 32-bit integer
+ */
+ public OrderTlv(long deleteOrder, long setupOrder) {
+ super();
+ this.deleteOrder = deleteOrder;
+ this.setupOrder = setupOrder;
+ }
+
+ /**
+ * Gets the delete order
+ *
+ * @return the delete order
+ */
+ public long getDeleteOrder() {
+ return this.deleteOrder;
+ }
+
+ /**
+ * Gets the setup order
+ *
+ * @return the setup order
+ */
+ public long getSetupOrder() {
+ return this.setupOrder;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("OrderTlv [deleteOrder=");
+ builder.append(this.deleteOrder);
+ builder.append(", setupOrder=");
+ builder.append(this.setupOrder);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (this.deleteOrder ^ (this.deleteOrder >>> 32));
+ result = prime * result + (int) (this.setupOrder ^ (this.setupOrder >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final OrderTlv other = (OrderTlv) obj;
+ if (this.deleteOrder != other.deleteOrder)
+ return false;
+ if (this.setupOrder != other.setupOrder)
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of Overloaded Duratioon Tlv.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.14">NOTIFICATION
+ * Object</a> - defined in text
+ */
+public class OverloadedDurationTlv implements PCEPTlv {
+ private static final long serialVersionUID = -5829314427598008054L;
+ private final int value;
+
+ /**
+ * Construct new Overloaded Duration Tlv.
+ *
+ * @param value
+ * int
+ */
+ public OverloadedDurationTlv(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets Integer representation of Overloade Duration Value.
+ *
+ * @return int
+ */
+ public int getValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.value;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final OverloadedDurationTlv other = (OverloadedDurationTlv) obj;
+ if (this.value != other.value)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("OverloadedDurationTlv [value=");
+ builder.append(this.value);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of P2MP Capability Tlv.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc6006#section-3.1.2">3.1.2. Open
+ * Message Extension [RFC6006]</a>
+ */
+public class P2MPCapabilityTlv implements PCEPTlv {
+ private static final long serialVersionUID = -7959631526276210055L;
+
+ private final int value;
+
+ /**
+ * Constructs new P2MP Capability Tlv.
+ */
+ public P2MPCapabilityTlv(int value) {
+ if (value < 0 || value > 65535)
+ throw new IllegalArgumentException("Value (" + value + ") cannot be negative or bigger than 2^16 -1.");
+
+ this.value = value;
+ }
+
+ /**
+ * Constructs new P2MP Capability Tlv, with value defaultly set to zero as
+ * mentioned in RFC6006.
+ */
+ public P2MPCapabilityTlv() {
+ this.value = 0;
+ }
+
+ /**
+ * Gets integer value of P2MP Capability Tlv.
+ *
+ * @return int
+ */
+ public int getValue() {
+ return this.value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.value;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final P2MPCapabilityTlv other = (P2MPCapabilityTlv) obj;
+ if (this.value != other.value)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("P2MPCapablityTlv [value=");
+ builder.append(this.value);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of PCE Stateful Capability Tlv.
+ *
+ * @see <a
+ * href="http://tools.ietf.org/html/draft-crabbe-pce-stateful-pce-02#section-8.6">STATEFUL-PCE-CAPABILITY
+ * TLV</a>
+ * @see <a
+ * href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt#section-4.1">Stateful PCE Capability
+ * TLV</a>
+ *
+ */
+public class PCEStatefulCapabilityTlv implements PCEPTlv {
+
+ private static final long serialVersionUID = 5567589958323130325L;
+
+ private final boolean update;
+
+ private final boolean versioned;
+
+ private final boolean instantiated;
+
+ /**
+ * Constructs PCE Stateful Capability Tlv
+ *
+ * @param update
+ * boolean
+ * @param versioned
+ * boolean
+ */
+ public PCEStatefulCapabilityTlv(boolean instantiated, boolean update, boolean versioned) {
+ this.instantiated = instantiated;
+ this.update = update;
+ this.versioned = versioned;
+ }
+
+ /**
+ * Setting of Instantiated flag.
+ *
+ * @return boolean
+ */
+ public boolean isInstantiated() {
+ return this.instantiated;
+ }
+
+ /**
+ * Setting of Update flag.
+ *
+ * @return boolean
+ */
+ public boolean isUpdate() {
+ return this.update;
+ }
+
+ /**
+ * Setting of Versioned flag.
+ *
+ * @return boolean
+ */
+ public boolean isVersioned() {
+ return this.versioned;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.instantiated ? 1231 : 1237);
+ result = prime * result + (this.update ? 1231 : 1237);
+ result = prime * result + (this.versioned ? 1231 : 1237);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof PCEStatefulCapabilityTlv))
+ return false;
+ final PCEStatefulCapabilityTlv other = (PCEStatefulCapabilityTlv) obj;
+ if (this.instantiated != other.instantiated)
+ return false;
+ if (this.update != other.update)
+ return false;
+ if (this.versioned != other.versioned)
+ return false;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEStatefulCapabilityTlv [update=");
+ builder.append(this.update);
+ builder.append(", versioned=");
+ builder.append(this.versioned);
+ builder.append(", instantiated=");
+ builder.append(this.instantiated);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.concepts.NetworkAddress;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of RSVP Error Spec Tlv.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc2205">Apendix A.5: ERROR_SPEC
+ * Class</a>
+ * @param <T>
+ */
+public class RSVPErrorSpecTlv<T extends NetworkAddress<T>> implements PCEPTlv {
+ private static final long serialVersionUID = 3948879942549682846L;
+
+ private final T errorNodeAddress;
+
+ private final boolean inPlace;
+
+ private final boolean guilty;
+
+ private final int errorCode;
+
+ private final int errorValue;
+
+ /**
+ *
+ * Constructs new RSVP Error Spec Tlv.
+ *
+ * @param errorNodeAddress
+ * T
+ * @param inPlace
+ * boolean
+ * @param guilty
+ * boolean
+ * @param errorCode
+ * int
+ * @param errorValue
+ * int
+ */
+ public RSVPErrorSpecTlv(T errorNodeAddress, boolean inPlace, boolean guilty, int errorCode, int errorValue) {
+ this.errorNodeAddress = errorNodeAddress;
+ this.inPlace = inPlace;
+ this.guilty = guilty;
+ this.errorCode = errorCode;
+ this.errorValue = errorValue;
+ }
+
+ /**
+ * Gets {@link NetworkAddress} of Error Node.
+ *
+ * @return T
+ */
+ public T getErrorNodeAddress() {
+ return this.errorNodeAddress;
+ }
+
+ /**
+ * Setting of InPlace flag.
+ *
+ * @return boolean
+ */
+ public boolean isInPlace() {
+ return this.inPlace;
+ }
+
+ /**
+ * Setting of Guilty flag.
+ *
+ * @return boolean
+ */
+ public boolean isGuilty() {
+ return this.guilty;
+ }
+
+ /**
+ * Gets int representation of Error Code.
+ *
+ * @return int
+ */
+ public int getErrorCode() {
+ return this.errorCode;
+ }
+
+ /**
+ * Gets int representation of Error Value.
+ *
+ * @return int
+ */
+ public int getErrorValue() {
+ return this.errorValue;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.errorCode;
+ result = prime * result + ((this.errorNodeAddress == null) ? 0 : this.errorNodeAddress.hashCode());
+ result = prime * result + this.errorValue;
+ result = prime * result + (this.guilty ? 1231 : 1237);
+ result = prime * result + (this.inPlace ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final RSVPErrorSpecTlv<?> other = (RSVPErrorSpecTlv<?>) obj;
+ if (this.errorCode != other.errorCode)
+ return false;
+ if (this.errorNodeAddress == null) {
+ if (other.errorNodeAddress != null)
+ return false;
+ } else if (!this.errorNodeAddress.equals(other.errorNodeAddress))
+ return false;
+ if (this.errorValue != other.errorValue)
+ return false;
+ if (this.guilty != other.guilty)
+ return false;
+ if (this.inPlace != other.inPlace)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("RSVPErrorSpecTlv [errorNodeAddress=");
+ builder.append(this.errorNodeAddress);
+ builder.append(", inPlace=");
+ builder.append(this.inPlace);
+ builder.append(", guilty=");
+ builder.append(this.guilty);
+ builder.append(", errorCode=");
+ builder.append(this.errorCode);
+ builder.append(", errorValue=");
+ builder.append(this.errorValue);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.tlv;
+
+import org.opendaylight.protocol.pcep.PCEPTlv;
+
+/**
+ * Structure of Request Missing Tlv.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc5440#section-7.15">PCEP-ERROR
+ * Object</a> - defined in text (Error-type=7)
+ */
+public class ReqMissingTlv implements PCEPTlv {
+ private static final long serialVersionUID = -3910927830017195746L;
+ private final long requestID;
+
+ /**
+ * Constructs new Request Missing Tlv.
+ *
+ * @param requestID
+ * long
+ */
+ public ReqMissingTlv(long requestID) {
+ this.requestID = requestID;
+ }
+
+ /**
+ * gets long representation of Requested ID.
+ *
+ * @return long
+ */
+ public long getRequestID() {
+ return this.requestID;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (this.requestID ^ (this.requestID >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final ReqMissingTlv other = (ReqMissingTlv) obj;
+ if (this.requestID != other.requestID)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("ReqMissingTlv [requestID=");
+ builder.append(this.requestID);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ *
+ */
+public class APITest {
+
+ @Test
+ public void testDeserializerException() {
+ final PCEPDeserializerException e = new PCEPDeserializerException("Some error message.");
+ assertEquals("Some error message.", e.getErrorMessage());
+
+ final PCEPDeserializerException e1 = new PCEPDeserializerException(new IllegalArgumentException(), "Some error message.");
+ assertEquals("Some error message.", e1.getErrorMessage());
+ assertTrue(e1.getCause() instanceof IllegalArgumentException);
+ }
+
+ @Test
+ public void testDocumentedException() throws PCEPDocumentedException {
+ final PCEPDocumentedException de = new PCEPDocumentedException("", PCEPErrors.C_BIT_SET);
+ assertEquals(PCEPErrors.C_BIT_SET, de.getError());
+ }
+
+ @Test
+ public void testPCEPMessage() {
+ final List<PCEPObject> objs = new ArrayList<PCEPObject>();
+ objs.add(new PCEPErrorObject(PCEPErrors.ATTEMPT_2ND_SESSION));
+ final PCEPMessage msg1 = new PCEPMessage(objs) {
+ private static final long serialVersionUID = 1L;
+ };
+ final PCEPMessage msg2 = new PCEPMessage(objs) {
+ private static final long serialVersionUID = 1L;
+ };
+
+ assertNotSame(msg1, msg2); //not same because they are anonymous classes
+ assertEquals(msg1.hashCode(), msg2.hashCode());
+ assertEquals(msg1.toString(), msg2.toString());
+ }
+
+ @Test
+ public void testPCEPObject() {
+ final PCEPObject obj1 = new PCEPObject(true, false) {
+ };
+ final PCEPObject obj2 = new PCEPErrorObject(PCEPErrors.CANNOT_PROCESS_STATE_REPORT);
+ final PCEPObject obj4 = new PCEPObject(true, false) {
+ };
+
+ assertNotSame(obj1, obj2);
+ assertNotSame(obj1, obj4);
+ assertEquals(obj1.hashCode(), obj4.hashCode());
+ assertEquals(obj1.toString(), obj4.toString());
+
+ }
+
+ @Test
+ public void testSubobject() {
+ final ExplicitRouteSubobject sub1 = new EROAsNumberSubobject(new ASNumber(100), true);
+ final ExplicitRouteSubobject sub2 = new ExplicitRouteSubobject(false) {
+ };
+ final ExplicitRouteSubobject sub3 = new ExplicitRouteSubobject(false) {
+ };
+ final ExplicitRouteSubobject sub4 = new EROAsNumberSubobject(new ASNumber(100), true);
+
+ assertNotSame(sub1, sub2);
+ assertNotSame(sub2, sub3);
+ assertEquals(sub1, sub4);
+ assertNotSame(sub2, sub3);
+ assertEquals(sub1.hashCode(), sub4.hashCode());
+ assertEquals(sub2.toString(), sub3.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.api;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.concepts.AbstractExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.AggregateBandwidthConsumptionMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeIGPCostMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeTECostMetric;
+import org.opendaylight.protocol.pcep.concepts.IPv4ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.IPv6ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.concepts.MostLoadedLinkLoadMetric;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+
+public class ConceptsTest {
+
+ @Test
+ public void testConcepts() throws UnknownHostException {
+ final AbstractExtendedTunnelIdentifier<IPv4Address> t1 = new AbstractExtendedTunnelIdentifier<IPv4Address>(new IPv4Address(
+ InetAddress.getByName("127.0.0.1"))) {
+ private static final long serialVersionUID = 445350555352830607L;
+ };
+
+ final AbstractExtendedTunnelIdentifier<IPv4Address> t2 = new AbstractExtendedTunnelIdentifier<IPv4Address>(new IPv4Address(
+ InetAddress.getByName("127.0.0.2"))) {
+ private static final long serialVersionUID = 572633522583009640L;
+ };
+
+ final AbstractExtendedTunnelIdentifier<IPv4Address> t3 = new AbstractExtendedTunnelIdentifier<IPv4Address>(new IPv4Address(
+ InetAddress.getByName("127.0.0.1"))) {
+ private static final long serialVersionUID = 445350555352830607L;
+ };
+
+ assertNotSame(t1, t2);
+ assertEquals(-1, t1.compareTo(t2));
+ assertEquals(t1.hashCode(), t3.hashCode());
+ assertEquals(t1.toString(), t3.toString());
+
+ final IPv4ExtendedTunnelIdentifier v4 = new IPv4ExtendedTunnelIdentifier(new IPv4Address(InetAddress.getByName("127.0.0.1")));
+ final IPv6ExtendedTunnelIdentifier v6 = new IPv6ExtendedTunnelIdentifier(new IPv6Address(InetAddress.getByName("2001:db8:85a3::8a2e:370:7333")));
+ assertTrue(v4 instanceof AbstractExtendedTunnelIdentifier);
+ assertTrue(v6 instanceof AbstractExtendedTunnelIdentifier);
+
+ final LSPIdentifier id1 = new LSPIdentifier(new byte[] { 1, 2 });
+ final LSPIdentifier id2 = new LSPIdentifier(new byte[] { 1, 3 });
+ final LSPIdentifier id3 = new LSPIdentifier(new byte[] { 1, 3 });
+
+ assertNotSame(id1, id2);
+ assertNotSame(id1.getLspId(), id2.getLspId());
+ assertEquals(id3.toString(), id2.toString());
+
+ final LSPSymbolicName n1 = new LSPSymbolicName(new byte[] { 5 });
+ final LSPSymbolicName n2 = new LSPSymbolicName(new byte[] { 6, 3 });
+ final LSPSymbolicName n3 = new LSPSymbolicName(new byte[] { 5 });
+ assertNotSame(n1.getSymbolicName(), n2.getSymbolicName());
+ assertEquals(n1, n3);
+ assertEquals(n1.toString(), n3.toString());
+
+ final TunnelIdentifier ti1 = new TunnelIdentifier(new byte[] { 2, 4 });
+ final TunnelIdentifier ti2 = new TunnelIdentifier(new byte[] { 2, 4 });
+ assertArrayEquals(ti1.getBytes(), ti2.getBytes());
+ assertEquals(ti1, ti2);
+ assertEquals(ti1.toString(), ti2.toString());
+
+ final UnnumberedInterfaceIdentifier u1 = new UnnumberedInterfaceIdentifier(3000);
+ final UnnumberedInterfaceIdentifier u2 = new UnnumberedInterfaceIdentifier(4000);
+ final UnnumberedInterfaceIdentifier u3 = new UnnumberedInterfaceIdentifier(3000);
+
+ assertEquals(-1, u1.compareTo(u2));
+ assertEquals(u1, u3);
+ assertEquals(u1.hashCode(), u3.hashCode());
+ assertEquals(u1.getInterfaceId(), u3.getInterfaceId());
+ assertEquals(u1.toString(), u3.toString());
+
+ final CumulativeIGPCostMetric cigp1 = new CumulativeIGPCostMetric(3000);
+ final CumulativeIGPCostMetric cigp2 = new CumulativeIGPCostMetric(4000);
+ final CumulativeIGPCostMetric cigp3 = new CumulativeIGPCostMetric(3000);
+ try {
+ new CumulativeIGPCostMetric(-1);
+ fail("Expected exception but no thrown.");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ assertEquals(-1, cigp1.compareTo(cigp2));
+ assertEquals(cigp1, cigp3);
+ assertEquals(cigp1.hashCode(), cigp3.hashCode());
+ assertEquals(cigp1.getValue(), cigp3.getValue());
+ assertEquals(cigp1.toString(), cigp3.toString());
+
+ final CumulativeTECostMetric cte1 = new CumulativeTECostMetric(3000);
+ final CumulativeTECostMetric cte2 = new CumulativeTECostMetric(4000);
+ final CumulativeTECostMetric cte3 = new CumulativeTECostMetric(3000);
+
+ assertEquals(-1, cte1.compareTo(cte2));
+ assertEquals(cte1, cte3);
+ assertEquals(cte1.hashCode(), cte3.hashCode());
+ assertEquals(cte1.getValue(), cte3.getValue());
+ assertEquals(cte1.toString(), cte3.toString());
+ try {
+ new CumulativeTECostMetric(-1);
+ fail("Expected exception but no thrown.");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ final AggregateBandwidthConsumptionMetric agg1 = new AggregateBandwidthConsumptionMetric(3000);
+ final AggregateBandwidthConsumptionMetric agg2 = new AggregateBandwidthConsumptionMetric(4000);
+ final AggregateBandwidthConsumptionMetric agg3 = new AggregateBandwidthConsumptionMetric(3000);
+
+ assertEquals(-1, agg1.compareTo(agg2));
+ assertEquals(agg1, agg3);
+ assertEquals(agg1.hashCode(), agg3.hashCode());
+ assertEquals(agg1.getValue(), agg3.getValue());
+ assertEquals(agg1.toString(), agg3.toString());
+ try {
+ new AggregateBandwidthConsumptionMetric(-1);
+ fail("Expected exception but no thrown.");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ final MostLoadedLinkLoadMetric mlm1 = new MostLoadedLinkLoadMetric(3000);
+ final MostLoadedLinkLoadMetric mlm2 = new MostLoadedLinkLoadMetric(4000);
+ final MostLoadedLinkLoadMetric mlm3 = new MostLoadedLinkLoadMetric(3000);
+
+ assertEquals(-1, mlm1.compareTo(mlm2));
+ assertEquals(mlm1, mlm3);
+ assertEquals(mlm1.hashCode(), mlm3.hashCode());
+ assertEquals(mlm1.getValue(), mlm3.getValue());
+ assertEquals(mlm1.toString(), mlm3.toString());
+ try {
+ new MostLoadedLinkLoadMetric(-1);
+ fail("Expected exception but no thrown.");
+ } catch (final IllegalArgumentException e) {
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+
+public class MessagesTest {
+
+ @Test
+ public void errorMessageTest() {
+ final List<PCEPErrorObject> errorObjs = new ArrayList<PCEPErrorObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPErrorObject(PCEPErrors.ATTEMPT_2ND_SESSION));
+ this.add(new PCEPErrorObject(PCEPErrors.ATTEMPT_2ND_SESSION));
+ }
+ };
+ final List<CompositeErrorObject> errors = new ArrayList<CompositeErrorObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeErrorObject(errorObjs));
+ }
+ };
+
+ final List<?> objs = new ArrayList<Object>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeErrorObject(errorObjs));
+ this.add(new PCEPErrorObject(PCEPErrors.BANDWIDTH_MISSING));
+ }
+ };
+
+ final PCEPErrorMessage m = new PCEPErrorMessage(new PCEPOpenObject(10, 10, 1), errorObjs, errors);
+ final PCEPErrorMessage m2 = new PCEPErrorMessage(new PCEPOpenObject(10, 10, 1), errorObjs, errors);
+ final PCEPErrorMessage m3 = new PCEPErrorMessage(objs);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getOpenObject(), m2.getOpenObject());
+ assertEquals(m.getErrors(), m2.getErrors());
+ assertEquals(m.getErrorObjects(), m2.getErrorObjects());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void closeMessageTest() {
+ final PCEPCloseMessage m = new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER));
+ final PCEPCloseMessage m2 = new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER));
+ final PCEPCloseMessage m3 = new PCEPCloseMessage(new PCEPCloseObject(Reason.MALFORMED_MSG));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCloseObject(), m2.getCloseObject());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+
+ new PCEPCloseMessage(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void openMessageTest() {
+ final PCEPOpenMessage m = new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1));
+ final PCEPOpenMessage m2 = new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1));
+ final PCEPOpenMessage m3 = new PCEPOpenMessage(new PCEPOpenObject(5, 5, 1));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getOpenObject(), m2.getOpenObject());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER))));
+ assertTrue(m.equals(m));
+
+ new PCEPOpenMessage(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void keepAliveMessageTest() {
+ final PCEPKeepAliveMessage m = new PCEPKeepAliveMessage();
+ final PCEPKeepAliveMessage m2 = new PCEPKeepAliveMessage();
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(new PCEPCloseMessage(new PCEPCloseObject(Reason.EXP_DEADTIMER))));
+ assertTrue(m.equals(m));
+
+ new PCEPOpenMessage(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void notifyMessageTest() {
+ final List<CompositeNotifyObject> notifications = new ArrayList<CompositeNotifyObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeNotifyObject(new ArrayList<PCEPNotificationObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPNotificationObject((short) 2, (short) 3));
+ }
+ }));
+ }
+ };
+
+ final PCEPNotificationMessage m = new PCEPNotificationMessage(notifications);
+ final PCEPNotificationMessage m2 = new PCEPNotificationMessage(notifications);
+ final PCEPNotificationMessage m3 = new PCEPNotificationMessage(new ArrayList<CompositeNotifyObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeNotifyObject(new ArrayList<PCEPNotificationObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPNotificationObject((short) 2, (short) 5));
+ }
+ }));
+ }
+ });
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getNotifications(), m2.getNotifications());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+
+ new PCEPNotificationMessage(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void replyMessageTest() {
+ final List<CompositeResponseObject> replies = new ArrayList<CompositeResponseObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false, (short) 1, 1, true,
+ false)));
+ }
+ };
+
+ final PCEPReplyMessage m = new PCEPReplyMessage(replies);
+ final PCEPReplyMessage m2 = new PCEPReplyMessage(replies);
+ final PCEPReplyMessage m3 = new PCEPReplyMessage(new ArrayList<CompositeResponseObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, false, true, false, false, false, (short) 2, 1, false,
+ false)));
+ }
+ });
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getResponses(), m2.getResponses());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+
+ new PCEPReplyMessage(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void reportMessageTest() {
+ final List<CompositeStateReportObject> reports = new ArrayList<CompositeStateReportObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeStateReportObject(new PCEPLspObject(1, true, true, true, true)));
+ }
+ };
+
+ final PCEPReportMessage m = new PCEPReportMessage(reports);
+ final PCEPReportMessage m2 = new PCEPReportMessage(reports);
+ final PCEPReportMessage m3 = new PCEPReportMessage(new ArrayList<CompositeStateReportObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeStateReportObject(new PCEPLspObject(5, false, true, true, true)));
+ }
+ });
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getStateReports(), m2.getStateReports());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+
+ new PCEPReportMessage(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void requestMessageTest() {
+ final List<CompositeRequestObject> reports = new ArrayList<CompositeRequestObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeRequestObject(
+ new PCEPRequestParameterObject(true, true, true, true, true, false, false, false, (short) 5, 5, true, true),
+ new PCEPEndPointsObject<IPv4Address>(
+ new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 }),
+ new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 }))));
+ }
+ };
+
+ final PCEPRequestMessage m = new PCEPRequestMessage(reports);
+ final PCEPRequestMessage m2 = new PCEPRequestMessage(reports);
+ final PCEPRequestMessage m3 = new PCEPRequestMessage(new ArrayList<CompositeRequestObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeRequestObject(
+ new PCEPRequestParameterObject(true, true, true, false, true, false, false, false, (short) 5, 5, true, true),
+ new PCEPEndPointsObject<IPv4Address>(
+ new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }),
+ new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 }))));
+ }
+ });
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getSvecObjects(), m2.getSvecObjects());
+ assertEquals(m.getRequests(), m2.getRequests());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+
+ new PCEPRequestMessage(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void updateRequestMessageTest() {
+ final List<CompositeUpdateRequestObject> reports = new ArrayList<CompositeUpdateRequestObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, true, true, true)));
+ }
+ };
+
+ final PCEPUpdateRequestMessage m = new PCEPUpdateRequestMessage(reports);
+ final PCEPUpdateRequestMessage m2 = new PCEPUpdateRequestMessage(reports);
+ final PCEPUpdateRequestMessage m3 = new PCEPUpdateRequestMessage(new ArrayList<CompositeUpdateRequestObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeUpdateRequestObject(new PCEPLspObject(5, true, true, true, true)));
+ }
+ });
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getUpdateRequests(), m2.getUpdateRequests());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+
+ new PCEPUpdateRequestMessage(null);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.CompositePathObject;
+import org.opendaylight.protocol.pcep.object.CompositeReplySvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestSvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.CompositeRptPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPoints;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import com.google.common.collect.Lists;
+
+/**
+ *
+ */
+public class ObjectsTest {
+
+ @Test
+ public void compositeErrorObjectTest() {
+
+ final List<PCEPErrorObject> errorObjects = new ArrayList<PCEPErrorObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPErrorObject(PCEPErrors.ATTEMPT_2ND_SESSION));
+ }
+ };
+
+ final List<PCEPRequestParameterObject> errorParams = new ArrayList<PCEPRequestParameterObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false, (short) 1, 1, true, true));
+ }
+ };
+ final CompositeErrorObject m = new CompositeErrorObject(errorParams, errorObjects);
+ final CompositeErrorObject m2 = new CompositeErrorObject(errorParams, errorObjects);
+ final CompositeErrorObject m3 = new CompositeErrorObject(errorObjects);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getErrors(), m2.getErrors());
+ assertEquals(m.getRequestParameters(), m2.getRequestParameters());
+ assertEquals(m, CompositeErrorObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositeNotifyObjectTest() {
+
+ final List<PCEPNotificationObject> notifications = new ArrayList<PCEPNotificationObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPNotificationObject((short) 2, (short) 3));
+ }
+ };
+
+ final List<PCEPRequestParameterObject> reqParams = new ArrayList<PCEPRequestParameterObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false, (short) 1, 1, true, true));
+ }
+ };
+ final CompositeNotifyObject m = new CompositeNotifyObject(reqParams, notifications);
+ final CompositeNotifyObject m2 = new CompositeNotifyObject(reqParams, notifications);
+ final CompositeNotifyObject m3 = new CompositeNotifyObject(notifications);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getNotificationObjects(), m2.getNotificationObjects());
+ assertEquals(m.getRequestParameters(), m2.getRequestParameters());
+ assertEquals(m, CompositeNotifyObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositePathObjectTest() {
+
+ final List<ExplicitRouteSubobject> subobjects = new ArrayList<ExplicitRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+ }
+ };
+
+ final CompositePathObject m = new CompositePathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2,
+ true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ }, new PCEPIncludeRouteObject(subobjects, true, true));
+ final CompositePathObject m2 = new CompositePathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2,
+ true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ }, new PCEPIncludeRouteObject(subobjects, true, true));
+ final CompositePathObject m3 = new CompositePathObject(new PCEPExplicitRouteObject(subobjects, false));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getBandwidth(), m2.getBandwidth());
+ assertEquals(m.getExcludedRoute(), m2.getExcludedRoute());
+ assertEquals(m.getIncludeRoute(), m2.getIncludeRoute());
+ assertEquals(m.getLspa(), m2.getLspa());
+ assertEquals(m.getMetrics(), m2.getMetrics());
+ assertEquals(m, CompositePathObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositeRptPathObjectTest() {
+
+ final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new EROUnnumberedInterfaceSubobject(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new UnnumberedInterfaceIdentifier(2), true));
+ this.add(new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(
+ new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22), false));
+ }
+ };
+
+ final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new RROUnnumberedInterfaceSubobject(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new UnnumberedInterfaceIdentifier(2)));
+ this.add(new RROIPAddressSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(
+ new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22), true, false));
+ }
+ };
+
+ final CompositeRptPathObject m = new CompositeRptPathObject(new PCEPExplicitRouteObject(eroSubobjects, false), new PCEPLspaObject(2, 2, 2, (short) 2,
+ (short) 2, true, true, true, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+ new PCEPReportedRouteObject(rroSubobjects, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ });
+ final CompositeRptPathObject m2 = new CompositeRptPathObject(new PCEPExplicitRouteObject(eroSubobjects, false), new PCEPLspaObject(2, 2, 2, (short) 2,
+ (short) 2, true, true, true, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+ new PCEPReportedRouteObject(rroSubobjects, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ });
+ final CompositePathObject m3 = new CompositePathObject(new PCEPExplicitRouteObject(eroSubobjects, false));
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getBandwidth(), m2.getBandwidth());
+ assertEquals(m.getExcludedRoute(), m2.getExcludedRoute());
+ assertEquals(m.getLspa(), m2.getLspa());
+ assertEquals(m.getMetrics(), m2.getMetrics());
+ assertEquals(m, CompositeRptPathObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositeUpdPathObjectTest() {
+
+ final List<ExplicitRouteSubobject> subobjects = new ArrayList<ExplicitRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+ }
+ };
+
+ final CompositeUpdPathObject m = new CompositeUpdPathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2,
+ (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+ new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ });
+ final CompositeUpdPathObject m2 = new CompositeUpdPathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2,
+ (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+ new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ });
+ final CompositeUpdPathObject m3 = new CompositeUpdPathObject(new PCEPExplicitRouteObject(subobjects, false));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getBandwidth(), m2.getBandwidth());
+ assertEquals(m.getExcludedRoute(), m2.getExcludedRoute());
+ assertEquals(m.getLspa(), m2.getLspa());
+ assertEquals(m.getMetrics(), m2.getMetrics());
+ assertEquals(m, CompositeUpdPathObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositeRequestedObjectTest() {
+
+ final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+ }
+ };
+
+ final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new RROAsNumberSubobject(new ASNumber(2555)));
+ }
+ };
+
+ final CompositeRequestObject m = new CompositeRequestObject(new PCEPRequestParameterObject(true, true, true, true, true, true, false, false, false,
+ (short) 1, 1, new ArrayList<PCEPTlv>() {
+ private static final long serialVersionUID = 1L;
+ {
+ this.add(new OrderTlv(1L, 2L));
+ }
+ }, true, true), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 })), new PCEPClassTypeObject((short) 2), new PCEPLspObject((short) 1, true, true, true,
+ true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth(
+ (float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ }, new PCEPReportedRouteObject(rroSubobjects, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+ new PCEPIncludeRouteObject(eroSubobjects, true, true), new PCEPLoadBalancingObject(2, new Bandwidth((float) 0.2), true));
+ final CompositeRequestObject m2 = new CompositeRequestObject(new PCEPRequestParameterObject(true, true, true, true, true, true, false, false, false,
+ (short) 1, 1, new ArrayList<PCEPTlv>() {
+ private static final long serialVersionUID = 1L;
+ {
+ this.add(new OrderTlv(1L, 2L));
+ }
+ }, true, true), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 })), new PCEPClassTypeObject((short) 2), new PCEPLspObject((short) 1, true, true, true,
+ true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth(
+ (float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ }, new PCEPReportedRouteObject(rroSubobjects, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true),
+ new PCEPIncludeRouteObject(eroSubobjects, true, true), new PCEPLoadBalancingObject(2, new Bandwidth((float) 0.2), true));
+ final CompositeRequestObject m3 = new CompositeRequestObject(new PCEPRequestParameterObject(true, true, true, true, true, true, false, false, false,
+ (short) 1, 1, new ArrayList<PCEPTlv>() {
+ private static final long serialVersionUID = 1L;
+ {
+ this.add(new OrderTlv(1L, 2L));
+ }
+ }, true, true), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 1 })));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getBandwidth(), m2.getBandwidth());
+ assertEquals(m.getLspa(), m2.getLspa());
+ assertEquals(m.getMetrics(), m2.getMetrics());
+ assertEquals(m.getClassType(), m2.getClassType());
+ assertEquals(m.getEndPoints(), m2.getEndPoints());
+ assertEquals(m.getIncludeRoute(), m2.getIncludeRoute());
+ assertEquals(m.getLsp(), m2.getLsp());
+ assertEquals(m.getRroBandwidth(), m2.getRroBandwidth());
+ assertEquals(m, CompositeRequestObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositeResponseObjectTest() {
+
+ final List<ExplicitRouteSubobject> subobjects = new ArrayList<ExplicitRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+ }
+ };
+
+ final List<CompositePathObject> paths = new ArrayList<CompositePathObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositePathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true,
+ true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ }, new PCEPIncludeRouteObject(subobjects, true, true)));
+ }
+ };
+
+ final CompositeResponseObject m = new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false,
+ (short) 1, 1, true, true), new PCEPNoPathObject((short) 2, true, false), new PCEPLspObject((short) 1, true, true, true, true),
+ new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222),
+ true, true), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ }, new PCEPIncludeRouteObject(subobjects, true, true), paths);
+ final CompositeResponseObject m2 = new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false,
+ (short) 1, 1, true, true), new PCEPNoPathObject((short) 2, true, false), new PCEPLspObject((short) 1, true, true, true, true),
+ new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true, true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222),
+ true, true), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ }, new PCEPIncludeRouteObject(subobjects, true, true), paths);
+ final CompositeResponseObject m3 = new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, true, true, false, false, false,
+ (short) 1, 1, true, true));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getBandwidth(), m2.getBandwidth());
+ assertEquals(m.getLspa(), m2.getLspa());
+ assertEquals(m.getMetrics(), m2.getMetrics());
+ assertEquals(m.getIncludeRoute(), m2.getIncludeRoute());
+ assertEquals(m.getLsp(), m2.getLsp());
+ assertEquals(m.getPaths(), m2.getPaths());
+ assertEquals(m.getRequestParameter(), m2.getRequestParameter());
+ assertEquals(m, CompositeResponseObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositeStateReportObjectTest() {
+
+ final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+ }
+ };
+
+ final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new RROAsNumberSubobject(new ASNumber(2555)));
+ }
+ };
+
+ final List<CompositeRptPathObject> paths = new ArrayList<CompositeRptPathObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(eroSubobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true,
+ true, true, true), new PCEPExistingPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new PCEPReportedRouteObject(
+ rroSubobjects, true), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ }));
+ }
+ };
+
+ final CompositeStateReportObject m = new CompositeStateReportObject(new PCEPLspObject((short) 1, true, true, true, true), paths);
+ final CompositeStateReportObject m2 = new CompositeStateReportObject(new PCEPLspObject((short) 1, true, true, true, true), paths);
+ final CompositeStateReportObject m3 = new CompositeStateReportObject(new PCEPLspObject((short) 1, true, true, true, true));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getLsp(), m2.getLsp());
+ assertEquals(m.getPaths(), m2.getPaths());
+ assertEquals(m, CompositeStateReportObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositeUpdateRequestObjectTest() {
+
+ final List<ExplicitRouteSubobject> subobjects = new ArrayList<ExplicitRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new EROAsNumberSubobject(new ASNumber(2555), false));
+ }
+ };
+
+ final List<CompositeUpdPathObject> paths = new ArrayList<CompositeUpdPathObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(subobjects, true), new PCEPLspaObject(2, 2, 2, (short) 2, (short) 2, true,
+ true, true, true), new PCEPRequestedPathBandwidthObject(new Bandwidth((float) 0.222), true, true), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(255), true, false));
+ }
+ }));
+ }
+ };
+
+ final CompositeUpdateRequestObject m = new CompositeUpdateRequestObject(new PCEPLspObject((short) 1, true, true, true, true), paths);
+ final CompositeUpdateRequestObject m2 = new CompositeUpdateRequestObject(new PCEPLspObject((short) 1, true, true, true, true), paths);
+ final CompositeUpdateRequestObject m3 = new CompositeUpdateRequestObject(new PCEPLspObject((short) 1, true, true, true, true));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getLsp(), m2.getLsp());
+ assertEquals(m.getPaths(), m2.getPaths());
+ assertEquals(m, CompositeUpdateRequestObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositeRequestSVECObjectTest() {
+
+ final List<ExcludeRouteSubobject> subobjects = new ArrayList<ExcludeRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new XROAsNumberSubobject(new ASNumber(2555), false));
+ }
+ };
+
+ final List<Long> requestIds = new ArrayList<Long>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(0x12345678L);
+ }
+ };
+
+ final CompositeRequestSvecObject m = new CompositeRequestSvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true),
+ new PCEPObjectiveFunctionObject(PCEPOFCodes.MBC, true, false), new PCEPGlobalConstraintsObject((short) 2, (short) 2, (short) 2, (short) 2,
+ true, false), new PCEPExcludeRouteObject(subobjects, true, true, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(0x123456), true, false));
+ }
+ });
+ final CompositeRequestSvecObject m2 = new CompositeRequestSvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true),
+ new PCEPObjectiveFunctionObject(PCEPOFCodes.MBC, true, false), new PCEPGlobalConstraintsObject((short) 2, (short) 2, (short) 2, (short) 2,
+ true, false), new PCEPExcludeRouteObject(subobjects, true, true, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(0x123456), true, false));
+ }
+ });
+ final CompositeRequestSvecObject m3 = new CompositeRequestSvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getExcludeRoute(), m2.getExcludeRoute());
+ assertEquals(m.getGlobalConstraints(), m2.getGlobalConstraints());
+ assertEquals(m.getObjectiveFunction(), m2.getObjectiveFunction());
+ assertEquals(m.getSvec(), m2.getSvec());
+ assertEquals(m, CompositeRequestSvecObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void compositeRplySVECObjectTest() {
+
+ final List<Long> requestIds = new ArrayList<Long>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(0x12345678L);
+ }
+ };
+
+ final CompositeReplySvecObject m = new CompositeReplySvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true),
+ new PCEPObjectiveFunctionObject(PCEPOFCodes.MBC, true, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(0x123456), true, false));
+ }
+ });
+ final CompositeReplySvecObject m2 = new CompositeReplySvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true),
+ new PCEPObjectiveFunctionObject(PCEPOFCodes.MBC, true, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(0x123456), true, false));
+ }
+ });
+ final CompositeReplySvecObject m3 = new CompositeReplySvecObject(new PCEPSvecObject(true, true, true, false, false, requestIds, true));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getCompositeAsList(), m2.getCompositeAsList());
+ assertEquals(m.getObjectiveFunction(), m2.getObjectiveFunction());
+ assertEquals(m.getSvec(), m2.getSvec());
+ assertEquals(m, CompositeReplySvecObject.getCompositeFromList(m.getCompositeAsList()));
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void subobjectsTest() {
+ final EROAsNumberSubobject as = new EROAsNumberSubobject(new ASNumber(2555), false);
+ final EROUnnumberedInterfaceSubobject uis = new EROUnnumberedInterfaceSubobject(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new UnnumberedInterfaceIdentifier(2), true);
+ final EROIPPrefixSubobject<IPv4Prefix> ips = new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22), false);
+
+ assertEquals(as.getASNumber().getAsn(), 2555);
+ assertEquals(as.isLoose(), false);
+ assertFalse(as.equals(null));
+ assertFalse(as.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(as.equals(as));
+
+ assertEquals(uis.getInterfaceID().getInterfaceId(), 2);
+ assertEquals(uis.getRouterID(),
+ new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }));
+ assertEquals(uis.isLoose(), true);
+ assertFalse(uis.equals(null));
+ assertFalse(uis.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(uis.equals(uis));
+
+ assertEquals(
+ ips.getPrefix(),
+ new IPv4Prefix(new IPv4Address(new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22));
+ assertEquals(ips.isLoose(), false);
+ assertFalse(ips.equals(null));
+ assertFalse(ips.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(ips.equals(ips));
+ }
+
+ @Test
+ public void xroSubobjectsTest() {
+ final XROAsNumberSubobject as = new XROAsNumberSubobject(new ASNumber(2555), false);
+ final XROUnnumberedInterfaceSubobject uis = new XROUnnumberedInterfaceSubobject(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new UnnumberedInterfaceIdentifier(2), true, XROSubobjectAttribute.SRLG);
+ final XROIPPrefixSubobject<IPv4Prefix> ips = new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22), false, XROSubobjectAttribute.SRLG);
+ final XROSRLGSubobject srlg = new XROSRLGSubobject(new SharedRiskLinkGroup(0x1234L), true);
+
+ assertEquals(as.getASNumber().getAsn(), 2555);
+ assertEquals(as.isMandatory(), false);
+ assertFalse(as.equals(null));
+ assertFalse(as.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(as.equals(as));
+ assertEquals(as.toString(), "XROAsNumberSubobject [asnumber=2555, mandatory=false]");
+
+ assertEquals(uis.getInterfaceID().getInterfaceId(), 2);
+ assertEquals(uis.getRouterID(),
+ new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }));
+ assertEquals(uis.isMandatory(), true);
+ assertFalse(uis.equals(null));
+ assertFalse(uis.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(uis.equals(uis));
+ assertEquals(uis.getAttribute(), XROSubobjectAttribute.SRLG);
+ assertEquals(uis.toString(),
+ "XROUnnumberedInterfaceSubobject [attribute=SRLG, interfaceID=UnnumberedInterfaceIdentifier [interfaceId=2], routerID=127.0.0.2, mandatory=true]");
+
+ assertEquals(
+ ips.getPrefix(),
+ new IPv4Prefix(new IPv4Address(new byte[] { (byte) 12, (byte) 122, (byte) 125, (byte) 2 }), 22));
+ assertEquals(ips.isMandatory(), false);
+ assertFalse(ips.equals(null));
+ assertFalse(ips.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(ips.equals(ips));
+ assertEquals(ips.getAttribute(), XROSubobjectAttribute.SRLG);
+ assertEquals(ips.toString(), "XROIPPrefixSubobject [attribute=SRLG, prefix=12.122.124.0/22, mandatory=false]");
+
+ assertEquals(srlg.getSrlgId().getValue(), 0x1234L);
+ assertEquals(srlg.getAttribute(), XROSubobjectAttribute.SRLG);
+ assertFalse(srlg.equals(null));
+ assertFalse(srlg.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(srlg.equals(srlg));
+ assertEquals(srlg.toString(), "XROSRLGSubobject [attribute=SRLG, srlgId=4660, mandatory=true]");
+ }
+
+ @Test
+ public void testToString(){
+ final List<PCEPObject> objects = Lists.newArrayList();
+ objects.add(new PCEPExistingPathBandwidthObject(new Bandwidth(22.0), true, false));
+ objects.add(new PCEPRequestedPathBandwidthObject(new Bandwidth(22.0), true, false));
+ objects.add(new PCEPEndPointsObject<IPv4Address>(IPv4.FAMILY.addressForBytes(new byte[]{1,1,1,1}),
+ IPv4.FAMILY.addressForBytes(new byte[]{1,1,1,2})));
+ objects.add(new PCEPP2MPEndPointsObject<IPv4Address>(0, IPv4.FAMILY.addressForBytes(new byte[] { 1, 1, 1, 1 }),
+ Lists.newArrayList(IPv4.FAMILY.addressForBytes(new byte[] { 1, 1, 1, 1 })), true, false));
+
+ for (final PCEPObject o: objects) {
+ assertThat(o.toString(), containsString("processed=true"));
+ assertThat(o.toString(), containsString("ignored=false"));
+ if(o instanceof PCEPBandwidthObject)
+ assertThat(o.toString(), containsString("bandwidth=Bandwidth [bytesPerSecond=22.0]"));
+ if(o instanceof PCEPEndPoints)
+ assertThat(o.toString(), containsString("sourceAddress=1.1.1.1"));
+ if(o instanceof PCEPP2MPEndPointsObject)
+ assertThat(o.toString(), containsString("destinationAddresses=[1.1.1.1]"));
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.api;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.concepts.IPv4ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.IPv6ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.IPv4LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.IPv6LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPCleanupTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPSymbolicNameTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPUpdateErrorTlv;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.pcep.tlv.OverloadedDurationTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.pcep.tlv.ReqMissingTlv;
+
+/**
+ *
+ */
+public class TlvsTest {
+ @Test
+ public void IPv4LSPIdentifiersTlvTest() {
+ final IPv4LSPIdentifiersTlv m = new IPv4LSPIdentifiersTlv(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(
+ new byte[] { (byte) 127, (byte) 0 }), new IPv4ExtendedTunnelIdentifier(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 })));
+ final IPv4LSPIdentifiersTlv m2 = new IPv4LSPIdentifiersTlv(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(
+ new byte[] { (byte) 127, (byte) 0 }), new IPv4ExtendedTunnelIdentifier(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 })));
+ final IPv4LSPIdentifiersTlv m3 = new IPv4LSPIdentifiersTlv(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(
+ new byte[] { (byte) 127, (byte) 0 }), new IPv4ExtendedTunnelIdentifier(new IPv4Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 3 })));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getExtendedTunnelID(), m2.getExtendedTunnelID());
+ assertEquals(m.getLspID(), m2.getLspID());
+ assertEquals(m.getSenderAddress(), m2.getSenderAddress());
+ assertEquals(m.getTunnelID(), m2.getTunnelID());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void IPv6LSPIdentifiersTlvTest() {
+ final IPv6LSPIdentifiersTlv m = new IPv6LSPIdentifiersTlv(new IPv6Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+ (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(new byte[] {
+ (byte) 127, (byte) 0 }), new IPv6ExtendedTunnelIdentifier(new IPv6Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+ (byte) 127, (byte) 0, (byte) 0, (byte) 2 })));
+ final IPv6LSPIdentifiersTlv m2 = new IPv6LSPIdentifiersTlv(new IPv6Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+ (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(new byte[] {
+ (byte) 127, (byte) 0 }), new IPv6ExtendedTunnelIdentifier(new IPv6Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+ (byte) 127, (byte) 0, (byte) 0, (byte) 2 })));
+ final IPv6LSPIdentifiersTlv m3 = new IPv6LSPIdentifiersTlv(new IPv6Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+ (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), new LSPIdentifier(new byte[] { (byte) 127, (byte) 0 }), new TunnelIdentifier(new byte[] {
+ (byte) 127, (byte) 0 }), new IPv6ExtendedTunnelIdentifier(new IPv6Address(
+ new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2, (byte) 127, (byte) 0, (byte) 0, (byte) 2,
+ (byte) 127, (byte) 0, (byte) 0, (byte) 3 })));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getExtendedTunnelID(), m2.getExtendedTunnelID());
+ assertEquals(m.getLspID(), m2.getLspID());
+ assertEquals(m.getSenderAddress(), m2.getSenderAddress());
+ assertEquals(m.getTunnelID(), m2.getTunnelID());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void LSPStateDBVersionTlvTest() {
+ final LSPStateDBVersionTlv m = new LSPStateDBVersionTlv(25);
+ final LSPStateDBVersionTlv m2 = new LSPStateDBVersionTlv(25);
+ final LSPStateDBVersionTlv m3 = new LSPStateDBVersionTlv(26);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getDbVersion(), m2.getDbVersion());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void LSPSymbolicNameTlvTest() {
+ final LSPSymbolicNameTlv m = new LSPSymbolicNameTlv(new LSPSymbolicName(new byte[] { (byte) 2 }));
+ final LSPSymbolicNameTlv m2 = new LSPSymbolicNameTlv(new LSPSymbolicName(new byte[] { (byte) 2 }));
+ final LSPSymbolicNameTlv m3 = new LSPSymbolicNameTlv(new LSPSymbolicName(new byte[] { (byte) 3 }));
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getSymbolicName(), m2.getSymbolicName());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void LSPUpdateErrorTlvTest() {
+ final LSPUpdateErrorTlv m = new LSPUpdateErrorTlv(new byte[] { (byte) 2, (byte) 2, (byte) 2, (byte) 2 });
+ final LSPUpdateErrorTlv m2 = new LSPUpdateErrorTlv(new byte[] { (byte) 2, (byte) 2, (byte) 2, (byte) 2 });
+ final LSPUpdateErrorTlv m3 = new LSPUpdateErrorTlv(new byte[] { (byte) 2, (byte) 2, (byte) 2, (byte) 3 });
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertArrayEquals(m.getErrorCode(), m2.getErrorCode());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void NoPathVectorTlvTest() {
+ final NoPathVectorTlv m = new NoPathVectorTlv(false, true, false, false, false, false);
+ final NoPathVectorTlv m2 = new NoPathVectorTlv(false, true, false, false, false, false);
+ final NoPathVectorTlv m3 = new NoPathVectorTlv(false, true, true, false, false, false);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertFalse(m.isPceUnavailable());
+ assertTrue(m.isUnknownDest());
+ assertFalse(m.isUnknownSrc());
+ assertFalse(m.isNoGCOSolution());
+ assertFalse(m.isNoGCOMigrationPath());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void NodeIdentifierTlvTest() throws UnsupportedEncodingException {
+ final NodeIdentifierTlv m = new NodeIdentifierTlv(new byte[] { (byte) 2 });
+ final NodeIdentifierTlv m2 = new NodeIdentifierTlv(new byte[] { (byte) 2 });
+ final NodeIdentifierTlv m3 = new NodeIdentifierTlv(new byte[] { (byte) 79, (byte) 102, (byte) 45, (byte) 57, (byte) 107, (byte) 45, (byte) 48,
+ (byte) 50 });
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertArrayEquals(m.getValue(), m2.getValue());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ assertEquals(m3.toString(), "NodeIdentifierTlv [value=Of-9k-02]");
+
+ //non-ascii string
+ final String str = "þščťžéíá";
+
+ //test utf-8 validity
+ assertEquals("NodeIdentifierTlv [value=" + str + "]", new NodeIdentifierTlv(str.getBytes("UTF-8")).toString());
+
+ //test enother encoding, should be represented as raw binary
+ assertEquals("NodeIdentifierTlv [value=" + Arrays.toString(str.getBytes("ISO8859_1")) + "]",
+ new NodeIdentifierTlv(str.getBytes("ISO8859_1")).toString());
+ }
+
+ @Test
+ public void OverloadedDurationTlvTest() {
+ final OverloadedDurationTlv m = new OverloadedDurationTlv(2);
+ final OverloadedDurationTlv m2 = new OverloadedDurationTlv(2);
+ final OverloadedDurationTlv m3 = new OverloadedDurationTlv(3);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getValue(), m2.getValue());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void PCEStatefulCapabilityTlvTest() {
+ final PCEStatefulCapabilityTlv m = new PCEStatefulCapabilityTlv(false, true, false);
+ final PCEStatefulCapabilityTlv m2 = new PCEStatefulCapabilityTlv(false, true, false);
+ final PCEStatefulCapabilityTlv m3 = new PCEStatefulCapabilityTlv(true, true, true);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void RSVPErrorSpecTlvTest() {
+ final RSVPErrorSpecTlv<IPv4Address> m = new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), true, true, 2, 2);
+ final RSVPErrorSpecTlv<IPv4Address> m2 = new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), true, true, 2, 2);
+ final RSVPErrorSpecTlv<IPv4Address> m3 = new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(new byte[] { (byte) 127, (byte) 0, (byte) 0, (byte) 2 }), false, true, 2, 2);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getErrorCode(), m2.getErrorCode());
+ assertEquals(m.getErrorNodeAddress(), m2.getErrorNodeAddress());
+ assertEquals(m.getErrorValue(), m2.getErrorValue());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void ReqMissingTlvTest() {
+ final ReqMissingTlv m = new ReqMissingTlv(2);
+ final ReqMissingTlv m2 = new ReqMissingTlv(2);
+ final ReqMissingTlv m3 = new ReqMissingTlv(3);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getRequestID(), m2.getRequestID());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void OFListTlvTest() {
+ final List<PCEPOFCodes> ofcodes = new ArrayList<PCEPOFCodes>();
+
+ final OFListTlv m = new OFListTlv(ofcodes);
+ final OFListTlv m2 = new OFListTlv(ofcodes);
+ final OFListTlv m3 = new OFListTlv(null);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getOfCodes(), m2.getOfCodes());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+ }
+
+ @Test
+ public void LSPCleanupTlvTest() {
+ final LSPCleanupTlv m = new LSPCleanupTlv(Integer.MAX_VALUE);
+ final LSPCleanupTlv m2 = new LSPCleanupTlv(Integer.MAX_VALUE);
+ final LSPCleanupTlv m3 = new LSPCleanupTlv(0);
+
+ assertEquals(m, m2);
+ assertEquals(m.toString(), m2.toString());
+ assertEquals(m.hashCode(), m2.hashCode());
+ assertEquals(m.getTimeout(), m2.getTimeout());
+ assertFalse(m.equals(null));
+ assertFalse(m.equals(m3));
+ assertFalse(m.equals(new PCEPOpenMessage(new PCEPOpenObject(10, 10, 1))));
+ assertTrue(m.equals(m));
+
+ try {
+ new LSPCleanupTlv(Integer.MIN_VALUE);
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Timeout (" + Integer.MIN_VALUE + ") cannot be negative or bigger than 2^31 -1.", e.getMessage());
+ }
+ }
+}
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>pcep-impl</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>pcep-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>pcep-impl</artifactId>
+ <description>PCE Protocol Implementation</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>framework</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>util</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>framework</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Import-Package>
+ org.opendaylight.protocol.concepts,
+ org.opendaylight.protocol.framework,
+ org.opendaylight.protocol.concepts,
+ com.google.common.base,
+ com.google.common.collect,
+ com.google.common.primitives,
+ javax.annotation,
+ javax.management,
+ javax.net.ssl,
+ org.opendaylight.protocol.pcep,
+ org.opendaylight.protocol.pcep.concepts,
+ org.opendaylight.protocol.pcep.message,
+ org.opendaylight.protocol.pcep.object,
+ org.opendaylight.protocol.pcep.subobject,
+ org.opendaylight.protocol.pcep.tlv,
+ org.opendaylight.protocol.util,
+ org.slf4j,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.protocol.pcep.impl.*,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>PCEP-IMPL Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+
+public class PCEPConnectionImpl implements PCEPConnection {
+
+ private final InetSocketAddress address;
+
+ private final PCEPSessionListener listener;
+
+ private final PCEPSessionPreferences proposal;
+
+ private final PCEPSessionProposalChecker checker;
+
+ public PCEPConnectionImpl(final InetSocketAddress address, final PCEPSessionListener listener, final PCEPSessionPreferences proposal,
+ final PCEPSessionProposalChecker checker) {
+ this.address = address;
+ this.listener = listener;
+ this.proposal = proposal;
+ this.checker = checker;
+ }
+
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return this.address;
+ }
+
+ @Override
+ public PCEPSessionListener getListener() {
+ return this.listener;
+ }
+
+ @Override
+ public PCEPSessionPreferences getProposal() {
+ return this.proposal;
+ }
+
+ @Override
+ public PCEPSessionProposalChecker getProposalChecker() {
+ return this.checker;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.Dispatcher;
+import org.opendaylight.protocol.framework.ProtocolServer;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPConnectionFactory;
+import org.opendaylight.protocol.pcep.PCEPDispatcher;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
+
+/**
+ * Implementation of PCEPDispatcher.
+ */
+public class PCEPDispatcherImpl implements PCEPDispatcher {
+ public static final int DEFAULT_MAX_UNKNOWN_MSG = 5;
+
+ private int maxUnknownMessages = DEFAULT_MAX_UNKNOWN_MSG;
+
+ private final Dispatcher dispatcher;
+
+ private final PCEPSessionProposalFactory proposalFactory;
+
+ /**
+ * Creates an instance of PCEPDispatcherImpl, gets the default selector and opens it.
+ *
+ * @throws IOException if some error occurred during opening the selector
+ */
+ public PCEPDispatcherImpl(final Dispatcher dispatcher, final PCEPSessionProposalFactory proposalFactory) {
+ this.dispatcher = dispatcher;
+ this.proposalFactory = proposalFactory;
+ }
+
+ @Override
+ public ProtocolServer createServer(final InetSocketAddress address, final PCEPConnectionFactory connectionFactory) throws IOException {
+ connectionFactory.setProposal(this.proposalFactory, address, 0);
+ return this.dispatcher.createServer(address, connectionFactory, new PCEPSessionFactoryImpl(this.maxUnknownMessages),
+ PCEPInputStream.FACTORY);
+ }
+
+ /**
+ * Create client is used for mock purposes only.
+ */
+ @Override
+ public PCEPSession createClient(final PCEPConnection connection) throws IOException {
+ return (PCEPSession) this.dispatcher.createClient(connection, new PCEPSessionFactoryImpl(this.maxUnknownMessages),
+ PCEPInputStream.FACTORY);
+ }
+
+ @Override
+ public void setMaxUnknownMessages(final int limit) {
+ this.maxUnknownMessages = limit;
+ }
+
+ public int getMaxUnknownMessages() {
+ return this.maxUnknownMessages;
+ }
+
+ public Dispatcher getDispatcher() {
+ return this.dispatcher;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.subobject.EROAsNumberSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROExplicitExclusionRouteSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROIPv4PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROIPv6PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROLabelSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROPathKeyWith128PCEIDSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROPathKeyWith32PCEIDSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROProtectionSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROExplicitExclusionRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.PCEPSubobject PCEPSubobject}
+ */
+public class PCEPEROSubobjectParser {
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPEROSubobjectParser.class);
+
+ /**
+ * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPSubobject
+ * PCEPSubobject}
+ */
+ public enum PCEPSubobjectType {
+ IPv4_PREFIX(1), IPv6_PREFIX(2), LABEL(3), UNNUMBERED_INTERFACE_ID(4), AS_NUMBER(32), EXRS(33), PROTECTION(37), PK_32(
+ 64), PK_128(65);
+
+ private final int indicator;
+
+ PCEPSubobjectType(int indicator) {
+ this.indicator = indicator;
+ }
+
+ public int getIndicator() {
+ return this.indicator;
+ }
+
+ public static PCEPSubobjectType getFromInt(int type) throws PCEPDeserializerException {
+
+ for (final PCEPSubobjectType type_e : PCEPSubobjectType.values()) {
+ if (type_e.getIndicator() == type)
+ return type_e;
+ }
+
+ throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + "; Known: "
+ + PCEPSubobjectType.values() + ".");
+ }
+ }
+
+ /*
+ * Fields lengths in Bytes
+ */
+ public static final int TYPE_FLAG_F_LENGTH = 1;
+ public static final int LENGTH_F_LENGTH = 1;
+
+ /*
+ * Fields offsets in Bytes
+ */
+ public static final int TYPE_FLAG_F_OFFSET = 0;
+ public static final int LENGTH_F_OFFSET = TYPE_FLAG_F_OFFSET + TYPE_FLAG_F_LENGTH;
+ public static final int SO_CONTENTS_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
+
+ public static List<ExplicitRouteSubobject> parse(byte[] bytes) throws PCEPDeserializerException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Byte array is mandatory.");
+
+ final List<ExplicitRouteSubobject> subobjsList = new ArrayList<ExplicitRouteSubobject>();
+ boolean loose_flag;
+ PCEPSubobjectType type;
+ byte[] soContentsBytes;
+ int length;
+ int offset = 0;
+
+ while (offset < bytes.length) {
+
+ loose_flag = ((bytes[offset + TYPE_FLAG_F_OFFSET] & (1 << 7)) != 0) ? true : false;
+ length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
+
+ type = PCEPSubobjectType.getFromInt((bytes[offset + TYPE_FLAG_F_OFFSET] & 0xff) & ~(1 << 7));
+
+ if (length > bytes.length - offset)
+ throw new PCEPDeserializerException("Wrong length specified. Passed: " + length + "; Expected: <= " + (bytes.length - offset));
+
+ soContentsBytes = new byte[length - SO_CONTENTS_OFFSET];
+ System.arraycopy(bytes, offset + SO_CONTENTS_OFFSET, soContentsBytes, 0, length - SO_CONTENTS_OFFSET);
+
+ logger.debug("Attempt to parse subobject from bytes: {}", ByteArray.bytesToHexString(soContentsBytes));
+ final ExplicitRouteSubobject subObj = parseSpecificSubobject(type, soContentsBytes, loose_flag);
+ logger.debug("Subobject was parsed. {}", subObj);
+
+ subobjsList.add(subObj);
+
+ offset += length;
+ }
+
+ return subobjsList;
+ }
+
+ public static byte[] put(List<ExplicitRouteSubobject> objsToSerialize) {
+ final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
+
+ int length = 0;
+ for (final ExplicitRouteSubobject obj : objsToSerialize) {
+ final byte[] bytes = put(obj);
+ length += bytes.length;
+ bytesList.add(bytes);
+ }
+
+ final byte[] retBytes = new byte[length];
+
+ int offset = 0;
+ for (final byte[] bytes : bytesList) {
+ System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
+ offset += bytes.length;
+ }
+
+ return retBytes;
+ }
+
+ public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+ int typeIndicator = 0;
+
+ final byte[] soContentsBytes;
+
+ if (objToSerialize instanceof EROIPPrefixSubobject<?> && ((EROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv4Prefix) {
+ typeIndicator = PCEPSubobjectType.IPv4_PREFIX.getIndicator();
+ soContentsBytes = EROIPv4PrefixSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof EROIPPrefixSubobject<?> && ((EROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv6Prefix) {
+ typeIndicator = PCEPSubobjectType.IPv6_PREFIX.getIndicator();
+ soContentsBytes = EROIPv6PrefixSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof EROAsNumberSubobject) {
+ typeIndicator = PCEPSubobjectType.AS_NUMBER.getIndicator();
+ soContentsBytes = EROAsNumberSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof EROUnnumberedInterfaceSubobject) {
+ typeIndicator = PCEPSubobjectType.UNNUMBERED_INTERFACE_ID.getIndicator();
+ soContentsBytes = EROUnnumberedInterfaceSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof EROLabelSubobject) {
+ typeIndicator = PCEPSubobjectType.LABEL.getIndicator();
+ soContentsBytes = EROLabelSubobjectParser.put((EROLabelSubobject) objToSerialize);
+ } else if (objToSerialize instanceof EROExplicitExclusionRouteSubobject) {
+ typeIndicator = PCEPSubobjectType.EXRS.getIndicator();
+ soContentsBytes = EROExplicitExclusionRouteSubobjectParser.put((EROExplicitExclusionRouteSubobject) objToSerialize);
+ } else if (objToSerialize instanceof EROPathKeyWith32PCEIDSubobject) {
+ typeIndicator = PCEPSubobjectType.PK_32.getIndicator();
+ soContentsBytes = EROPathKeyWith32PCEIDSubobjectParser.put((EROPathKeyWith32PCEIDSubobject) objToSerialize);
+ } else if (objToSerialize instanceof EROPathKeyWith128PCEIDSubobject) {
+ typeIndicator = PCEPSubobjectType.PK_128.getIndicator();
+ soContentsBytes = EROPathKeyWith128PCEIDSubobjectParser.put((EROPathKeyWith128PCEIDSubobject) objToSerialize);
+ } else if (objToSerialize instanceof EROProtectionSubobject) {
+ typeIndicator = PCEPSubobjectType.PROTECTION.getIndicator();
+ soContentsBytes = EROProtectionSubobjectParser.put((EROProtectionSubobject) objToSerialize);
+ } else
+ throw new IllegalArgumentException("Unknown instance of PCEPSubobject. Passed: " + objToSerialize.getClass() + ".");
+
+ final byte[] bytes = new byte[SO_CONTENTS_OFFSET + soContentsBytes.length];
+
+ bytes[TYPE_FLAG_F_OFFSET] = (byte) (ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_FLAG_F_LENGTH)[0] | (objToSerialize
+ .isLoose() ? 1 << 7 : 0));
+ bytes[LENGTH_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(soContentsBytes.length + SO_CONTENTS_OFFSET), (Integer.SIZE / 8) - LENGTH_F_LENGTH)[0];
+
+ System.arraycopy(soContentsBytes, 0, bytes, SO_CONTENTS_OFFSET, soContentsBytes.length);
+
+ return bytes;
+ }
+
+ private static ExplicitRouteSubobject parseSpecificSubobject(PCEPSubobjectType type, byte[] soContentsBytes, boolean loose_flag)
+ throws PCEPDeserializerException {
+
+ switch (type) {
+ case IPv4_PREFIX:
+ return EROIPv4PrefixSubobjectParser.parse(soContentsBytes, loose_flag);
+ case IPv6_PREFIX:
+ return EROIPv6PrefixSubobjectParser.parse(soContentsBytes, loose_flag);
+ case UNNUMBERED_INTERFACE_ID:
+ return EROUnnumberedInterfaceSubobjectParser.parse(soContentsBytes, loose_flag);
+ case AS_NUMBER:
+ return EROAsNumberSubobjectParser.parse(soContentsBytes, loose_flag);
+ case LABEL:
+ return EROLabelSubobjectParser.parse(soContentsBytes, loose_flag);
+ case EXRS:
+ return EROExplicitExclusionRouteSubobjectParser.parse(soContentsBytes, loose_flag);
+ case PK_32:
+ return EROPathKeyWith32PCEIDSubobjectParser.parse(soContentsBytes, loose_flag);
+ case PK_128:
+ return EROPathKeyWith128PCEIDSubobjectParser.parse(soContentsBytes, loose_flag);
+ case PROTECTION:
+ return EROProtectionSubobjectParser.parse(soContentsBytes, loose_flag);
+ default:
+ throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + ".");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolInputStream;
+import org.opendaylight.protocol.framework.ProtocolInputStreamFactory;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+
+/**
+ *
+ */
+public class PCEPInputStream implements ProtocolInputStream {
+ static final ProtocolInputStreamFactory FACTORY = new ProtocolInputStreamFactory() {
+ @Override
+ public ProtocolInputStream getProtocolInputStream(final PipedInputStream pis, final ProtocolMessageFactory pmf) {
+ return new PCEPInputStream(pis, pmf);
+ }
+ };
+
+ private final ProtocolMessageFactory factory;
+ private final PipedInputStream inputStream;
+ private PCEPMessageHeader header;
+
+ public PCEPInputStream(final PipedInputStream inputStream, final ProtocolMessageFactory factory) {
+ this.factory = factory;
+ this.inputStream = inputStream;
+ this.header = new PCEPMessageHeader();
+ }
+
+ /**
+ * Check availability of a message in underlying input stream. A message is available when there are more or the
+ * same amount of bytes in the stream as the message length is specified in message header. If there are not enough
+ * bytes for the message or even to read a message header, return false.
+ *
+ * @return true if there are enough bytes to read a message false if there are not enough bytes to read a message or
+ * a message header.
+ * @throws IOException
+ */
+ @Override
+ public synchronized boolean isMessageAvailable() throws IOException {
+ if (!this.header.isParsed()) {
+ // No header, try to parse it
+ this.header = this.parseHeaderIfAvailable();
+
+ if (!this.header.isParsed()) {
+ // No luck, we do not have a message
+ return false;
+ }
+ }
+ // message length contains the size of the header too
+ if (this.inputStream.available() < (this.header.getLength() - PCEPMessageHeader.COMMON_HEADER_LENGTH)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * If there are enough bytes in the underlying stream, parse the message. Blocking, till there are enough bytes to
+ * read, therefore the call of method isMessageAvailable() is suggested first.
+ *
+ * @param factory protocol specific message factory
+ * @return protocol specific message
+ * @throws DeserializerException
+ * @throws IOException
+ * @throws DocumentedException
+ */
+ @Override
+ public synchronized ProtocolMessage getMessage() throws DeserializerException, IOException, DocumentedException {
+ // isMessageAvailable wasn't called, or there were not enough bytes to form message header
+ // blocking till the header is available
+ while (!this.header.isParsed()) {
+ this.header = this.parseHeaderIfAvailable();
+ }
+ final byte[] bytes = new byte[this.header.getLength() - PCEPMessageHeader.COMMON_HEADER_LENGTH]; // message
+ // length
+ // contains
+ // the size
+ // of the
+ // header
+ // too
+ // blocking till the whole message is available
+ if (this.inputStream.read(bytes) == -1) {
+ throw new IOException("PipedInputStream was closed, before data could be read from it.");
+ }
+ final ProtocolMessage msg = this.factory.parse(bytes, this.header);
+
+ this.header.setParsed(); // if we have all the bytes to send the message for parsing, clear the header, to let know,
+ // we're ready to read another message
+
+ return msg;
+ }
+
+ /**
+ * Checks if there are enough bytes to parse a header and parses it. Non-blocking: if there are not enough bytes to
+ * parse a message header, returns false.
+ *
+ * @return cleared header if no header is available
+ * @return header object when enough data is available
+ */
+ private PCEPMessageHeader parseHeaderIfAvailable() throws IOException {
+ if (this.inputStream.available() < PCEPMessageHeader.COMMON_HEADER_LENGTH) {
+ this.header.setParsed();
+ return this.header;
+ }
+
+ final byte[] messageHeader = new byte[PCEPMessageHeader.COMMON_HEADER_LENGTH];
+ if (this.inputStream.read(messageHeader) == -1) {
+ this.header.setParsed();
+ return this.header;
+ }
+ return this.header.fromBytes(messageHeader);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.HashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.message.PCCreateMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPCloseMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPErrorMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPKeepAliveMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPNotificationMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPOpenMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRawMessage;
+import org.opendaylight.protocol.pcep.impl.message.PCEPReplyMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPReportMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRequestMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPUpdateRequestMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPXRAddTunnelMessageParser;
+import org.opendaylight.protocol.pcep.impl.message.PCEPXRDeleteTunnelMessageParser;
+import org.opendaylight.protocol.pcep.message.PCCreateMessage;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRDeleteTunnelMessage;
+
+/**
+ * Factory for subclasses of {@link org.opendaylight.protocol.pcep.PCEPMessage PCEPMessage}
+ */
+public class PCEPMessageFactory implements ProtocolMessageFactory {
+
+ private final static Logger logger = LoggerFactory.getLogger(PCEPMessageFactory.class);
+
+ /**
+ * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPMessage PCEPMessage}
+ */
+ public enum PCEPMessageType {
+ OPEN(1), NOTIFICATION(5), KEEPALIVE(2), RESPONSE(4), REQUEST(3), ERROR(6), CLOSE(7), UPDATE_REQUEST(11), STATUS_REPORT(10),
+ // TODO: replace with actual values by IANA
+ XR_ADD_TUNNEL(8),
+ XR_DELETE_TUNNEL(9),
+ PCCREATE(12);
+
+ private final int identifier;
+
+ PCEPMessageType(final int identifier) {
+ this.identifier = identifier;
+ }
+
+ public int getIdentifier() {
+ return this.identifier;
+ }
+
+ public static PCEPMessageType getFromInt(final int type) throws PCEPDeserializerException {
+
+ for (final PCEPMessageType type_e : PCEPMessageType.values()) {
+ if (type_e.getIdentifier() == type)
+ return type_e;
+ }
+
+ throw new PCEPDeserializerException("Unknown PCEPMessage Class identifier. Passed: " + type + "; Known: " + PCEPMessageType.values() + ".");
+ }
+ }
+
+ private static class MapOfParsers extends HashMap<PCEPMessageType, PCEPMessageParser> {
+
+ private static final long serialVersionUID = -5715193806554448822L;
+
+ private final static MapOfParsers instance = new MapOfParsers();
+
+ private MapOfParsers() {
+ this.fillInMap();
+ }
+
+ private void fillInMap() {
+ this.put(PCEPMessageType.OPEN, new PCEPOpenMessageParser());
+ this.put(PCEPMessageType.KEEPALIVE, new PCEPKeepAliveMessageParser());
+ this.put(PCEPMessageType.NOTIFICATION, new PCEPNotificationMessageParser());
+ this.put(PCEPMessageType.ERROR, new PCEPErrorMessageParser());
+ this.put(PCEPMessageType.RESPONSE, new PCEPReplyMessageParser());
+ this.put(PCEPMessageType.REQUEST, new PCEPRequestMessageParser());
+ this.put(PCEPMessageType.UPDATE_REQUEST, new PCEPUpdateRequestMessageParser());
+ this.put(PCEPMessageType.STATUS_REPORT, new PCEPReportMessageParser());
+ this.put(PCEPMessageType.CLOSE, new PCEPCloseMessageParser());
+ this.put(PCEPMessageType.XR_ADD_TUNNEL, new PCEPXRAddTunnelMessageParser());
+ this.put(PCEPMessageType.XR_DELETE_TUNNEL, new PCEPXRDeleteTunnelMessageParser());
+ this.put(PCEPMessageType.PCCREATE, new PCCreateMessageParser());
+ }
+
+ public static MapOfParsers getInstance() {
+ return instance;
+ }
+ }
+
+ /**
+ *
+ * @param bytes
+ * assume array of bytes without common header
+ * @param msgHeader
+ * @return Parsed specific PCEPMessage
+ * @throws PCEPDeserializerException
+ * @throws PCEPDocumentedException
+ */
+
+ @Override
+ public ProtocolMessage parse(final byte[] bytes, final ProtocolMessageHeader msgH) throws DeserializerException, DocumentedException {
+ final PCEPMessageHeader msgHeader = (PCEPMessageHeader) msgH;
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory.");
+ if (msgHeader == null)
+ throw new IllegalArgumentException("PCEPMessageHeader is mandatory.");
+
+ logger.trace("Attempt to parse message from bytes: {}", ByteArray.bytesToHexString(bytes));
+
+ if (bytes.length != (msgHeader.getLength() - PCEPMessageHeader.COMMON_HEADER_LENGTH))
+ throw new DeserializerException("Size don't match size specified in header. Passed: " + bytes.length + "; Expected: "
+ + (msgHeader.getLength() - PCEPMessageHeader.COMMON_HEADER_LENGTH) + ". " + msgHeader.getLength());
+
+ /*
+ * if PCEPObjectIdentifier.getObjectClassFromInt() dont't throws
+ * exception and if returned null we know the error type
+ */
+ PCEPMessageType msgType;
+ try {
+ msgType = PCEPMessageType.getFromInt(msgHeader.getType());
+ } catch (final PCEPDeserializerException e) {
+ throw new DeserializerException(e.getMessage(), e);
+ }
+ if (msgType == null)
+ throw new DocumentedException("Unhandled message type " + msgHeader.getType(), new PCEPDocumentedException("Unhandled message type " + msgHeader.getType(), PCEPErrors.CAPABILITY_NOT_SUPPORTED));
+
+ PCEPMessage msg;
+ try {
+ msg = new PCEPRawMessage(PCEPObjectFactory.parseObjects(bytes), msgType);
+ } catch (final PCEPDeserializerException e) {
+ throw new DeserializerException(e.getMessage(), e);
+ } catch (final PCEPDocumentedException e) {
+ throw new DocumentedException(e.getMessage(), e);
+ }
+ logger.debug("Message was parsed. {}", msg);
+ return msg;
+ }
+
+ @Override
+ public byte[] put(final ProtocolMessage msg) {
+ final PCEPMessage pcepMsg = (PCEPMessage) msg;
+ if (pcepMsg == null)
+ throw new IllegalArgumentException("PCEPMessage is mandatory.");
+
+ final PCEPMessageType msgType;
+
+ if (pcepMsg instanceof PCEPOpenMessage) {
+ msgType = PCEPMessageType.OPEN;
+ } else if (pcepMsg instanceof PCEPKeepAliveMessage) {
+ msgType = PCEPMessageType.KEEPALIVE;
+ } else if (pcepMsg instanceof PCEPCloseMessage) {
+ msgType = PCEPMessageType.CLOSE;
+ } else if (pcepMsg instanceof PCEPReplyMessage) {
+ msgType = PCEPMessageType.RESPONSE;
+ } else if (pcepMsg instanceof PCEPRequestMessage) {
+ msgType = PCEPMessageType.REQUEST;
+ } else if (pcepMsg instanceof PCEPNotificationMessage) {
+ msgType = PCEPMessageType.NOTIFICATION;
+ } else if (pcepMsg instanceof PCEPErrorMessage) {
+ msgType = PCEPMessageType.ERROR;
+ } else if (pcepMsg instanceof PCEPReportMessage) {
+ msgType = PCEPMessageType.STATUS_REPORT;
+ } else if (pcepMsg instanceof PCEPUpdateRequestMessage) {
+ msgType = PCEPMessageType.UPDATE_REQUEST;
+ } else if (pcepMsg instanceof PCEPXRAddTunnelMessage) {
+ msgType = PCEPMessageType.XR_ADD_TUNNEL;
+ } else if (pcepMsg instanceof PCEPXRDeleteTunnelMessage) {
+ msgType = PCEPMessageType.XR_DELETE_TUNNEL;
+ } else if (pcepMsg instanceof PCCreateMessage) {
+ msgType = PCEPMessageType.PCCREATE;
+ } else {
+ logger.error("Unknown instance of PCEPMessage. Message class: {}", pcepMsg.getClass());
+ throw new IllegalArgumentException("Unknown instance of PCEPMessage. Passed " + pcepMsg.getClass());
+ }
+
+ logger.trace("Serializing {}", msgType);
+
+ final byte[] msgBody = MapOfParsers.getInstance().get(msgType).put(pcepMsg);
+
+ final PCEPMessageHeader msgHeader = new PCEPMessageHeader(msgType.getIdentifier(), msgBody.length + PCEPMessageHeader.COMMON_HEADER_LENGTH,
+ PCEPMessage.PCEP_VERSION);
+
+ final byte[] headerBytes = msgHeader.toBytes();
+ final byte[] retBytes = new byte[headerBytes.length + msgBody.length];
+
+ ByteArray.copyWhole(headerBytes, retBytes, 0);
+ ByteArray.copyWhole(msgBody, retBytes, PCEPMessageHeader.COMMON_HEADER_LENGTH);
+
+ return retBytes;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.ProtocolMessageHeader;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Header parser for {@link org.opendaylight.protocol.pcep.PCEPMessage PCEPMessage}
+ */
+public final class PCEPMessageHeader implements ProtocolMessageHeader {
+
+ public static final Logger logger = LoggerFactory.getLogger(PCEPMessageHeader.class);
+
+ /*
+ * lengths of fields in bytes
+ */
+ private static final int VER_FLAGS_MF_LENGTH = 1;
+ private static final int TYPE_F_LENGTH = 1;
+ private static final int LENGTH_F_LENGTH = 2;
+
+ /*
+ * lengths of subfields inside multi-field in bits
+ */
+ private static final int VERSION_SF_LENGTH = 3;
+
+ /*
+ * offsets of field in bytes
+ */
+ private static final int VER_FLAGS_MF_OFFSET = 0;
+ private static final int TYPE_F_OFFSET = VER_FLAGS_MF_LENGTH + VER_FLAGS_MF_OFFSET;
+ private static final int LENGTH_F_OFFSET = TYPE_F_LENGTH + TYPE_F_OFFSET;
+
+ /*
+ * offsets of subfields inside multi-filed in bits
+ */
+
+ private static final int VERSION_SF_OFFSET = 0;
+
+ /*
+ * COMMON HEADER LENGTH
+ */
+ public static final int COMMON_HEADER_LENGTH = VER_FLAGS_MF_LENGTH + TYPE_F_LENGTH + LENGTH_F_LENGTH;
+
+ private int type;
+ private int length;
+ private int version;
+
+ private boolean parsed = false;
+
+ public PCEPMessageHeader() {
+
+ }
+
+ public PCEPMessageHeader(final int type, final int length, final int version) {
+ this.type = type;
+ this.length = length;
+ this.version = version;
+ }
+
+ public PCEPMessageHeader fromBytes(final byte[] bytes) {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory");
+
+ logger.trace("Attempt to parse message header: {}", ByteArray.bytesToHexString(bytes));
+
+ if (bytes.length < COMMON_HEADER_LENGTH)
+ throw new IllegalArgumentException("Too few bytes in passed array. Passed: " + bytes.length + "; Expected: >= " + COMMON_HEADER_LENGTH + ".");
+
+ this.type = UnsignedBytes.toInt(bytes[TYPE_F_OFFSET]);
+
+ this.length = ByteArray.bytesToInt(Arrays.copyOfRange(bytes,
+ LENGTH_F_OFFSET, LENGTH_F_OFFSET + LENGTH_F_LENGTH));
+
+ this.version = ByteArray.copyBitsRange(bytes[VER_FLAGS_MF_OFFSET], VERSION_SF_OFFSET, VERSION_SF_LENGTH);
+
+ logger.trace("Message header was parsed. {}", this);
+ this.parsed = true;
+ return this;
+ }
+
+ public byte[] toBytes() {
+ final byte[] retBytes = new byte[COMMON_HEADER_LENGTH];
+
+ // msgVer_Flag
+ retBytes[VER_FLAGS_MF_OFFSET] = (byte) (this.version << (Byte.SIZE - VERSION_SF_LENGTH));
+
+ // msgType
+ retBytes[TYPE_F_OFFSET] = (byte) this.type;
+
+ // msgLength
+ System.arraycopy(ByteArray.intToBytes(this.length), Integer.SIZE / Byte.SIZE - LENGTH_F_LENGTH, retBytes, LENGTH_F_OFFSET, LENGTH_F_LENGTH);
+
+ return retBytes;
+ }
+
+ public void setLength(final int length) {
+ this.length = length;
+ }
+
+ public void setType(final int type) {
+ this.type = type;
+ }
+
+ public void setVersion(final int version) {
+ this.version = version;
+ }
+
+ public int getLength() {
+ return this.length;
+ }
+
+ public int getVersion() {
+ return this.version;
+ }
+
+ public int getType() {
+ return this.type;
+ }
+
+ /**
+ * @return the parsed
+ */
+ public boolean isParsed() {
+ return this.parsed;
+ }
+
+ /**
+ * @param parsed the parsed to set
+ */
+ public void setParsed() {
+ this.parsed = false;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPMessageHeader [type=");
+ builder.append(this.type);
+ builder.append(", length=");
+ builder.append(this.length);
+ builder.append(", version=");
+ builder.append(this.version);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+
+/**
+ * Interface for specific message parsers
+ */
+public interface PCEPMessageParser {
+
+ public byte[] put(PCEPMessage obj);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageFactory.PCEPMessageType;
+import org.opendaylight.protocol.pcep.impl.message.PCCreateMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPCloseMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPErrorMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPKeepAliveMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPNotificationMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPOpenMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPReplyMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPReportMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRequestMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPUpdateRequestMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPXRAddTunnelMessageValidator;
+import org.opendaylight.protocol.pcep.impl.message.PCEPXRDeleteTunnelMessageValidator;
+
+/**
+ * Base class for message validators
+ */
+public abstract class PCEPMessageValidator {
+
+ private static class MapOfValidators extends HashMap<PCEPMessageType, PCEPMessageValidator> {
+
+ private static final long serialVersionUID = -5715193806554448822L;
+
+ private final static MapOfValidators instance = new MapOfValidators();
+
+ private MapOfValidators() {
+ this.fillInMap();
+ }
+
+ private void fillInMap() {
+ this.put(PCEPMessageType.OPEN, new PCEPOpenMessageValidator());
+ this.put(PCEPMessageType.KEEPALIVE, new PCEPKeepAliveMessageValidator());
+ this.put(PCEPMessageType.NOTIFICATION, new PCEPNotificationMessageValidator());
+ this.put(PCEPMessageType.ERROR, new PCEPErrorMessageValidator());
+ this.put(PCEPMessageType.RESPONSE, new PCEPReplyMessageValidator());
+ this.put(PCEPMessageType.REQUEST, new PCEPRequestMessageValidator());
+ this.put(PCEPMessageType.UPDATE_REQUEST, new PCEPUpdateRequestMessageValidator());
+ this.put(PCEPMessageType.STATUS_REPORT, new PCEPReportMessageValidator());
+ this.put(PCEPMessageType.CLOSE, new PCEPCloseMessageValidator());
+ this.put(PCEPMessageType.XR_ADD_TUNNEL, new PCEPXRAddTunnelMessageValidator());
+ this.put(PCEPMessageType.XR_DELETE_TUNNEL, new PCEPXRDeleteTunnelMessageValidator());
+ this.put(PCEPMessageType.PCCREATE, new PCCreateMessageValidator());
+ }
+
+ public static MapOfValidators getInstance() {
+ return instance;
+ }
+ }
+
+ public abstract List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException;
+
+ public static PCEPMessageValidator getValidator(final PCEPMessageType msgType) {
+ return MapOfValidators.getInstance().get(msgType);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+
+/**
+ * Mapping of enumerable objective function codes to integral identifiers and
+ * vice-versa.
+ */
+public class PCEPOFCodesMapping {
+ private static final PCEPOFCodesMapping instance = new PCEPOFCodesMapping();
+
+ private final Map<PCEPOFCodes, Integer> ofCodesMap = new EnumMap<PCEPOFCodes, Integer>(PCEPOFCodes.class);
+ private final Map<Integer, PCEPOFCodes> ofCodeIdsMap = new HashMap<Integer, PCEPOFCodes>();
+
+ private PCEPOFCodesMapping() {
+ this.fillIn();
+ }
+
+ private void fillIn() {
+ this.fillIn(1, PCEPOFCodes.MCP);
+ this.fillIn(2, PCEPOFCodes.MLP);
+ this.fillIn(3, PCEPOFCodes.MBP);
+ this.fillIn(4, PCEPOFCodes.MBC);
+ this.fillIn(5, PCEPOFCodes.MLL);
+ this.fillIn(6, PCEPOFCodes.MCC);
+ this.fillIn(7, PCEPOFCodes.SPT);
+ this.fillIn(8, PCEPOFCodes.MCT);
+ }
+
+ private void fillIn(int identifier, PCEPOFCodes ofCode) {
+ this.ofCodesMap.put(ofCode, identifier);
+ this.ofCodeIdsMap.put(identifier, ofCode);
+ }
+
+ public int getFromOFCodesEnum(PCEPOFCodes ofCode) {
+ final Integer ofci = this.ofCodesMap.get(ofCode);
+ if (ofci == null)
+ throw new NoSuchElementException("Unknown PCEPOFCodes type: " + ofCode);
+ return ofci;
+ }
+
+ public PCEPOFCodes getFromCodeIdentifier(int identifier) {
+ final PCEPOFCodes ofc = this.ofCodeIdsMap.get(identifier);
+ if (ofc == null)
+ throw new NoSuchElementException("Unknown PCEPOFCode identifier.");
+ return ofc;
+ }
+
+ public static PCEPOFCodesMapping getInstance() {
+ return instance;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectIdentifier.ObjectClass;
+import org.opendaylight.protocol.pcep.impl.object.PCEPBranchNodeListObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPCloseObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPEndPointsIPv4ObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPEndPointsIPv6ObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPErrorObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPExcludeRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPExistingPathBandwidthObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPExplicitRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPGlobalConstraintsObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPIncludeRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPLoadBalancingObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPLspObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPLspaObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPMetricObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPNoPathObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPNonBranchNodeListObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPNotificationObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPObjectiveFunctionObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPOpenObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPP2MPEndPointsIPv4ObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPP2MPEndPointsIPv6ObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPReportedRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPRequestParameterObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPRequestedPathBandwidthObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPSecondaryExplicitRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPSecondaryRecordRouteObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPSvecObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPUnreachedIPv4DestinationObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPUnreachedIPv6DestinationObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.object.PCEPBranchNodeListObject;
+import org.opendaylight.protocol.pcep.object.PCEPBranchNodeObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNonBranchNodeListObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryRecordRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.pcep.object.PCEPUnreachedDestinationObject;
+
+/**
+ * Factory for subclasses of {@link org.opendaylight.protocol.pcep.PCEPObject PCEPObject}
+ */
+public class PCEPObjectFactory {
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPObjectFactory.class);
+
+ /**
+ * Map of parsers for subobjects of {@link org.opendaylight.protocol.pcep.PCEPObject
+ * PCEPObject}
+ */
+ private static class MapOfParsers extends HashMap<PCEPObjectIdentifier, PCEPObjectParser> {
+ private static final long serialVersionUID = 1L;
+
+ private final static MapOfParsers instance = new MapOfParsers();
+
+ private MapOfParsers() {
+ this.fillInMap();
+ }
+
+ private void fillInMap() {
+ this.put(new PCEPObjectIdentifier(ObjectClass.OPEN, 1), new PCEPOpenObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.RP, 1), new PCEPRequestParameterObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.NO_PATH, 1), new PCEPNoPathObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.BANDWIDTH, 1), new PCEPRequestedPathBandwidthObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.BANDWIDTH, 2), new PCEPExistingPathBandwidthObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.METRIC, 1), new PCEPMetricObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 1), new PCEPEndPointsIPv4ObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 2), new PCEPEndPointsIPv6ObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.LSPA, 1), new PCEPLspaObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.SVEC, 1), new PCEPSvecObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.NOTIFICATION, 1), new PCEPNotificationObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.ERROR, 1), new PCEPErrorObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.CLOSE, 1), new PCEPCloseObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.LOAD_BALANCING, 1), new PCEPLoadBalancingObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.LSP, 1), new PCEPLspObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.ERO, 1), new PCEPExplicitRouteObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.RRO, 1), new PCEPReportedRouteObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.IRO, 1), new PCEPIncludeRouteObjectParser());
+
+ /* GCO extension */
+ this.put(new PCEPObjectIdentifier(ObjectClass.XRO, 1), new PCEPExcludeRouteObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.OBJCETIVE_FUNCTION, 1), new PCEPObjectiveFunctionObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.GLOBAL_CONSTRAINTS, 1), new PCEPGlobalConstraintsObjectParser());
+
+ /* RFC6006 */
+ this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 3), new PCEPP2MPEndPointsIPv4ObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 4), new PCEPP2MPEndPointsIPv6ObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.UNREACHED_DESTINATION, 1), new PCEPUnreachedIPv4DestinationObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.UNREACHED_DESTINATION, 2), new PCEPUnreachedIPv6DestinationObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.SERO, 1), new PCEPSecondaryExplicitRouteObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.SRRO, 1), new PCEPSecondaryRecordRouteObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.BRANCH_NODE, 1), new PCEPBranchNodeListObjectParser());
+ this.put(new PCEPObjectIdentifier(ObjectClass.BRANCH_NODE, 2), new PCEPNonBranchNodeListObjectParser());
+ }
+
+ public static MapOfParsers getInstance() {
+ return instance;
+ }
+ }
+
+ private static PCEPObject parse(final byte[] bytes, final PCEPObjectHeader header) throws PCEPDocumentedException, PCEPDeserializerException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory.");
+ if (header == null)
+ throw new IllegalArgumentException("PCEPObjectHeader is mandatory.");
+
+ logger.trace("Attempt to parse object from bytes: {}", ByteArray.bytesToHexString(bytes));
+
+ /*
+ * if PCEPObjectIdentifier.getObjectClassFromInt() don't throws
+ * exception and if Map.get() returns null, we know that we can't
+ * recognize OBJ TYPE.
+ */
+ final PCEPObjectParser objParserClass = MapOfParsers.getInstance().get(
+ new PCEPObjectIdentifier(PCEPObjectIdentifier.ObjectClass.getFromInt(header.objClass), header.objType));
+ if (objParserClass == null) {
+ logger.debug("Object could not be parsed. Header: {}. Body bytes: {}", header, Arrays.toString(bytes));
+ throw new PCEPDocumentedException("Unrecognized object type: " + header.objType + " for object class: " + header.objClass,
+ PCEPErrors.UNRECOGNIZED_OBJ_TYPE);
+ }
+ final PCEPObject obj = objParserClass.parse(bytes, header.processed, header.ignored);
+ logger.trace("Object was parsed. {}", obj);
+ return obj;
+ }
+
+ public static List<PCEPObject> parseObjects(final byte[] bytes) throws PCEPDeserializerException, PCEPDocumentedException {
+ int offset = 0;
+ final List<PCEPObject> objs = new ArrayList<PCEPObject>();
+
+ while (bytes.length - offset > 0) {
+ if (bytes.length - offset < PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH)
+ throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + (bytes.length - offset) + " Expected: >= "
+ + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH + ".");
+
+ final PCEPObjectHeader header = PCEPObjectHeader.parseHeader(Arrays.copyOfRange(bytes, offset, offset
+ + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH));
+
+ if (bytes.length - offset < header.objLength)
+ throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + (bytes.length - offset) + " Expected: >= " + header.objLength
+ + ".");
+
+ // copy bytes for deeper parsing
+ final byte[] bytesToPass = ByteArray.subByte(bytes, offset + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH, header.objLength
+ - PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH);
+
+ offset += header.objLength;
+
+ // if obj is not-supported or unrecognized and p flag si set
+ // adds UnknownObject to list for validation purposes
+ try {
+ objs.add(PCEPObjectFactory.parse(bytesToPass, header));
+ } catch (final PCEPDocumentedException e) {
+ if (e.getError() == PCEPErrors.UNRECOGNIZED_OBJ_CLASS | e.getError() == PCEPErrors.UNRECOGNIZED_OBJ_TYPE
+ | e.getError() == PCEPErrors.NOT_SUPPORTED_OBJ_CLASS | e.getError() == PCEPErrors.NOT_SUPPORTED_OBJ_TYPE) {
+ objs.add(new UnknownObject(header.processed, header.ignored, e.getError()));
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ return objs;
+ }
+
+ public static byte[] put(final List<PCEPObject> objects) {
+ if (objects == null || objects.isEmpty())
+ throw new IllegalArgumentException("List<PCEPObject> is mandatory and can't be empty.");
+
+ final List<byte[]> listBytes = new ArrayList<byte[]>();
+
+ byte[] bytes;
+ int size = 0;
+ for (final PCEPObject obj : objects) {
+ bytes = put(obj);
+ size += bytes.length;
+ listBytes.add(bytes);
+ }
+
+ final byte[] retBytes = new byte[size];
+
+ int offset = 0;
+ for (final byte[] bs : listBytes) {
+ ByteArray.copyWhole(bs, retBytes, offset);
+ offset += bs.length;
+ }
+
+ return retBytes;
+ }
+
+ private static byte[] put(final PCEPObject obj) {
+
+ byte[] objBody;
+ ObjectClass objClass;
+ int objType = 1;
+
+ if (obj instanceof PCEPOpenObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.OPEN;
+ } else if (obj instanceof PCEPRequestParameterObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.RP;
+ } else if (obj instanceof PCEPNoPathObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.NO_PATH;
+ } else if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.BANDWIDTH;
+ } else if (obj instanceof PCEPExistingPathBandwidthObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.BANDWIDTH;
+ objType = 2;
+ } else if (obj instanceof PCEPMetricObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.METRIC;
+ } else if (obj instanceof PCEPEndPointsObject<?>) {
+ objClass = PCEPObjectIdentifier.ObjectClass.END_POINTS;
+ if (((PCEPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv6Address) {
+ objType = 2;
+ } else if (!(((PCEPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv4Address))
+ throw new IllegalArgumentException("Unknown instance of Source Address.");
+
+ } else if (obj instanceof PCEPP2MPEndPointsObject<?>) {
+ objClass = PCEPObjectIdentifier.ObjectClass.END_POINTS;
+ objType = 3;
+ if (((PCEPP2MPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv6Address) {
+ objType = 4;
+ } else if (!(((PCEPP2MPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv4Address))
+ throw new IllegalArgumentException("Unknown instance of Source Address.");
+
+ } else if (obj instanceof PCEPUnreachedDestinationObject<?>) {
+ objClass = PCEPObjectIdentifier.ObjectClass.UNREACHED_DESTINATION;
+ if (((PCEPUnreachedDestinationObject<?>) obj).getUnreachedDestinations().get(0) instanceof IPv6Address) {
+ objType = 2;
+ } else if (!(((PCEPUnreachedDestinationObject<?>) obj).getUnreachedDestinations().get(0) instanceof IPv4Address))
+ throw new IllegalArgumentException("Unknown instance of Source Address.");
+
+ } else if (obj instanceof PCEPLspaObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.LSPA;
+ } else if (obj instanceof PCEPSvecObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.SVEC;
+ objType = 1;
+ } else if (obj instanceof PCEPNotificationObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.NOTIFICATION;
+ } else if (obj instanceof PCEPErrorObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.ERROR;
+ } else if (obj instanceof PCEPCloseObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.CLOSE;
+ } else if (obj instanceof PCEPLoadBalancingObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.LOAD_BALANCING;
+ } else if (obj instanceof PCEPLspObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.LSP;
+ } else if (obj instanceof PCEPExplicitRouteObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.ERO;
+ } else if (obj instanceof PCEPReportedRouteObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.RRO;
+ } else if (obj instanceof PCEPIncludeRouteObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.IRO;
+ } else if (obj instanceof PCEPExcludeRouteObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.XRO;
+ } else if (obj instanceof PCEPObjectiveFunctionObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.OBJCETIVE_FUNCTION;
+ } else if (obj instanceof PCEPGlobalConstraintsObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.GLOBAL_CONSTRAINTS;
+ } else if (obj instanceof PCEPBranchNodeObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.BRANCH_NODE;
+ if (obj instanceof PCEPNonBranchNodeListObject) {
+ objType = 2;
+ } else if (!(obj instanceof PCEPBranchNodeListObject))
+ throw new IllegalArgumentException("Unknown instance of PCEPBranchNodeObject.");
+ } else if (obj instanceof PCEPSecondaryExplicitRouteObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.SERO;
+ } else if (obj instanceof PCEPSecondaryRecordRouteObject) {
+ objClass = PCEPObjectIdentifier.ObjectClass.SRRO;
+ } else
+ throw new IllegalArgumentException("Unknown instance of PCEPObject.");
+
+ final PCEPObjectParser objParserClass = MapOfParsers.getInstance().get(new PCEPObjectIdentifier(objClass, objType));
+ objBody = objParserClass.put(obj);
+
+ final byte[] objHeader = PCEPObjectHeader.putHeader(new PCEPObjectHeader(objClass.getIdentifier(), objType, objBody.length
+ + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH, obj.isProcessed(), obj.isIgnored()));
+
+ assert objBody.length % 4 == 0 : "Wrong length of PCEPObjectBody. Passed object has length: " + objBody.length + " that is not multiple of 4.";
+
+ final byte[] retBytes = new byte[objHeader.length + objBody.length];
+ ByteArray.copyWhole(objHeader, retBytes, 0);
+ ByteArray.copyWhole(objBody, retBytes, PCEPObjectHeader.OBJ_BODY_OFFSET);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Header parser for {@link org.opendaylight.protocol.pcep.PCEPObject PCEPObject}
+ */
+public class PCEPObjectHeader {
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPObjectHeader.class);
+
+ /*
+ * Common object header fields lengths in bytes
+ */
+ public final static int OC_F_LENGTH = 1;
+ public final static int OT_FLAGS_MF_LENGTH = 1; // multi-field
+ public final static int OBJ_LENGTH_F_LENGTH = 2;
+
+ /*
+ * size of fields inside of multi-filed in bits
+ */
+ public final static int OT_SF_LENGTH = 4;
+ public final static int FLAGS_SF_LENGTH = 4;
+
+ /*
+ * offsets of fields inside of multi-field in bits
+ */
+ public final static int OT_SF_OFFSET = 0;
+ public final static int FLAGS_SF_OFFSET = OT_SF_OFFSET + OT_SF_LENGTH;
+
+ /*
+ * flags offsets inside multi-filed
+ */
+ public final static int P_FLAG_OFFSET = 6;
+ public final static int I_FLAG_OFFSET = 7;
+
+ /*
+ * Common object header fields offsets in bytes;
+ */
+ public final static int OC_F_OFFSET = 0;
+ public final static int OT_FLAGS_MF_OFFSET = OC_F_OFFSET + OC_F_LENGTH;
+ public final static int OBJ_LENGTH_F_OFFSET = OT_FLAGS_MF_OFFSET + OT_FLAGS_MF_LENGTH;
+ public final static int OBJ_BODY_OFFSET = OBJ_LENGTH_F_OFFSET + OBJ_LENGTH_F_LENGTH;
+
+ /*
+ * Common object header length in bytes
+ */
+ public final static int COMMON_OBJECT_HEADER_LENGTH = (OC_F_LENGTH + OT_FLAGS_MF_LENGTH + OBJ_LENGTH_F_LENGTH);
+
+ public final int objClass;
+ public final int objType;
+ public final int objLength;
+ public final boolean processed;
+ public final boolean ignored;
+
+ public PCEPObjectHeader(final int objClass, final int objType, final int objLength, final boolean processed, final boolean ignore) {
+ this.objClass = objClass;
+ this.objType = objType;
+ this.objLength = objLength;
+ this.processed = processed;
+ this.ignored = ignore;
+
+ }
+
+ public static PCEPObjectHeader parseHeader(final byte[] bytes) {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory.");
+
+ logger.trace("Attempt to parse object header from bytes: {}", ByteArray.bytesToHexString(bytes));
+
+ final int objClass = ByteArray.bytesToInt(Arrays.copyOfRange(bytes, OC_F_OFFSET, OC_F_OFFSET + OC_F_LENGTH));
+
+ final int objType = UnsignedBytes.toInt(ByteArray.copyBitsRange(bytes[OT_FLAGS_MF_OFFSET], OT_SF_OFFSET, OT_SF_LENGTH));
+
+ final int objLength = ByteArray.bytesToInt(Arrays.copyOfRange(bytes, OBJ_LENGTH_F_OFFSET, OBJ_LENGTH_F_OFFSET + OBJ_LENGTH_F_LENGTH));
+
+ final byte[] flagsBytes = { ByteArray.copyBitsRange(bytes[OT_FLAGS_MF_OFFSET], FLAGS_SF_OFFSET, FLAGS_SF_LENGTH) };
+
+ final BitSet flags = ByteArray.bytesToBitSet(flagsBytes);
+
+ final PCEPObjectHeader objHeader = new PCEPObjectHeader(objClass, objType, objLength, flags.get(P_FLAG_OFFSET), flags.get(I_FLAG_OFFSET));
+ logger.trace("Object header was parsed. {}", objHeader);
+ return objHeader;
+ }
+
+ public static byte[] putHeader(final PCEPObjectHeader header) {
+ if (header == null)
+ throw new IllegalArgumentException("PCEPObjectHeader is mandatory.");
+
+ final byte[] retBytes = new byte[COMMON_OBJECT_HEADER_LENGTH];
+
+ // objClass
+ retBytes[OC_F_OFFSET] = (byte) header.objClass;
+
+ // objType_flags multi-field
+ retBytes[OT_FLAGS_MF_OFFSET] = (byte) (header.objType << (Byte.SIZE - OT_SF_LENGTH));
+ if (header.processed)
+ retBytes[OT_FLAGS_MF_OFFSET] |= 1 << Byte.SIZE - (P_FLAG_OFFSET) - 1;
+ if (header.ignored)
+ retBytes[OT_FLAGS_MF_OFFSET] |= 1 << Byte.SIZE - (I_FLAG_OFFSET) - 1;
+
+ // objLength
+ System.arraycopy(ByteArray.intToBytes(header.objLength), Integer.SIZE / Byte.SIZE - OBJ_LENGTH_F_LENGTH, retBytes, OBJ_LENGTH_F_OFFSET,
+ OBJ_LENGTH_F_LENGTH);
+
+ return retBytes;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPObjectHeader [objClass=");
+ builder.append(this.objClass);
+ builder.append(", objType=");
+ builder.append(this.objType);
+ builder.append(", objLength=");
+ builder.append(this.objLength);
+ builder.append(", processed=");
+ builder.append(this.processed);
+ builder.append(", ignored=");
+ builder.append(this.ignored);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.ignored ? 1231 : 1237);
+ result = prime * result + this.objClass;
+ result = prime * result + this.objLength;
+ result = prime * result + this.objType;
+ result = prime * result + (this.processed ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPObjectHeader other = (PCEPObjectHeader) obj;
+ if (this.ignored != other.ignored)
+ return false;
+ if (this.objClass != other.objClass)
+ return false;
+ if (this.objLength != other.objLength)
+ return false;
+ if (this.objType != other.objType)
+ return false;
+ if (this.processed != other.processed)
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+
+/**
+ * PCEP objects are identified with a couple <class, type>.
+ */
+public class PCEPObjectIdentifier {
+ /**
+ * Class identifier for {@link org.opendaylight.protocol.pcep.PCEPObject PCEPObject}
+ */
+ public static enum ObjectClass {
+ OPEN(1),
+ RP(2),
+ NO_PATH(3),
+ END_POINTS(4),
+ BANDWIDTH(5),
+ METRIC(6),
+ ERO(7),
+ RRO(8),
+ LSPA(9),
+ IRO(10),
+ SVEC(11),
+ NOTIFICATION(12),
+ ERROR(13),
+ LOAD_BALANCING(14),
+ CLOSE(15),
+ XRO(17),
+ OBJCETIVE_FUNCTION(21),
+ GLOBAL_CONSTRAINTS(24),
+ UNREACHED_DESTINATION(28),
+ SERO(29),
+ SRRO(30),
+ BRANCH_NODE(31),
+ LSP(32);
+
+ private final int identifier;
+
+ ObjectClass(final int identifier) {
+ this.identifier = identifier;
+ }
+
+ public int getIdentifier() {
+ return this.identifier;
+ }
+
+ public static ObjectClass getFromInt(int identifier) throws PCEPDocumentedException {
+ for (final ObjectClass type_e : ObjectClass.values()) {
+ if (type_e.getIdentifier() == identifier)
+ return type_e;
+ }
+
+ throw new PCEPDocumentedException("Unrecognized object class " + identifier, PCEPErrors.UNRECOGNIZED_OBJ_CLASS);
+ }
+ }
+
+ private final int objectType;
+
+ private final ObjectClass objectClass;
+
+ public PCEPObjectIdentifier(ObjectClass objectClass, int objectType) {
+ this.objectType = objectType;
+ this.objectClass = objectClass;
+ }
+
+ public int getObjectType() {
+ return this.objectType;
+ }
+
+ public ObjectClass getObjectClass() {
+ return this.objectClass;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.objectClass == null) ? 0 : this.objectClass.hashCode());
+ result = prime * result + this.objectType;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPObjectIdentifier other = (PCEPObjectIdentifier) obj;
+ if (this.objectClass != other.objectClass)
+ return false;
+ if (this.objectType != other.objectType)
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+/**
+ * Interface for {@link org.opendaylight.protocol.pcep.PCEPObject PCEPObject} subobjects
+ */
+public interface PCEPObjectParser {
+ public abstract PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException;
+
+ public abstract byte[] put(PCEPObject obj);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.subobject.RROAttributesSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROIPv4AddressSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROIPv6AddressSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROLabelSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROPathKeyWith128PCEIDSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROPathKeyWith32PCEIDSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROProtectionSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.RROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.RROAttributesSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.PCEPSubobject PCEPSubobject}
+ */
+public class PCEPRROSubobjectParser {
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPRROSubobjectParser.class);
+
+ /**
+ * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPSubobject
+ * PCEPSubobject}
+ */
+ public enum PCEPSubobjectType {
+ IPv4_PREFIX(1), IPv6_PREFIX(2), LABEL(3), UNNUMBERED_INTERFACE_ID(4), ATTRIBUTES(5), PROTECTION(37), PK_32(64), PK_128(65);
+
+ private final int indicator;
+
+ PCEPSubobjectType(final int indicator) {
+ this.indicator = indicator;
+ }
+
+ public int getIndicator() {
+ return this.indicator;
+ }
+
+ public static PCEPSubobjectType getFromInt(final int type) throws PCEPDeserializerException {
+
+ for (final PCEPSubobjectType type_e : PCEPSubobjectType.values()) {
+ if (type_e.getIndicator() == type)
+ return type_e;
+ }
+
+ throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + "; Known: " + PCEPSubobjectType.values() + ".");
+ }
+ }
+
+ /*
+ * Fields lengths in Bytes
+ */
+ public static final int TYPE_F_LENGTH = 1;
+ public static final int LENGTH_F_LENGTH = 1;
+
+ /*
+ * Fields offsets in Bytes
+ */
+ public static final int TYPE_F_OFFSET = 0;
+ public static final int LENGTH_F_OFFSET = TYPE_F_OFFSET + TYPE_F_LENGTH;
+ public static final int SO_CONTENTS_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
+
+ public static List<ReportedRouteSubobject> parse(final byte[] bytes) throws PCEPDeserializerException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Byte array is mandatory.");
+
+ final List<ReportedRouteSubobject> subobjsList = new ArrayList<ReportedRouteSubobject>();
+ PCEPSubobjectType type;
+ byte[] soContentsBytes;
+ int length;
+ int offset = 0;
+
+ while (offset < bytes.length) {
+ length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
+
+ type = PCEPSubobjectType.getFromInt(bytes[offset + TYPE_F_OFFSET] & 0xff);
+
+ if (length > bytes.length - offset)
+ throw new PCEPDeserializerException("Wrong length specified. Passed: " + length + "; Expected: <= " + (bytes.length - offset));
+
+ soContentsBytes = new byte[length - SO_CONTENTS_OFFSET];
+ System.arraycopy(bytes, offset + SO_CONTENTS_OFFSET, soContentsBytes, 0, length - SO_CONTENTS_OFFSET);
+
+ logger.trace("Attempt to parse subobject from bytes: {}", ByteArray.bytesToHexString(soContentsBytes));
+ final ReportedRouteSubobject subObj = parseSpecificSubobject(type, soContentsBytes);
+ logger.trace("Subobject was parsed. {}", subObj);
+
+ subobjsList.add(subObj);
+
+ offset += length;
+ }
+
+ return subobjsList;
+ }
+
+ public static byte[] put(final List<ReportedRouteSubobject> objsToSerialize) {
+ final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
+
+ int length = 0;
+ for (final ReportedRouteSubobject obj : objsToSerialize) {
+ final byte[] bytes = put(obj);
+ length += bytes.length;
+ bytesList.add(bytes);
+ }
+
+ final byte[] retBytes = new byte[length];
+
+ int offset = 0;
+ for (final byte[] bytes : bytesList) {
+ System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
+ offset += bytes.length;
+ }
+
+ return retBytes;
+ }
+
+ public static byte[] put(final ReportedRouteSubobject objToSerialize) {
+ int typeIndicator = 0;
+
+ final byte[] soContentsBytes;
+
+ if (objToSerialize instanceof RROIPAddressSubobject<?> && ((RROIPAddressSubobject<?>) objToSerialize).getPrefix() instanceof IPv4Prefix) {
+ typeIndicator = PCEPSubobjectType.IPv4_PREFIX.getIndicator();
+ soContentsBytes = RROIPv4AddressSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof RROIPAddressSubobject<?> && ((RROIPAddressSubobject<?>) objToSerialize).getPrefix() instanceof IPv6Prefix) {
+ typeIndicator = PCEPSubobjectType.IPv6_PREFIX.getIndicator();
+ soContentsBytes = RROIPv6AddressSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof RROUnnumberedInterfaceSubobject) {
+ typeIndicator = PCEPSubobjectType.UNNUMBERED_INTERFACE_ID.getIndicator();
+ soContentsBytes = RROUnnumberedInterfaceSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof RROLabelSubobject) {
+ typeIndicator = PCEPSubobjectType.LABEL.getIndicator();
+ soContentsBytes = RROLabelSubobjectParser.put((RROLabelSubobject) objToSerialize);
+ } else if (objToSerialize instanceof RROProtectionSubobject) {
+ typeIndicator = PCEPSubobjectType.PROTECTION.getIndicator();
+ soContentsBytes = RROProtectionSubobjectParser.put((RROProtectionSubobject) objToSerialize);
+ } else if (objToSerialize instanceof RROPathKeyWith32PCEIDSubobject) {
+ typeIndicator = PCEPSubobjectType.PK_32.getIndicator();
+ soContentsBytes = RROPathKeyWith32PCEIDSubobjectParser.put((RROPathKeyWith32PCEIDSubobject) objToSerialize);
+ } else if (objToSerialize instanceof RROPathKeyWith128PCEIDSubobject) {
+ typeIndicator = PCEPSubobjectType.PK_128.getIndicator();
+ soContentsBytes = RROPathKeyWith128PCEIDSubobjectParser.put((RROPathKeyWith128PCEIDSubobject) objToSerialize);
+ } else if (objToSerialize instanceof RROAttributesSubobject) {
+ typeIndicator = PCEPSubobjectType.ATTRIBUTES.getIndicator();
+ soContentsBytes = RROAttributesSubobjectParser.put((RROAttributesSubobject) objToSerialize);
+ } else
+ throw new IllegalArgumentException("Unknown instance of PCEPSubobject. Passed: " + objToSerialize.getClass() + ".");
+
+ final byte[] bytes = new byte[SO_CONTENTS_OFFSET + soContentsBytes.length];
+
+ bytes[TYPE_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_F_LENGTH)[0];
+ bytes[LENGTH_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(soContentsBytes.length + SO_CONTENTS_OFFSET), (Integer.SIZE / 8) - LENGTH_F_LENGTH)[0];
+
+ System.arraycopy(soContentsBytes, 0, bytes, SO_CONTENTS_OFFSET, soContentsBytes.length);
+
+ return bytes;
+ }
+
+ private static ReportedRouteSubobject parseSpecificSubobject(final PCEPSubobjectType type, final byte[] soContentsBytes) throws PCEPDeserializerException {
+
+ switch (type) {
+ case IPv4_PREFIX:
+ return RROIPv4AddressSubobjectParser.parse(soContentsBytes);
+ case IPv6_PREFIX:
+ return RROIPv6AddressSubobjectParser.parse(soContentsBytes);
+ case UNNUMBERED_INTERFACE_ID:
+ return RROUnnumberedInterfaceSubobjectParser.parse(soContentsBytes);
+ case LABEL:
+ return RROLabelSubobjectParser.parse(soContentsBytes);
+ case PROTECTION:
+ return RROProtectionSubobjectParser.parse(soContentsBytes);
+ case PK_32:
+ return RROPathKeyWith32PCEIDSubobjectParser.parse(soContentsBytes);
+ case PK_128:
+ return RROPathKeyWith128PCEIDSubobjectParser.parse(soContentsBytes);
+ case ATTRIBUTES:
+ return RROAttributesSubobjectParser.parse(soContentsBytes);
+ default:
+ throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + ".");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import org.opendaylight.protocol.framework.ProtocolConnection;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPSessionFactory;
+
+import java.util.Timer;
+
+public class PCEPSessionFactoryImpl implements PCEPSessionFactory {
+
+ private final int maxUnknownMessages;
+
+ public PCEPSessionFactoryImpl(final int maxUnknownMessages) {
+ this.maxUnknownMessages = maxUnknownMessages;
+ }
+
+ @Override
+ public ProtocolSession getProtocolSession(final SessionParent parent, final Timer timer,
+ final ProtocolConnection connection, final int sessionId) {
+ return new PCEPSessionImpl(parent, timer, (PCEPConnection)connection, new PCEPMessageFactory(),
+ this.maxUnknownMessages, sessionId);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.framework.ProtocolMessage;
+import org.opendaylight.protocol.framework.ProtocolMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolOutputStream;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+import org.opendaylight.protocol.pcep.PCEPCloseTermination;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPErrorTermination;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRawMessage;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * Implementation of PCEPSession. (Not final for testing.)
+ */
+class PCEPSessionImpl implements PCEPSession, ProtocolSession, PCEPSessionRuntimeMXBean {
+
+ /**
+ * KeepAlive Timer is to be scheduled periodically, each time it starts, it sends KeepAlive Message.
+ */
+ private class KeepAliveTimer extends TimerTask {
+ private final PCEPSessionImpl parent;
+
+ public KeepAliveTimer(final PCEPSessionImpl parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public void run() {
+ this.parent.handleKeepaliveTimer();
+ }
+ }
+
+ /**
+ * DeadTimer is to be scheduled periodically, when it expires, it closes PCEP session.
+ */
+ private class DeadTimer extends TimerTask {
+ private final PCEPSessionImpl parent;
+
+ public DeadTimer(final PCEPSessionImpl parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public void run() {
+ this.parent.handleDeadtimer();
+ }
+ }
+
+ /**
+ * OpenWaitTimer runs just once, but can be rescheduled or canceled before expiration. When it expires, it sends an
+ * error message (1, 2)
+ */
+ private class OpenWaitTimer extends TimerTask {
+
+ private final PCEPSessionImpl parent;
+
+ public OpenWaitTimer(final PCEPSessionImpl parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public void run() {
+ this.parent.handleOpenWait();
+ }
+ }
+
+ /**
+ * KeepWaitTimer runs just once, but can be rescheduled or canceled before expiration. When it expires, it sends an
+ * error message (1, 7)
+ */
+ private class KeepWaitTimer extends TimerTask {
+
+ private final PCEPSessionImpl parent;
+
+ public KeepWaitTimer(final PCEPSessionImpl parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public void run() {
+ this.parent.handleKeepWait();
+ }
+ }
+
+ /**
+ * Possible states for Finite State Machine
+ */
+ private enum State {
+ IDLE, OPEN_WAIT, KEEP_WAIT, UP
+ }
+
+ /**
+ * In seconds.
+ */
+ public static final int OPEN_WAIT_TIMER_VALUE = 60;
+
+ public static final int KEEP_WAIT_TIMER_VALUE = 60;
+
+ public int KEEP_ALIVE_TIMER_VALUE = 3;
+
+ public int DEAD_TIMER_VALUE = 4 * this.KEEP_ALIVE_TIMER_VALUE;
+
+ /**
+ * Actual state of the FSM.
+ */
+ private State state;
+
+ private OpenWaitTimer openWaitTimer;
+
+ private KeepWaitTimer keepWaitTimer;
+
+ /**
+ * System.nanoTime value about when was sent the last message Protected to be updated also in tests.
+ */
+ protected long lastMessageSentAt;
+
+ /**
+ * System.nanoTime value about when was received the last message
+ */
+ private long lastMessageReceivedAt;
+
+ private boolean localOK = false;
+
+ private boolean remoteOK = false;
+
+ private boolean openRetry = false;
+
+ private final int sessionId;
+
+ /**
+ * Protected for testing.
+ */
+ protected int maxUnknownMessages = 5;
+
+ protected final Queue<Long> unknownMessagesTimes = new LinkedList<Long>();
+
+ private final PCEPSessionListener listener;
+
+ private PCEPSessionProposalChecker checker = null;
+
+ /**
+ * Open Object with session characteristics that were accepted by another PCE (sent from this session).
+ */
+ private PCEPOpenObject localOpen = null;
+
+ /**
+ * Open Object with session characteristics for this session (sent from another PCE).
+ */
+ private PCEPOpenObject remoteOpen = null;
+
+ private final ProtocolOutputStream outputStream;
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPSessionImpl.class);
+
+ /**
+ * Timer object grouping FSM Timers
+ */
+ private final Timer stateTimer;
+
+ private final SessionParent parent;
+
+ private final PCEPMessageFactory factory;
+
+ private int sentMsgCount = 0;
+
+ private int receivedMsgCount = 0;
+
+ private final String peerAddress;
+
+ PCEPSessionImpl(final SessionParent parent, final Timer timer, final PCEPConnection connection, final PCEPMessageFactory factory,
+ final int maxUnknownMessages, final int sessionId) {
+ this.state = State.IDLE;
+ this.listener = connection.getListener();
+ this.checker = connection.getProposalChecker();
+ this.sessionId = sessionId;
+ this.localOpen = connection.getProposal().getOpenObject();
+ this.outputStream = new ProtocolOutputStream();
+ this.peerAddress = connection.getPeerAddress().getHostString();
+ this.stateTimer = timer;
+ this.parent = parent;
+ this.factory = factory;
+ if (this.maxUnknownMessages != 0)
+ this.maxUnknownMessages = maxUnknownMessages;
+ }
+
+ @Override
+ public void startSession() {
+ logger.debug("Session started.");
+ this.sendMessage(new PCEPOpenMessage(this.localOpen));
+ this.restartOpenWait();
+ this.changeState(State.OPEN_WAIT);
+ }
+
+ /**
+ * OpenWait timer can be canceled or rescheduled before its expiration. When it expires, it sends particular
+ * PCEPErrorMessage and closes PCEP session.
+ */
+ private synchronized void handleOpenWait() {
+ if (this.state != State.IDLE) {
+ this.terminate(PCEPErrors.NO_OPEN_BEFORE_EXP_OPENWAIT); // 1, 1
+ }
+ }
+
+ /**
+ * KeepWait timer can be canceled or rescheduled before its expiration. When it expires, it sends particular
+ * PCEPErrorMessage and closes PCEP session.
+ */
+ private synchronized void handleKeepWait() {
+ if (this.state != State.IDLE) {
+ this.terminate(PCEPErrors.NO_MSG_BEFORE_EXP_KEEPWAIT); // 1, 7
+ }
+ }
+
+ /**
+ * If DeadTimer expires, the session ends. If a message (whichever) was received during this period, the DeadTimer
+ * will be rescheduled by DEAD_TIMER_VALUE + the time that has passed from the start of the DeadTimer to the time at
+ * which the message was received. If the session was closed by the time this method starts to execute (the session
+ * state will become IDLE), that rescheduling won't occur.
+ */
+ private synchronized void handleDeadtimer() {
+ final long ct = System.nanoTime();
+
+ final long nextDead = (long) (this.lastMessageReceivedAt + (this.DEAD_TIMER_VALUE * 1E9));
+
+ if (this.state != State.IDLE) {
+ if (ct >= nextDead) {
+ logger.debug("DeadTimer expired. " + new Date());
+ this.terminate(Reason.EXP_DEADTIMER);
+ return;
+ }
+
+ this.stateTimer.schedule(new DeadTimer(this), (long) ((nextDead - ct) / 1E6));
+ }
+ }
+
+ /**
+ * If KeepAlive Timer expires, sends KeepAlive message. If a message (whichever) was send during this period, the
+ * KeepAlive Timer will be rescheduled by KEEP_ALIVE_TIMER_VALUE + the time that has passed from the start of the
+ * KeepAlive timer to the time at which the message was sent. If the session was closed by the time this method
+ * starts to execute (the session state will become IDLE), that rescheduling won't occur.
+ */
+ private synchronized void handleKeepaliveTimer() {
+ final long ct = System.nanoTime();
+
+ long nextKeepalive = (long) (this.lastMessageSentAt + (this.KEEP_ALIVE_TIMER_VALUE * 1E9));
+
+ if (this.state != State.IDLE) {
+ if (ct >= nextKeepalive) {
+ this.sendMessage(new PCEPKeepAliveMessage());
+ nextKeepalive = (long) (this.lastMessageSentAt + (this.KEEP_ALIVE_TIMER_VALUE * 1E9));
+ }
+
+ this.stateTimer.schedule(new KeepAliveTimer(this), (long) ((nextKeepalive - ct) / 1E6));
+ }
+ }
+
+ private void changeState(final State finalState) {
+ switch (finalState) {
+ case IDLE:
+ logger.debug("Changed to state: " + State.IDLE);
+ this.state = State.IDLE;
+ return;
+ case OPEN_WAIT:
+ logger.debug("Changed to state: " + State.OPEN_WAIT);
+ if (this.state == State.UP) {
+ throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.OPEN_WAIT);
+ }
+ this.state = State.OPEN_WAIT;
+ return;
+ case KEEP_WAIT:
+ logger.debug("Changed to state: " + State.KEEP_WAIT);
+ if (this.state == State.UP || this.state == State.IDLE) {
+ throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.KEEP_WAIT);
+ }
+ this.state = State.KEEP_WAIT;
+ return;
+ case UP:
+ logger.debug("Changed to state: " + State.UP);
+ if (this.state == State.IDLE || this.state == State.UP) {
+ throw new IllegalArgumentException("Cannot change state from " + this.state + " to " + State.UP);
+ }
+ this.state = State.UP;
+ return;
+ }
+ }
+
+ private void restartOpenWait() {
+ if (this.state == State.OPEN_WAIT && this.openWaitTimer != null) {
+ this.openWaitTimer.cancel();
+ }
+ this.openWaitTimer = new OpenWaitTimer(this);
+ this.stateTimer.schedule(this.openWaitTimer, OPEN_WAIT_TIMER_VALUE * 1000);
+ }
+
+ private void restartKeepWaitTimer() {
+ if (this.state == State.KEEP_WAIT && this.keepWaitTimer != null) {
+ this.keepWaitTimer.cancel();
+ }
+ this.keepWaitTimer = new KeepWaitTimer(this);
+ this.stateTimer.schedule(this.keepWaitTimer, KEEP_WAIT_TIMER_VALUE * 1000);
+ }
+
+ /**
+ * Makes a callback to check if the session characteristics that FSM received, are acceptable.
+ *
+ * @param keepAliveTimerValue
+ * @param deadTimerValue
+ * @param tlvs
+ * @return
+ */
+ private boolean checkSessionCharacteristics(final PCEPOpenObject openObj) {
+ return this.checker.checkSessionCharacteristics(new PCEPSessionPreferences(openObj));
+ }
+
+ private PCEPOpenObject getNewProposal() {
+ return this.checker.getNewProposal(new PCEPSessionPreferences(this.localOpen)).getOpenObject();
+ }
+
+ /**
+ * Sends message to serialization.
+ *
+ * @param msg to be sent
+ */
+ @Override
+ public void sendMessage(final PCEPMessage msg) {
+ this.outputStream.putMessage(msg, this.factory);
+ this.lastMessageSentAt = System.nanoTime();
+ if (!(msg instanceof PCEPKeepAliveMessage))
+ logger.debug("Sent message: " + msg);
+ this.parent.checkOutputBuffer(this);
+ this.sentMsgCount++;
+ }
+
+ @Override
+ public ProtocolOutputStream getStream() {
+ return this.outputStream;
+ }
+
+ private void commonClose() {
+ this.changeState(State.IDLE);
+ this.parent.onSessionClosed(this);
+ }
+
+ /**
+ * Closes PCEP session from the parent with given reason. A message needs to be sent, but parent doesn't have to be
+ * modified, because he initiated the closing. (To prevent concurrent modification exception).
+ *
+ * @param closeObject
+ */
+ void closeWithoutMessage() {
+ logger.debug("Closing session: {}", this);
+ commonClose();
+ }
+
+ /**
+ * Closes PCEP session, cancels all timers, returns to state Idle WITHOUT sending the Close Message. KeepAlive and
+ * DeadTimer are cancelled if the state of the session changes to IDLE. This method is used to close the PCEP
+ * session from inside the session or from the listener, therefore the parent of this session should be informed.
+ * The only closing reason is UNKNOWN.
+ */
+ @Override
+ public synchronized void close() {
+ logger.debug("Closing session: {}", this);
+ this.sendMessage(new PCEPCloseMessage(new PCEPCloseObject(Reason.UNKNOWN)));
+ commonClose();
+ }
+
+ private void terminate(final PCEPCloseObject.Reason reason) {
+ this.sendMessage(new PCEPCloseMessage(new PCEPCloseObject(reason)));
+ this.closeWithoutMessage();
+ this.listener.onSessionTerminated(this, new PCEPCloseTermination(reason));
+ }
+
+ private void terminate(final PCEPErrors error) {
+ this.sendErrorMessage(error);
+ this.closeWithoutMessage();
+ this.listener.onSessionTerminated(this, new PCEPErrorTermination(error));
+ }
+
+ @Override
+ public void endOfInput() {
+ if (this.state != State.IDLE) {
+ this.listener.onSessionDown(this, null, new IOException("End of input detected. Close the session."));
+ }
+ }
+
+ @Override
+ public int maximumMessageSize() {
+ return 65535;
+ }
+
+ private void sendErrorMessage(final PCEPErrors value) {
+ this.sendErrorMessage(value, null);
+ }
+
+ /**
+ * Sends PCEP Error Message with one PCEPError and Open Object.
+ *
+ * @param value
+ * @param open
+ */
+ private void sendErrorMessage(final PCEPErrors value, final PCEPOpenObject open) {
+ final PCEPErrorObject error = new PCEPErrorObject(value);
+ final List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+ errors.add(error);
+ this.sendMessage(new PCEPErrorMessage(open, errors, null));
+ }
+
+ @Override
+ public void handleMalformedMessage(final DeserializerException e) {
+ // FIXME rewrite
+
+ }
+
+ @Override
+ public void handleMalformedMessage(final DocumentedException e) {
+ // FIXME rewrite
+
+ }
+
+ /**
+ * The fact, that a message is malformed, comes from parser. In case of unrecognized message a particular error is
+ * sent (CAPABILITY_NOT_SUPPORTED) and the method checks if the MAX_UNKNOWN_MSG per minute wasn't overstepped.
+ * Second, any other error occurred that is specified by rfc. In this case, the an error message is generated and
+ * sent.
+ *
+ * @param error documented error in RFC5440 or draft
+ */
+ public void handleMalformedMessage(final PCEPErrors error) {
+ final long ct = System.nanoTime();
+ this.sendErrorMessage(error);
+ if (error == PCEPErrors.CAPABILITY_NOT_SUPPORTED) {
+ this.unknownMessagesTimes.add(ct);
+ while (ct - this.unknownMessagesTimes.peek() > 60 * 1E9) {
+ this.unknownMessagesTimes.poll();
+ }
+ if (this.unknownMessagesTimes.size() > this.maxUnknownMessages) {
+ this.terminate(Reason.TOO_MANY_UNKNOWN_MSG);
+ }
+ }
+ }
+
+ /**
+ * In case of syntactic error or some parsing error, the session needs to be closed with the Reason: malformed
+ * message. The user needs to be notified about this error.
+ *
+ * @param e exception that was thrown from parser
+ */
+ public void handleMalformedMessage(final Exception e) {
+ logger.warn("PCEP byte stream corruption detected", e);
+ this.terminate(Reason.MALFORMED_MSG);
+ }
+
+ /**
+ * Open message should be handled only if the FSM is in OPEN_WAIT state.
+ *
+ * @param msg
+ */
+ private void handleOpenMessage(final PCEPOpenMessage msg) {
+ this.remoteOpen = msg.getOpenObject();
+ logger.debug("Received message: " + msg.toString());
+ if (this.state != State.OPEN_WAIT) {
+ this.sendErrorMessage(PCEPErrors.ATTEMPT_2ND_SESSION);
+ return;
+ }
+ final Boolean result = this.checkSessionCharacteristics(this.remoteOpen);
+ if (result == null) {
+ this.terminate(PCEPErrors.NON_ACC_NON_NEG_SESSION_CHAR); // 1, 3
+ return;
+ } else if (result) {
+ this.DEAD_TIMER_VALUE = this.remoteOpen.getDeadTimerValue();
+ this.KEEP_ALIVE_TIMER_VALUE = this.remoteOpen.getKeepAliveTimerValue();
+ logger.debug("Session chars are acceptable. Overwriting: deadtimer: " + this.DEAD_TIMER_VALUE + "keepalive: "
+ + this.KEEP_ALIVE_TIMER_VALUE);
+ this.remoteOK = true;
+ this.openWaitTimer.cancel();
+ this.sendMessage(new PCEPKeepAliveMessage());
+ // if the timer is not disabled
+ if (this.KEEP_ALIVE_TIMER_VALUE != 0) {
+ this.stateTimer.schedule(new KeepAliveTimer(this), this.KEEP_ALIVE_TIMER_VALUE * 1000);
+ }
+ if (this.localOK) {
+ // if the timer is not disabled
+ if (this.DEAD_TIMER_VALUE != 0) {
+ this.stateTimer.schedule(new DeadTimer(this), this.DEAD_TIMER_VALUE * 1000);
+ }
+ this.changeState(State.UP);
+ this.listener.onSessionUp(this, this.localOpen, this.remoteOpen);
+ } else {
+ this.restartKeepWaitTimer();
+ this.changeState(State.KEEP_WAIT);
+ }
+ return;
+ } else if (!result) {
+ this.localOpen = this.getNewProposal();
+ if (this.openRetry) {
+ this.terminate(PCEPErrors.SECOND_OPEN_MSG); // 1, 5
+ } else {
+ this.openRetry = true;
+ this.sendErrorMessage(PCEPErrors.NON_ACC_NEG_SESSION_CHAR, this.localOpen); // 1, 4
+ if (this.localOK) {
+ this.restartOpenWait();
+ this.changeState(State.OPEN_WAIT);
+ } else {
+ this.restartKeepWaitTimer();
+ this.changeState(State.KEEP_WAIT);
+ }
+ }
+ }
+ }
+
+ /**
+ * Error message should be handled in FSM if its state is KEEP_WAIT, otherwise it is just passed to session listener
+ * for handling.
+ *
+ * @param msg
+ */
+ private void handleErrorMessage(final PCEPErrorMessage msg) {
+ this.remoteOpen = msg.getOpenObject();
+ final Boolean result = this.checkSessionCharacteristics(this.remoteOpen);
+ if (result == null || !result) {
+ this.terminate(PCEPErrors.PCERR_NON_ACC_SESSION_CHAR); // 1, 6
+ return;
+ } else {
+ this.KEEP_ALIVE_TIMER_VALUE = this.remoteOpen.getKeepAliveTimerValue();
+ this.DEAD_TIMER_VALUE = this.remoteOpen.getDeadTimerValue();
+ logger.debug("New values for keepalive: " + this.remoteOpen.getKeepAliveTimerValue() + " deadtimer "
+ + this.remoteOpen.getDeadTimerValue());
+ this.sendMessage(new PCEPOpenMessage(this.remoteOpen));
+ if (this.remoteOK) {
+ this.restartKeepWaitTimer();
+ this.changeState(State.KEEP_WAIT);
+ } else {
+ this.keepWaitTimer.cancel();
+ this.restartOpenWait();
+ this.changeState(State.OPEN_WAIT);
+ }
+ }
+ }
+
+ /**
+ * KeepAlive message should be explicitly parsed in FSM when its state is KEEP_WAIT. Otherwise is handled by the
+ * KeepAliveTimer or it's invalid.
+ */
+ private void handleKeepAliveMessage() {
+ if (this.state == State.KEEP_WAIT) {
+ this.localOK = true;
+ this.keepWaitTimer.cancel();
+ if (this.remoteOK) {
+ if (this.DEAD_TIMER_VALUE != 0) {
+ this.stateTimer.schedule(new DeadTimer(this), this.DEAD_TIMER_VALUE * 1000);
+ }
+ this.changeState(State.UP);
+ this.listener.onSessionUp(this, this.localOpen, this.remoteOpen);
+ } else {
+ this.restartOpenWait();
+ this.changeState(State.OPEN_WAIT);
+ }
+ }
+ }
+
+ /**
+ * Handles incoming message. If the session is up, it notifies the user. The user is notified about every message
+ * except KeepAlive.
+ *
+ * @param msg incoming message
+ */
+ @Override
+ public void handleMessage(final ProtocolMessage msg) {
+ // Update last reception time
+ final PCEPMessage pcepMsg = (PCEPMessage) msg;
+
+ this.lastMessageReceivedAt = System.nanoTime();
+ this.receivedMsgCount++;
+
+ if (pcepMsg instanceof PCEPRawMessage) {
+ List<PCEPMessage> msgs;
+ try {
+ msgs = PCEPMessageValidator.getValidator(((PCEPRawMessage) pcepMsg).getMsgType()).validate(
+ ((PCEPRawMessage) pcepMsg).getAllObjects());
+ for (final PCEPMessage tmpMsg : msgs) {
+ this.handleMessage(tmpMsg);
+ }
+ } catch (final PCEPDeserializerException e) {
+ logger.error("Malformed message, terminating. ", e);
+ this.terminate(Reason.MALFORMED_MSG);
+ }
+ return;
+ }
+
+ // Keepalives are handled internally
+ if (pcepMsg instanceof PCEPKeepAliveMessage) {
+ this.handleKeepAliveMessage();
+ return;
+ }
+
+ // Open messages are handled internally
+ if (pcepMsg instanceof PCEPOpenMessage) {
+ this.handleOpenMessage((PCEPOpenMessage) pcepMsg);
+ return;
+ }
+
+ /*
+ * During initial handshake we handle all the messages.
+ */
+ if (this.state != State.UP) {
+ /*
+ * In KEEP_WAIT, an Error message is a valid thing to see, because
+ * it is used in negotiation.
+ */
+ if (pcepMsg instanceof PCEPErrorMessage && this.state == State.KEEP_WAIT
+ && ((PCEPErrorMessage) pcepMsg).getOpenObject() != null) {
+ this.handleErrorMessage((PCEPErrorMessage) pcepMsg);
+ return;
+ }
+
+ /*
+ * OPEN and KEEPALIVE messages are handled at the top. ERROR
+ * messages are handled in the specific case of KEEP_WAIT above, so
+ * anything else is invalid here.
+ */
+ this.terminate(PCEPErrors.NON_OR_INVALID_OPEN_MSG);
+ return;
+ }
+
+ /*
+ * Session is up, we are reporting all messages to user. One notable
+ * exception is CLOSE message, which needs to be converted into a
+ * session DOWN event.
+ */
+ if (pcepMsg instanceof PCEPCloseMessage) {
+ this.listener.onSessionTerminated(this, new PCEPCloseTermination(((PCEPCloseMessage) pcepMsg).getCloseObject().getReason()));
+ this.closeWithoutMessage();
+ return;
+ }
+ this.listener.onMessage(this, pcepMsg);
+ }
+
+ @Override
+ public ProtocolMessageFactory getMessageFactory() {
+ return this.factory;
+ }
+
+ @Override
+ public void onConnectionFailed(final IOException e) {
+ logger.info("Connection failed before finishing: {}", e.getMessage(), e);
+ this.listener.onSessionDown(this, new PCEPCloseObject(Reason.UNKNOWN), e);
+ }
+
+ /**
+ * @return the sentMsgCount
+ */
+
+ @Override
+ public Integer getSentMsgCount() {
+ return this.sentMsgCount;
+ }
+
+ /**
+ * @return the receivedMsgCount
+ */
+
+ @Override
+ public Integer getReceivedMsgCount() {
+ return this.receivedMsgCount;
+ }
+
+
+ @Override
+ public Integer getDeadTimerValue() {
+ return this.DEAD_TIMER_VALUE;
+ }
+
+
+ @Override
+ public Integer getKeepAliveTimerValue() {
+ return this.KEEP_ALIVE_TIMER_VALUE;
+ }
+
+
+ @Override
+ public String getPeerAddress() {
+ return this.peerAddress;
+ }
+
+ @Override
+ public void tearDown() throws IOException {
+ this.close();
+ }
+
+
+ @Override
+ public String getNodeIdentifier() {
+ if (!this.remoteOpen.getTlvs().isEmpty()) {
+ final PCEPTlv tlv = this.remoteOpen.getTlvs().iterator().next();
+ if (tlv != null && tlv instanceof NodeIdentifierTlv) {
+ return tlv.toString();
+ }
+ }
+ return "";
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("PCEPSessionImpl [state=");
+ builder.append(this.state);
+ builder.append(", localOK=");
+ builder.append(this.localOK);
+ builder.append(", remoteOK=");
+ builder.append(this.remoteOK);
+ builder.append(", openRetry=");
+ builder.append(this.openRetry);
+ builder.append(", sessionId=");
+ builder.append(this.sessionId);
+ builder.append(", checker=");
+ builder.append(this.checker);
+ builder.append(", localOpen=");
+ builder.append(this.localOpen);
+ builder.append(", remoteOpen=");
+ builder.append(this.remoteOpen);
+ builder.append(", outputStream=");
+ builder.append(this.outputStream);
+ builder.append("]");
+ return builder.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalCheckerFactory;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+public class PCEPSessionProposalCheckerFactoryImpl extends
+ PCEPSessionProposalCheckerFactory implements Closeable {
+
+ @Override
+ public PCEPSessionProposalChecker getPreferencesChecker(
+ final InetSocketAddress address) {
+ return new PCEPSessionProposalChecker() {
+
+ @Override
+ public Boolean checkSessionCharacteristics(
+ final SessionPreferences openObj) {
+ return true;
+ }
+
+ @Override
+ public PCEPSessionPreferences getNewProposal(
+ final SessionPreferences open) {
+ return new PCEPSessionPreferences(new PCEPOpenObject(30, 120, 0, null));
+ }
+
+ };
+ }
+
+ @Override
+ public void close() throws IOException {
+ // nothing to close
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposal;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.LSPCleanupTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+
+public class PCEPSessionProposalFactoryImpl extends PCEPSessionProposalFactory implements Closeable {
+
+ private final int keepAlive, deadTimer, timeout;
+
+ private final boolean stateful, active, versioned, instant;
+
+ public PCEPSessionProposalFactoryImpl(final int deadTimer, final int keepAlive, final boolean stateful, final boolean active, final boolean versioned, final boolean instant, final int timeout) {
+ this.deadTimer = deadTimer;
+ this.keepAlive = keepAlive;
+ this.stateful = stateful;
+ this.active = active;
+ this.versioned = versioned;
+ this.instant = instant;
+ this.timeout = timeout;
+ }
+
+ @Override
+ public PCEPSessionProposal getSessionProposal(final InetSocketAddress address, final int sessionId) {
+ return new PCEPSessionProposal() {
+
+ @Override
+ public PCEPSessionPreferences getProposal() {
+ List<PCEPTlv> tlvs = null;
+ if (PCEPSessionProposalFactoryImpl.this.stateful) {
+ tlvs = new ArrayList<PCEPTlv>();
+ tlvs.add(new PCEStatefulCapabilityTlv(PCEPSessionProposalFactoryImpl.this.instant, PCEPSessionProposalFactoryImpl.this.active, PCEPSessionProposalFactoryImpl.this.versioned));
+ if (PCEPSessionProposalFactoryImpl.this.instant) {
+ tlvs.add(new LSPCleanupTlv(PCEPSessionProposalFactoryImpl.this.timeout));
+ }
+ }
+ return new PCEPSessionPreferences(new PCEPOpenObject(PCEPSessionProposalFactoryImpl.this.keepAlive, PCEPSessionProposalFactoryImpl.this.deadTimer, sessionId, tlvs));
+ }
+
+ };
+ }
+
+ public int getKeepAlive() {
+ return this.keepAlive;
+ }
+
+ public int getDeadTimer() {
+ return this.deadTimer;
+ }
+
+ public boolean isStateful() {
+ return this.stateful;
+ }
+
+ public boolean isActive() {
+ return this.active;
+ }
+
+ public boolean isVersioned() {
+ return this.versioned;
+ }
+
+ public boolean isInstant() {
+ return this.instant;
+ }
+
+ public int getTimeout() {
+ return this.timeout;
+ }
+
+ @Override
+ public void close() throws IOException {
+ // nothing to close
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.io.IOException;
+
+public interface PCEPSessionRuntimeMXBean {
+ //TODO remove once operations are generated
+
+ Integer getDeadTimerValue();
+
+ Integer getKeepAliveTimerValue();
+
+ Integer getReceivedMsgCount();
+
+ Integer getSentMsgCount();
+
+ String getPeerAddress();
+
+ String getNodeIdentifier();
+
+ void tearDown() throws IOException;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.impl.tlv.LSPIdentifierIPv4TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.LSPIdentifierIPv6TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.NoPathVectorTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.OFListTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.PCEStatefulCapabilityTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.RSVPErrorSpecIPv4TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.RSVPErrorSpecIPv6TlvParser;
+import org.opendaylight.protocol.pcep.tlv.IPv4LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.IPv6LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPCleanupTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPSymbolicNameTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPUpdateErrorTlv;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import org.opendaylight.protocol.pcep.tlv.OverloadedDurationTlv;
+import org.opendaylight.protocol.pcep.tlv.P2MPCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.pcep.tlv.ReqMissingTlv;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.PCEPTlv PCEPTlv} and its subclasses
+ */
+public final class PCEPTlvParser {
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPTlvParser.class);
+
+ /**
+ * Type indicator for {@link org.opendaylight.protocol.pcep.PCEPTlv PCEPTlv}
+ */
+ private enum PCEPTlvType {
+ NO_PATH_VECTOR(1),
+ OVERLOADED_DURATION(2),
+ REQ_MISSING(3),
+ OF_LIST_TLV(4),
+ ORDER_TLV(5),
+ P2MP_CAPABILITY(6),
+ PCE_STATEFUL_CAPABILITY(16),
+ LSP_SYMBOLIC_NAME(17),
+ LSP_IDENTIFIER_IPV4(18),
+ LSP_IDENTIFIER_IPV6(19),
+ LSP_UPDATE_ERROR(20),
+ RSVP_ERROR_SPEC_IPV4(21),
+ RSVP_ERROR_SPEC_IPV6(22),
+ LSP_STATE_DB_VERSION(23),
+ // TODO: use IANA defined number - for now has been used first unused
+ // number
+ NODE_IDENTIFIER(24),
+ LSP_CLEANUP_TLV(26);
+
+ private final int indicator;
+
+ PCEPTlvType(final int indicator) {
+ this.indicator = indicator;
+ }
+
+ public int getIndicator() {
+ return this.indicator;
+ }
+
+ public static PCEPTlvType getFromInt(final int type) throws PCEPDeserializerException {
+
+ for (final PCEPTlvType type_e : PCEPTlvType.values()) {
+ if (type_e.getIndicator() == type)
+ return type_e;
+ }
+
+ throw new PCEPDeserializerException("Unknown TLV type: " + type);
+ }
+ }
+
+ /*
+ * Fields lengths in Bytes
+ */
+ public static final int TYPE_F_LENGTH = 2;
+ public static final int LENGTH_F_LENGTH = 2;
+ public static final int HEADER_LENGTH = LENGTH_F_LENGTH + TYPE_F_LENGTH;
+
+ /*
+ * Fields offsets in Bytes
+ */
+ public static final int TYPE_F_OFFSET = 0;
+ public static final int LENGTH_F_OFFSET = TYPE_F_OFFSET + TYPE_F_LENGTH;
+ public static final int VALUE_F_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
+
+ /*
+ * padding of value field in bytes
+ */
+ public static final int PADDED_TO = 4;
+
+ /*
+ * constants for specific one-value tlvs
+ */
+ private static final int DBV_F_LENGTH = 8;
+ private static final int OVERLOADED_DURATION_LENGTH = 4;
+ private static final int UPDATE_ERR_CODE_LENGTH = 4;
+ private static final int REQ_ID_LENGTH = 4;
+ private static final int ORDR_DEL_LENGTH = 4;
+ private static final int ORDR_SETUP_LENGTH = 4;
+ private static final int P2MP_CAPABLITY_LENGTH = 2;
+
+ public static List<PCEPTlv> parse(final byte[] bytes) throws PCEPDeserializerException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Byte array is mandatory.");
+
+ final List<PCEPTlv> tlvList = new ArrayList<PCEPTlv>();
+ PCEPTlvType type;
+ int length;
+ int offset = 0;
+
+ while (offset + HEADER_LENGTH < bytes.length) {
+
+ length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
+
+ type = PCEPTlvType.getFromInt(ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + TYPE_F_OFFSET, TYPE_F_LENGTH)));
+
+ if (HEADER_LENGTH + length > bytes.length - offset)
+ throw new PCEPDeserializerException("Wrong length specified. Passed: " + (HEADER_LENGTH + length) + "; Expected: <= " + (bytes.length - offset)
+ + ".");
+
+ final byte[] tlvBytes = ByteArray.subByte(bytes, offset + VALUE_F_OFFSET, length);
+
+ logger.trace("Attempt to parse tlv from bytes: {}", ByteArray.bytesToHexString(tlvBytes));
+ final PCEPTlv tlv = parseSpecificTLV(type, tlvBytes);
+ logger.trace("Tlv was parsed. {}", tlv);
+
+ tlvList.add(tlv);
+
+ offset += HEADER_LENGTH + length + Util.getPadding(HEADER_LENGTH + length, PADDED_TO);
+ }
+
+ return tlvList;
+ }
+
+ public static byte[] put(final List<PCEPTlv> objsToSerialize) {
+ final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
+
+ int length = 0;
+ for (final PCEPTlv obj : objsToSerialize) {
+ final byte[] bytes = put(obj);
+ length += bytes.length;
+ bytesList.add(bytes);
+ }
+
+ final byte[] retBytes = new byte[length];
+
+ int offset = 0;
+ for (final byte[] bytes : bytesList) {
+ System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
+ offset += bytes.length;
+ }
+
+ return retBytes;
+ }
+
+ public static byte[] put(final PCEPTlv objToSerialize) {
+ int typeIndicator = 0;
+
+ byte[] valueBytes;
+
+ if (objToSerialize instanceof PCEStatefulCapabilityTlv) {
+ typeIndicator = PCEPTlvType.PCE_STATEFUL_CAPABILITY.getIndicator();
+ valueBytes = PCEStatefulCapabilityTlvParser.serializeValueField((PCEStatefulCapabilityTlv) objToSerialize);
+ } else if (objToSerialize instanceof LSPStateDBVersionTlv) {
+ typeIndicator = PCEPTlvType.LSP_STATE_DB_VERSION.getIndicator();
+ valueBytes = ByteArray.longToBytes(((LSPStateDBVersionTlv) objToSerialize).getDbVersion());
+ } else if (objToSerialize instanceof NoPathVectorTlv) {
+ typeIndicator = PCEPTlvType.NO_PATH_VECTOR.getIndicator();
+ valueBytes = NoPathVectorTlvParser.put((NoPathVectorTlv) objToSerialize);
+ } else if (objToSerialize instanceof OverloadedDurationTlv) {
+ typeIndicator = PCEPTlvType.OVERLOADED_DURATION.getIndicator();
+ valueBytes = ByteArray.intToBytes(((OverloadedDurationTlv) objToSerialize).getValue());
+ } else if (objToSerialize instanceof LSPSymbolicNameTlv) {
+ typeIndicator = PCEPTlvType.LSP_SYMBOLIC_NAME.getIndicator();
+ valueBytes = ((LSPSymbolicNameTlv) objToSerialize).getSymbolicName().getSymbolicName();
+ } else if (objToSerialize instanceof LSPUpdateErrorTlv) {
+ typeIndicator = PCEPTlvType.LSP_UPDATE_ERROR.getIndicator();
+ valueBytes = ((LSPUpdateErrorTlv) objToSerialize).getErrorCode();
+
+ assert valueBytes.length == UPDATE_ERR_CODE_LENGTH : "Update error code si too large.";
+
+ } else if (objToSerialize instanceof IPv4LSPIdentifiersTlv) {
+ typeIndicator = PCEPTlvType.LSP_IDENTIFIER_IPV4.getIndicator();
+ valueBytes = LSPIdentifierIPv4TlvParser.put((IPv4LSPIdentifiersTlv) objToSerialize);
+ } else if (objToSerialize instanceof IPv6LSPIdentifiersTlv) {
+ typeIndicator = PCEPTlvType.LSP_IDENTIFIER_IPV6.getIndicator();
+ valueBytes = LSPIdentifierIPv6TlvParser.put((IPv6LSPIdentifiersTlv) objToSerialize);
+ } else if (objToSerialize instanceof RSVPErrorSpecTlv<?> && ((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress() instanceof IPv4Address) {
+ typeIndicator = PCEPTlvType.RSVP_ERROR_SPEC_IPV4.getIndicator();
+ valueBytes = RSVPErrorSpecIPv4TlvParser.put((RSVPErrorSpecTlv<?>) objToSerialize);
+ } else if (objToSerialize instanceof RSVPErrorSpecTlv<?> && ((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress() instanceof IPv6Address) {
+ typeIndicator = PCEPTlvType.RSVP_ERROR_SPEC_IPV6.getIndicator();
+ valueBytes = RSVPErrorSpecIPv6TlvParser.put((RSVPErrorSpecTlv<?>) objToSerialize);
+ } else if (objToSerialize instanceof ReqMissingTlv) {
+ typeIndicator = PCEPTlvType.REQ_MISSING.getIndicator();
+ valueBytes = new byte[REQ_ID_LENGTH];
+ System.arraycopy(ByteArray.longToBytes(((ReqMissingTlv) objToSerialize).getRequestID()), Long.SIZE / Byte.SIZE - REQ_ID_LENGTH, valueBytes, 0,
+ REQ_ID_LENGTH);
+ } else if (objToSerialize instanceof NodeIdentifierTlv) {
+ typeIndicator = PCEPTlvType.NODE_IDENTIFIER.getIndicator();
+ valueBytes = ((NodeIdentifierTlv) objToSerialize).getValue();
+ } else if (objToSerialize instanceof OrderTlv) {
+ typeIndicator = PCEPTlvType.ORDER_TLV.getIndicator();
+ valueBytes = new byte[ORDR_DEL_LENGTH + ORDR_SETUP_LENGTH];
+ ByteArray.copyWhole(ByteArray.intToBytes((int) ((OrderTlv) objToSerialize).getDeleteOrder()), valueBytes, 0);
+ ByteArray.copyWhole(ByteArray.intToBytes((int) ((OrderTlv) objToSerialize).getSetupOrder()), valueBytes, ORDR_DEL_LENGTH);
+ } else if (objToSerialize instanceof P2MPCapabilityTlv) {
+ typeIndicator = PCEPTlvType.P2MP_CAPABILITY.getIndicator();
+ valueBytes = new byte[P2MP_CAPABLITY_LENGTH];
+ ByteArray.copyWhole(ByteArray.shortToBytes((short) ((P2MPCapabilityTlv) objToSerialize).getValue()), valueBytes, 0);
+ } else if (objToSerialize instanceof OFListTlv) {
+ typeIndicator = PCEPTlvType.OF_LIST_TLV.getIndicator();
+ valueBytes = OFListTlvParser.put((OFListTlv) objToSerialize);
+ } else if (objToSerialize instanceof LSPCleanupTlv) {
+ typeIndicator = PCEPTlvType.LSP_CLEANUP_TLV.getIndicator();
+ valueBytes = ByteArray.intToBytes(((LSPCleanupTlv) objToSerialize).getTimeout());
+ } else
+ throw new IllegalArgumentException("Unknown instance of PCEPTlv. Passed: " + objToSerialize + ".");
+
+ final byte[] typeBytes = ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_F_LENGTH);
+ final byte[] lengthBytes = ByteArray.cutBytes(ByteArray.intToBytes(valueBytes.length), (Integer.SIZE / 8) - LENGTH_F_LENGTH);
+ final byte[] bytes = new byte[HEADER_LENGTH + valueBytes.length + Util.getPadding(HEADER_LENGTH + valueBytes.length, PADDED_TO)];
+
+ System.arraycopy(typeBytes, 0, bytes, TYPE_F_OFFSET, TYPE_F_LENGTH);
+ System.arraycopy(lengthBytes, 0, bytes, LENGTH_F_OFFSET, LENGTH_F_LENGTH);
+ System.arraycopy(valueBytes, 0, bytes, VALUE_F_OFFSET, valueBytes.length);
+
+ return bytes;
+ }
+
+ private static PCEPTlv parseSpecificTLV(final PCEPTlvType type, final byte[] valueBytes) throws PCEPDeserializerException {
+ switch (type) {
+ case PCE_STATEFUL_CAPABILITY:
+ return PCEStatefulCapabilityTlvParser.deserializeValueField(valueBytes);
+ case LSP_STATE_DB_VERSION:
+ return new LSPStateDBVersionTlv(ByteArray.bytesToLong(ByteArray.subByte(valueBytes, 0, DBV_F_LENGTH)));
+ case NO_PATH_VECTOR:
+ return NoPathVectorTlvParser.parse(valueBytes);
+ case OVERLOADED_DURATION:
+ return new OverloadedDurationTlv(ByteArray.bytesToInt(ByteArray.subByte(valueBytes, 0, OVERLOADED_DURATION_LENGTH)));
+ case LSP_SYMBOLIC_NAME:
+ return new LSPSymbolicNameTlv(new LSPSymbolicName(valueBytes));
+ case LSP_UPDATE_ERROR:
+ return new LSPUpdateErrorTlv(valueBytes);
+ case LSP_IDENTIFIER_IPV4:
+ return LSPIdentifierIPv4TlvParser.parse(valueBytes);
+ case LSP_IDENTIFIER_IPV6:
+ return LSPIdentifierIPv6TlvParser.parse(valueBytes);
+ case RSVP_ERROR_SPEC_IPV4:
+ return RSVPErrorSpecIPv4TlvParser.parse(valueBytes);
+ case RSVP_ERROR_SPEC_IPV6:
+ return RSVPErrorSpecIPv6TlvParser.parse(valueBytes);
+ case REQ_MISSING:
+ return new ReqMissingTlv(ByteArray.bytesToLong(ByteArray.subByte(valueBytes, 0, REQ_ID_LENGTH)));
+ case NODE_IDENTIFIER:
+ return new NodeIdentifierTlv(valueBytes);
+ case ORDER_TLV:
+ return new OrderTlv(ByteArray.bytesToLong(ByteArray.subByte(valueBytes, 0, ORDR_DEL_LENGTH)), ByteArray.bytesToLong(ByteArray.subByte(
+ valueBytes, ORDR_DEL_LENGTH, ORDR_SETUP_LENGTH)));
+ case P2MP_CAPABILITY:
+ return new P2MPCapabilityTlv(ByteArray.bytesToShort(ByteArray.subByte(valueBytes, 0, P2MP_CAPABLITY_LENGTH)) & 0xFFFF);
+ case OF_LIST_TLV:
+ return OFListTlvParser.parse(valueBytes);
+ case LSP_CLEANUP_TLV:
+ return new LSPCleanupTlv(ByteArray.bytesToInt(valueBytes));
+ default:
+ throw new PCEPDeserializerException("Unknown TLV type. Passed: " + type + ";");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.subobject.XROAsNumberSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROIPv4PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROIPv6PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROSRLGSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.PCEPXROSubobject PCEPXROSubobject}
+ */
+public class PCEPXROSubobjectParser {
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPXROSubobjectParser.class);
+
+ /**
+ * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPXROSubobject
+ * PCEPXROSubobject}
+ */
+ public enum PCEPXROSubobjectType {
+ IPv4_PREFIX(1), IPv6_PREFIX(2), UNNUMBERED_INTERFACE_ID(4), AS_NUMBER(32), SRLG(34);
+
+ private final int indicator;
+
+ PCEPXROSubobjectType(int indicator) {
+ this.indicator = indicator;
+ }
+
+ public int getIndicator() {
+ return this.indicator;
+ }
+
+ public static PCEPXROSubobjectType getFromInt(int type) throws PCEPDeserializerException {
+
+ for (final PCEPXROSubobjectType type_e : PCEPXROSubobjectType.values()) {
+ if (type_e.getIndicator() == type)
+ return type_e;
+ }
+
+ throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + "; Known: " + PCEPXROSubobjectType.values() + ".");
+ }
+ }
+
+ /*
+ * Fields lengths in Bytes
+ */
+ public static final int TYPE_FLAG_F_LENGTH = 1;
+ public static final int LENGTH_F_LENGTH = 1;
+
+ /*
+ * Fields offsets in Bytes
+ */
+ public static final int TYPE_FLAG_F_OFFSET = 0;
+ public static final int LENGTH_F_OFFSET = TYPE_FLAG_F_OFFSET + TYPE_FLAG_F_LENGTH;
+ public static final int SO_CONTENTS_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
+
+ public static List<ExcludeRouteSubobject> parse(byte[] bytes) throws PCEPDeserializerException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Byte array is mandatory.");
+
+ final List<ExcludeRouteSubobject> subobjsList = new ArrayList<ExcludeRouteSubobject>();
+ boolean mandatoryFlag;
+ PCEPXROSubobjectType type;
+ byte[] soContentsBytes;
+ int length;
+ int offset = 0;
+
+ while (offset < bytes.length) {
+
+ mandatoryFlag = ((bytes[offset + TYPE_FLAG_F_OFFSET] & (1 << 7)) != 0);
+ length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
+
+ type = PCEPXROSubobjectType.getFromInt((bytes[offset + TYPE_FLAG_F_OFFSET] & 0xff) & ~(1 << 7));
+
+ if (length > bytes.length - offset)
+ throw new PCEPDeserializerException("Wrong length specified. Passed: " + length + "; Expected: <= " + (bytes.length - offset));
+
+ soContentsBytes = new byte[length - SO_CONTENTS_OFFSET];
+ System.arraycopy(bytes, offset + SO_CONTENTS_OFFSET, soContentsBytes, 0, length - SO_CONTENTS_OFFSET);
+
+ logger.debug("Attempt to parse exclude route objects subobject from bytes: {}", ByteArray.bytesToHexString(soContentsBytes));
+ final ExcludeRouteSubobject subObj = parseSpecificSubobject(type, soContentsBytes, mandatoryFlag);
+ logger.debug("Subobject was parsed. {}", subObj);
+
+ subobjsList.add(subObj);
+
+ offset += length;
+ }
+
+ return subobjsList;
+ }
+
+ public static byte[] put(List<ExcludeRouteSubobject> objsToSerialize) {
+ final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
+
+ int length = 0;
+ for (final ExcludeRouteSubobject obj : objsToSerialize) {
+ final byte[] bytes = put(obj);
+ length += bytes.length;
+ bytesList.add(bytes);
+ }
+
+ final byte[] retBytes = new byte[length];
+
+ int offset = 0;
+ for (final byte[] bytes : bytesList) {
+ System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
+ offset += bytes.length;
+ }
+
+ return retBytes;
+ }
+
+ public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+ int typeIndicator = 0;
+
+ final byte[] soContentsBytes;
+
+ if (objToSerialize instanceof XROIPPrefixSubobject<?> && ((XROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv4Prefix) {
+ typeIndicator = PCEPXROSubobjectType.IPv4_PREFIX.getIndicator();
+ soContentsBytes = XROIPv4PrefixSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof XROIPPrefixSubobject<?> && ((XROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv6Prefix) {
+ typeIndicator = PCEPXROSubobjectType.IPv6_PREFIX.getIndicator();
+ soContentsBytes = XROIPv6PrefixSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof XROAsNumberSubobject) {
+ typeIndicator = PCEPXROSubobjectType.AS_NUMBER.getIndicator();
+ soContentsBytes = XROAsNumberSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof XROUnnumberedInterfaceSubobject) {
+ typeIndicator = PCEPXROSubobjectType.UNNUMBERED_INTERFACE_ID.getIndicator();
+ soContentsBytes = XROUnnumberedInterfaceSubobjectParser.put(objToSerialize);
+ } else if (objToSerialize instanceof XROSRLGSubobject) {
+ typeIndicator = PCEPXROSubobjectType.SRLG.getIndicator();
+ soContentsBytes = XROSRLGSubobjectParser.put(objToSerialize);
+ } else
+ throw new IllegalArgumentException("Unknown instance of PCEPXROSubobject. Passed: " + objToSerialize.getClass() + ".");
+
+ final byte[] bytes = new byte[SO_CONTENTS_OFFSET + soContentsBytes.length];
+
+ bytes[TYPE_FLAG_F_OFFSET] = (byte) (ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_FLAG_F_LENGTH)[0] | (objToSerialize
+ .isMandatory() ? 1 << 7 : 0));
+ bytes[LENGTH_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(soContentsBytes.length + SO_CONTENTS_OFFSET), (Integer.SIZE / 8) - LENGTH_F_LENGTH)[0];
+
+ System.arraycopy(soContentsBytes, 0, bytes, SO_CONTENTS_OFFSET, soContentsBytes.length);
+
+ return bytes;
+ }
+
+ private static ExcludeRouteSubobject parseSpecificSubobject(PCEPXROSubobjectType type, byte[] soContentsBytes, boolean mandatory)
+ throws PCEPDeserializerException {
+
+ switch (type) {
+ case IPv4_PREFIX:
+ return XROIPv4PrefixSubobjectParser.parse(soContentsBytes, mandatory);
+ case IPv6_PREFIX:
+ return XROIPv6PrefixSubobjectParser.parse(soContentsBytes, mandatory);
+ case UNNUMBERED_INTERFACE_ID:
+ return XROUnnumberedInterfaceSubobjectParser.parse(soContentsBytes, mandatory);
+ case AS_NUMBER:
+ return XROAsNumberSubobjectParser.parse(soContentsBytes, mandatory);
+ case SRLG:
+ return XROSRLGSubobjectParser.parse(soContentsBytes, mandatory);
+ default:
+ throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + ".");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.AddressFamily;
+import org.opendaylight.protocol.concepts.NetworkAddress;
+
+/**
+ * Utilities used in pcep-impl
+ */
+public final class Util {
+
+ private Util() {
+ }
+
+ public static class BiParsersMap<K, KV, V> {
+ private final HashMap<K, KV> kToKv = new HashMap<K, KV>();
+
+ private final HashMap<KV, V> kvToV = new HashMap<KV, V>();
+
+ public void put(K key, KV keyValue, V value) {
+ this.kToKv.put(key, keyValue);
+ this.kvToV.put(keyValue, value);
+ }
+
+ public KV getKeyValueFromKey(K key) {
+ return this.kToKv.get(key);
+ }
+
+ public V getValueFromKeyValue(KV keyValue) {
+ return this.kvToV.get(keyValue);
+ }
+ }
+
+ public static int getPadding(int length, int padding) {
+ return (padding - (length % padding)) % padding;
+ }
+
+ public static <T extends NetworkAddress<T>> List<T> parseAddresses(byte[] bytes, int offset, AddressFamily<T> family, int addrLen) {
+ final List<T> addresses = new ArrayList<T>();
+
+ while (bytes.length > offset) {
+ addresses.add(family.addressForBytes(ByteArray.subByte(bytes, offset, addrLen)));
+ offset += addrLen;
+ }
+
+ return addresses;
+ }
+
+ public static <T extends NetworkAddress<T>> void putAddresses(byte[] destBytes, int offset, List<T> addresses, int addrLen) {
+ for (final T address : addresses) {
+ System.arraycopy(address.getAddress(), 0, destBytes, offset, addrLen);
+ offset += addrLen;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCCreateMessage;
+
+/**
+ * Parser for {@link PCCreateMessage}
+ */
+public class PCCreateMessageParser implements PCEPMessageParser {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.protocol.pcep.impl.PCEPMessageParser#put(org.opendaylight.protocol.pcep.PCEPMessage
+ * )
+ */
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCCreateMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Needed PCCreateMessage.");
+
+ return PCEPObjectFactory.put(((PCCreateMessage) msg).getAllObjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCCreateMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.object.CompositeInstantiationObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+
+/**
+ * PCCCreateMessage validator. Validates message integrity.
+ */
+public class PCCreateMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ final List<CompositeInstantiationObject> insts = new ArrayList<CompositeInstantiationObject>();
+
+ CompositeInstantiationObject inst;
+ while (!objects.isEmpty()) {
+ try {
+ if ((inst = this.getValidInstantiationObject(objects)) == null)
+ break;
+ } catch (final PCEPDocumentedException e) {
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+ }
+
+ insts.add(inst);
+ }
+
+ if (insts.isEmpty())
+ throw new PCEPDeserializerException("At least one CompositeInstantiationObject is mandatory.");
+
+ if (!objects.isEmpty())
+ throw new PCEPDeserializerException("Unprocessed objects: " + objects);
+
+ return Arrays.asList((PCEPMessage) new PCCreateMessage(insts));
+ }
+
+ private CompositeInstantiationObject getValidInstantiationObject(List<PCEPObject> objects) throws PCEPDocumentedException {
+ if (objects.get(0) instanceof UnknownObject)
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) objects.get(0)).getError());
+ if (!(objects.get(0) instanceof PCEPEndPointsObject<?>))
+ return null;
+
+ final PCEPEndPointsObject<?> endPoints = ((PCEPEndPointsObject<?>) objects.get(0));
+ objects.remove(0);
+
+ if (objects.get(0) instanceof UnknownObject)
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) objects.get(0)).getError());
+ if (!(objects.get(0) instanceof PCEPLspaObject))
+ throw new PCEPDocumentedException("LSPA Object must be second.", PCEPErrors.LSPA_MISSING);
+ final PCEPLspaObject lspa = (PCEPLspaObject) objects.get(0);
+ objects.remove(0);
+
+ PCEPExplicitRouteObject ero = null;
+ PCEPRequestedPathBandwidthObject bandwidth = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+ PCEPObject obj;
+ int state = 1;
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+ if (obj instanceof UnknownObject) {
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+ }
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPExplicitRouteObject) {
+ ero = (PCEPExplicitRouteObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 3;
+ break;
+ }
+ }
+
+ if (state == 4)
+ break;
+
+ objects.remove(0);
+ }
+
+ return new CompositeInstantiationObject(endPoints, lspa, ero, bandwidth, metrics);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPCloseMessage
+ * PCEPCloseMessage}
+ */
+public class PCEPCloseMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPCloseMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPCloseMessage.");
+
+ return PCEPObjectFactory.put(((PCEPCloseMessage) msg).getAllObjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+
+/**
+ * PCEPCloseMessage validator. Validates message integrity.
+ */
+public class PCEPCloseMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ if (objects.isEmpty() || !(objects.get(0) instanceof PCEPCloseObject))
+ throw new PCEPDeserializerException("Close message doesn't contain CLOSE object.");
+
+ final PCEPCloseMessage msg = new PCEPCloseMessage((PCEPCloseObject) objects.get(0));
+ objects.remove(0);
+
+ if (!objects.isEmpty())
+ throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+ return new ArrayList<PCEPMessage>() {
+ private static final long serialVersionUID = 1L;
+ {
+ this.add(msg);
+ }
+ };
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPErrorMessage
+ * PCEPErrorMessage}
+ */
+public class PCEPErrorMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPErrorMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance " + msg.getClass() + ". Nedded PCEPErrorMessage.");
+
+ return PCEPObjectFactory.put(((PCEPErrorMessage) msg).getAllObjects());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+
+/**
+ * PCEPErrorMessage validator. Validates message integrity.
+ */
+public class PCEPErrorMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ PCEPOpenObject openObj = null;
+ final List<CompositeErrorObject> errors = new ArrayList<CompositeErrorObject>();
+ final List<PCEPErrorObject> errorObjects = new ArrayList<PCEPErrorObject>();
+
+ PCEPObject obj;
+ int state = 1;
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+
+ if (obj instanceof UnknownObject)
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) obj).getError())));
+
+ switch (state) {
+ case 1:
+ if (obj instanceof PCEPErrorObject) {
+ errorObjects.add((PCEPErrorObject) obj);
+ break;
+ }
+ state = 2;
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPOpenObject) {
+ openObj = (PCEPOpenObject) obj;
+ break;
+ }
+ case 3:
+ while (!objects.isEmpty()) {
+ CompositeErrorObject comObj;
+
+ try {
+ comObj = getValidErrorComposite(objects);
+ } catch (final PCEPDocumentedException e) {
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+ }
+
+ if (comObj == null)
+ break;
+
+ errors.add(comObj);
+ }
+
+ state = 4;
+ break;
+ }
+
+ if (state == 4) {
+ break;
+ }
+
+ objects.remove(0);
+ }
+
+ if (errors.isEmpty() && errorObjects.isEmpty())
+ throw new PCEPDeserializerException("At least one PCEPErrorObject is mandatory.");
+
+ if (!objects.isEmpty())
+ throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(openObj, errorObjects, errors));
+ }
+
+ private static CompositeErrorObject getValidErrorComposite(List<PCEPObject> objects) throws PCEPDocumentedException, PCEPDeserializerException {
+ final List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+ final List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+ PCEPObject obj;
+ int state = 1;
+
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+
+ if (obj instanceof UnknownObject)
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPRequestParameterObject) {
+ if (((PCEPRequestParameterObject) obj).isProcessed())
+ throw new PCEPDocumentedException("Invalid setting of P flag.", PCEPErrors.P_FLAG_NOT_SET);
+ requestParameters.add((PCEPRequestParameterObject) obj);
+ state = 1;
+ break;
+ }
+ case 2:
+ if (obj instanceof PCEPErrorObject) {
+ errors.add((PCEPErrorObject) obj);
+ state = 2;
+ break;
+ }
+ state = 3;
+ }
+
+ if (state == 3)
+ break;
+
+ objects.remove(0);
+ }
+
+ if (errors.isEmpty())
+ return null;
+
+ return new CompositeErrorObject(requestParameters, errors);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage
+ * PCEPKeepAliveMessage}
+ */
+public class PCEPKeepAliveMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPKeepAliveMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPKeepAliveMessage.");
+
+ return new byte[0];
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+
+/**
+ * PCEPKeepAliveMessage validator. Validates message integrity.
+ */
+public class PCEPKeepAliveMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects != null && !objects.isEmpty())
+ throw new PCEPDeserializerException("KeepAlive message has content.");
+
+ return new ArrayList<PCEPMessage>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPKeepAliveMessage());
+ }
+ };
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPNotificationMessage
+ * PCEPNotificationMessage}
+ */
+public class PCEPNotificationMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPNotificationMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Needed PCEPNotificationMessage.");
+
+ return PCEPObjectFactory.put(((PCEPNotificationMessage) msg).getAllObjects());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+
+/**
+ * PCEPNotificationMessage validator. Validates message integrity.
+ */
+public class PCEPNotificationMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ final List<CompositeNotifyObject> compositeNotifications = new ArrayList<CompositeNotifyObject>();
+
+ while (!objects.isEmpty()) {
+ CompositeNotifyObject comObj;
+ try {
+ comObj = getValidNotificationComposite(objects);
+ } catch (final PCEPDocumentedException e) {
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+ }
+
+ if (comObj == null)
+ break;
+
+ compositeNotifications.add(comObj);
+ }
+
+ if (compositeNotifications.isEmpty())
+ throw new PCEPDeserializerException("Atleast one CompositeNotifiObject is mandatory.");
+
+ if (!objects.isEmpty())
+ throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+ return Arrays.asList((PCEPMessage) new PCEPNotificationMessage(compositeNotifications));
+ }
+
+ private static CompositeNotifyObject getValidNotificationComposite(List<PCEPObject> objects) throws PCEPDocumentedException {
+ final List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+ final List<PCEPNotificationObject> notifications = new ArrayList<PCEPNotificationObject>();
+ PCEPObject obj;
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+
+ if (obj instanceof UnknownObject)
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPRequestParameterObject) {
+ if (((PCEPRequestParameterObject) obj).isProcessed())
+ throw new PCEPDocumentedException("Invalid setting of P flag.", PCEPErrors.P_FLAG_NOT_SET);
+ requestParameters.add((PCEPRequestParameterObject) obj);
+ state = 1;
+ break;
+ }
+ case 2:
+ if (obj instanceof PCEPNotificationObject) {
+ notifications.add((PCEPNotificationObject) obj);
+ state = 2;
+ break;
+ }
+ state = 3;
+ }
+
+ if (state == 3)
+ break;
+
+ objects.remove(obj);
+ }
+
+ if (notifications.isEmpty())
+ return null;
+
+ return new CompositeNotifyObject(requestParameters, notifications);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPOpenMessage PCEPOpenMessage}
+ */
+public class PCEPOpenMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPOpenMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance " + msg.getClass() + ". Nedded PCEPOpenMessage.");
+
+ return PCEPObjectFactory.put(((PCEPOpenMessage) msg).getAllObjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * PCEPOpenMessage validator. Validates message integrity.
+ */
+public class PCEPOpenMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ if (objects.isEmpty() || !(objects.get(0) instanceof PCEPOpenObject))
+ throw new PCEPDeserializerException("Open message doesn't contain OPEN object.");
+
+ final PCEPOpenMessage msg = new PCEPOpenMessage((PCEPOpenObject) objects.get(0));
+ objects.remove(0);
+
+ if (!objects.isEmpty())
+ throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+ return new ArrayList<PCEPMessage>() {
+ private static final long serialVersionUID = 1L;
+ {
+ this.add(msg);
+ }
+ };
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageFactory.PCEPMessageType;
+
+/**
+ * Class representing raw message.
+ */
+public class PCEPRawMessage extends PCEPMessage {
+
+ private static final long serialVersionUID = 1075879993862417873L;
+
+ private final PCEPMessageType msgType;
+
+ public PCEPRawMessage(List<PCEPObject> objects, PCEPMessageType msgType) {
+ super(objects);
+ this.msgType = msgType;
+ }
+
+ public PCEPMessageType getMsgType() {
+ return this.msgType;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+ * PCEPReplyMessage}
+ */
+public class PCEPReplyMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPReplyMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPReplyMessage.");
+
+ return PCEPObjectFactory.put(((PCEPReplyMessage) msg).getAllObjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositePathObject;
+import org.opendaylight.protocol.pcep.object.CompositeReplySvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+
+/**
+ * PCEPReplyMessage validator. Validates message integrity.
+ */
+public class PCEPReplyMessageValidator extends PCEPMessageValidator {
+
+ private static class SubReplyValidator {
+
+ private boolean requestRejected = true;
+
+ private List<PCEPMessage> msgs = new ArrayList<PCEPMessage>();
+
+ private PCEPRequestParameterObject rpObj;
+
+ private PCEPNoPathObject noPath;
+ private PCEPLspObject lsp;
+ private PCEPLspaObject lspa;
+ private PCEPRequestedPathBandwidthObject bandwidth;
+ private List<PCEPMetricObject> metrics;
+ private PCEPIncludeRouteObject iro;
+ private List<CompositePathObject> paths;
+
+ private void init() {
+ this.requestRejected = false;
+ this.msgs = new ArrayList<PCEPMessage>();
+
+ this.noPath = null;
+ this.lsp = null;
+ this.lspa = null;
+ this.iro = null;
+ this.rpObj = null;
+ this.metrics = new ArrayList<PCEPMetricObject>();
+ this.paths = new ArrayList<CompositePathObject>();
+ }
+
+ public List<PCEPMessage> validate(List<PCEPObject> objects, List<CompositeReplySvecObject> svecList) {
+ this.init();
+
+ if (!(objects.get(0) instanceof PCEPRequestParameterObject))
+ return null;
+
+ final PCEPRequestParameterObject rpObj = (PCEPRequestParameterObject) objects.get(0);
+ objects.remove(0);
+
+ PCEPObject obj;
+ int state = 1;
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+ if (obj instanceof UnknownObject) {
+ if (((UnknownObject) obj).isProcessed()) {
+ this.msgs.add(new PCEPErrorMessage(
+ new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(((UnknownObject) obj).getError()))));
+ this.requestRejected = true;
+ }
+
+ objects.remove(0);
+ continue;
+ }
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPNoPathObject) {
+ this.noPath = (PCEPNoPathObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPLspObject) {
+ this.lsp = (PCEPLspObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPLspaObject) {
+ this.lspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 4:
+ state = 5;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ this.bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 5:
+ state = 6;
+ if (obj instanceof PCEPMetricObject) {
+ this.metrics.add((PCEPMetricObject) obj);
+ state = 5;
+ break;
+ }
+ case 6:
+ state = 7;
+ if (obj instanceof PCEPIncludeRouteObject) {
+ this.iro = (PCEPIncludeRouteObject) obj;
+ state = 8;
+ break;
+ }
+ }
+
+ if (state == 7)
+ break;
+
+ objects.remove(0);
+
+ if (state == 8)
+ break;
+ }
+
+ if (!objects.isEmpty()) {
+ CompositePathObject path = this.getValidCompositePath(objects);
+ while (path != null) {
+ this.paths.add(path);
+ if (objects.isEmpty())
+ break;
+ path = this.getValidCompositePath(objects);
+ }
+ }
+
+ if (!this.requestRejected) {
+ this.msgs.add(new PCEPReplyMessage(Collections.unmodifiableList(Arrays.asList(new CompositeResponseObject(rpObj, this.noPath, this.lsp,
+ this.lspa, this.bandwidth, this.metrics, this.iro, this.paths))), Collections.unmodifiableList(svecList)));
+ }
+
+ return this.msgs;
+ }
+
+ private CompositePathObject getValidCompositePath(List<PCEPObject> objects) {
+ if (!(objects.get(0) instanceof PCEPExplicitRouteObject))
+ return null;
+
+ final PCEPExplicitRouteObject explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+ objects.remove(0);
+
+ PCEPLspaObject pathLspa = null;
+ PCEPRequestedPathBandwidthObject pathBandwidth = null;
+ final List<PCEPMetricObject> pathMetrics = new ArrayList<PCEPMetricObject>();
+ PCEPIncludeRouteObject pathIro = null;
+
+ PCEPObject obj;
+ int state = 1;
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+ if (obj instanceof UnknownObject) {
+ if (((UnknownObject) obj).isProcessed()) {
+ this.msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(this.rpObj, false), new PCEPErrorObject(((UnknownObject) obj)
+ .getError()))));
+ this.requestRejected = true;
+ }
+ objects.remove(0);
+ continue;
+ }
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPLspaObject) {
+ pathLspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ pathBandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPMetricObject) {
+ pathMetrics.add((PCEPMetricObject) obj);
+ state = 3;
+ break;
+ }
+ case 4:
+ state = 5;
+ if (obj instanceof PCEPIncludeRouteObject) {
+ pathIro = (PCEPIncludeRouteObject) obj;
+ state = 6;
+ break;
+ }
+
+ }
+
+ if (state == 5)
+ break;
+
+ objects.remove(0);
+
+ if (state == 6)
+ break;
+ }
+
+ return new CompositePathObject(explicitRoute, pathLspa, pathBandwidth, pathMetrics, pathIro);
+ }
+ }
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ final List<PCEPMessage> msgs = new ArrayList<PCEPMessage>();
+ final List<CompositeReplySvecObject> svecList = new ArrayList<CompositeReplySvecObject>();
+
+ CompositeReplySvecObject svecComp;
+ while (!objects.isEmpty()) {
+ try {
+ if ((svecComp = this.getValidSvecComposite(objects)) == null)
+ break;
+ } catch (final PCEPDocumentedException e) {
+ msgs.add(new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+ return msgs;
+ }
+
+ svecList.add(svecComp);
+ }
+
+ List<PCEPMessage> subMessages;
+ final SubReplyValidator subValidator = new SubReplyValidator();
+ while (!objects.isEmpty()) {
+ subMessages = subValidator.validate(objects, svecList);
+ if (subMessages == null)
+ break;
+ msgs.addAll(subMessages);
+ }
+
+ if (msgs.isEmpty()) {
+ msgs.add(new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.RP_MISSING)));
+ return msgs;
+ }
+
+ if (!objects.isEmpty())
+ throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+ return msgs;
+ }
+
+ private CompositeReplySvecObject getValidSvecComposite(List<PCEPObject> objects) throws PCEPDocumentedException {
+ if (objects == null)
+ throw new IllegalArgumentException("List cannot be null.");
+
+ if (!(objects.get(0) instanceof PCEPSvecObject))
+ return null;
+
+ final PCEPSvecObject svec = (PCEPSvecObject) objects.get(0);
+ objects.remove(0);
+
+ PCEPObjectiveFunctionObject of = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+ PCEPObject obj;
+ int state = 1;
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+
+ if (obj instanceof UnknownObject)
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPObjectiveFunctionObject) {
+ of = (PCEPObjectiveFunctionObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 2;
+ break;
+ }
+ }
+
+ if (state == 3)
+ break;
+
+ objects.remove(0);
+ }
+
+ return new CompositeReplySvecObject(svec, of, metrics);
+ }
+
+ private static PCEPRequestParameterObject copyRP(PCEPRequestParameterObject origRp, boolean processed) {
+ return new PCEPRequestParameterObject(origRp.isLoose(), origRp.isBidirectional(), origRp.isReoptimized(), origRp.isMakeBeforeBreak(),
+ origRp.isReportRequestOrder(), origRp.isSuplyOFOnResponse(), origRp.isFragmentation(), origRp.isP2mp(), origRp.isEroCompression(),
+ origRp.getPriority(), origRp.getRequestID(), origRp.getTlvs(), processed, origRp.isIgnored());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPReportMessage
+ * PCEPReportMessage}
+ */
+public class PCEPReportMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPReportMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPReportMessage.");
+
+ return PCEPObjectFactory.put(((PCEPReportMessage) msg).getAllObjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+import org.opendaylight.protocol.pcep.object.CompositeRptPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+
+/**
+ * PCEPReportMessage validator. Validates message integrity.
+ */
+public class PCEPReportMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(final List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ final List<CompositeStateReportObject> report = new ArrayList<CompositeStateReportObject>();
+
+ while (!objects.isEmpty()) {
+ if (objects.get(0) instanceof UnknownObject)
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) objects.get(0)).getError())));
+
+ if (!(objects.get(0) instanceof PCEPLspObject))
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.LSP_MISSING)));
+
+ final PCEPLspObject lsp = (PCEPLspObject) objects.get(0);
+ objects.remove(0);
+
+ final List<CompositeRptPathObject> paths = new ArrayList<CompositeRptPathObject>();
+
+ if (!objects.isEmpty()) {
+ try {
+ CompositeRptPathObject path;
+ path = this.getValidCompositePath(objects);
+ while (path != null) {
+ paths.add(path);
+ if (objects.isEmpty())
+ break;
+ path = this.getValidCompositePath(objects);
+ }
+ } catch (final PCEPDocumentedException e) {
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+ }
+ }
+
+ report.add(new CompositeStateReportObject(lsp, paths));
+ }
+
+ if (report.isEmpty())
+ throw new PCEPDeserializerException("Atleast one CompositeStateReportObject is mandatory.");
+
+ if (!objects.isEmpty()) {
+ if (objects.get(0) instanceof UnknownObject)
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) objects.get(0)).getError())));
+ throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+ }
+
+ return Arrays.asList((PCEPMessage) new PCEPReportMessage(report));
+ }
+
+ private CompositeRptPathObject getValidCompositePath(final List<PCEPObject> objects) throws PCEPDocumentedException {
+ if (objects.get(0) instanceof UnknownObject)
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) objects.get(0)).getError());
+ if (!(objects.get(0) instanceof PCEPExplicitRouteObject))
+ return null;
+ final PCEPExplicitRouteObject explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+ objects.remove(0);
+
+ PCEPLspaObject pathLspa = null;
+ PCEPExistingPathBandwidthObject pathBandwidth = null;
+ PCEPReportedRouteObject pathRro = null;
+ final List<PCEPMetricObject> pathMetrics = new ArrayList<PCEPMetricObject>();
+
+ PCEPObject obj;
+ int state = 1;
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+ if (obj instanceof UnknownObject) {
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+ }
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPLspaObject) {
+ pathLspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPExistingPathBandwidthObject) {
+ pathBandwidth = (PCEPExistingPathBandwidthObject) obj;
+ break;
+ }
+
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPReportedRouteObject) {
+ pathRro = (PCEPReportedRouteObject) obj;
+ break;
+ }
+ case 4:
+ state = 5;
+ if (obj instanceof PCEPMetricObject) {
+ pathMetrics.add((PCEPMetricObject) obj);
+ state = 4;
+ break;
+ }
+ }
+
+ if (state == 5)
+ break;
+
+ objects.remove(0);
+ }
+
+ return new CompositeRptPathObject(explicitRoute, pathLspa, pathBandwidth, pathRro, pathMetrics);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.message.PCEPReportMessage
+ * PCEPReportMessage}
+ */
+public class PCEPRequestMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPRequestMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Needed PCEPRequestMessage.");
+
+ return PCEPObjectFactory.put(((PCEPRequestMessage) msg).getAllObjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestSvecObject;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+
+/**
+ * PCEPRequestMessage validator. Validates message integrity.
+ */
+public class PCEPRequestMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ final List<PCEPMessage> msgs = new ArrayList<PCEPMessage>();
+ final List<CompositeRequestSvecObject> svecList = new ArrayList<CompositeRequestSvecObject>();
+
+ CompositeRequestSvecObject svecComp;
+ while (!objects.isEmpty()) {
+ try {
+ if ((svecComp = getValidSvecComposite(objects)) == null)
+ break;
+ } catch (final PCEPDocumentedException e) {
+ msgs.add(new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+ return msgs;
+ }
+
+ svecList.add(svecComp);
+ }
+
+ while (!objects.isEmpty()) {
+ final List<CompositeRequestObject> requests = new ArrayList<CompositeRequestObject>();
+ PCEPRequestParameterObject rpObj = null;
+ boolean requestRejected = false;
+
+ if (objects.get(0) instanceof PCEPRequestParameterObject) {
+ rpObj = (PCEPRequestParameterObject) objects.get(0);
+ objects.remove(rpObj);
+ if (!rpObj.isProcessed()) {
+ msgs.add(new PCEPErrorMessage(new CompositeErrorObject(rpObj, new PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+ requestRejected = true;
+ }
+
+ } else {
+ // if RP obj is missing return error only;
+ msgs.clear();
+ msgs.add(new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.RP_MISSING)));
+ return msgs;
+ }
+
+ PCEPEndPointsObject<?> endPoints = null;
+ if (objects.get(0) instanceof PCEPEndPointsObject<?>) {
+ endPoints = (PCEPEndPointsObject<?>) objects.get(0);
+ objects.remove(0);
+ if (!endPoints.isProcessed()) {
+ msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+ requestRejected = true;
+ }
+ } else {
+ msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(PCEPErrors.END_POINTS_MISSING))));
+ requestRejected = true;
+ }
+
+ // ignore all continual end-points objects
+ while (!objects.isEmpty() && objects.get(0) instanceof PCEPEndPointsObject<?>) {
+ objects.remove(0);
+ }
+
+ PCEPClassTypeObject classType = null;
+ PCEPLspObject lsp = null;
+ PCEPLspaObject lspa = null;
+ PCEPRequestedPathBandwidthObject bandwidth = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+ PCEPReportedRouteObject rro = null;
+ PCEPExistingPathBandwidthObject rroBandwidth = null;
+ PCEPIncludeRouteObject iro = null;
+ PCEPLoadBalancingObject loadBalancing = null;
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+ if (obj instanceof UnknownObject) {
+ if (((UnknownObject) obj).isProcessed()) {
+ msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(((UnknownObject) obj).getError()))));
+ requestRejected = true;
+ }
+
+ objects.remove(0);
+ continue;
+ }
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPClassTypeObject) {
+ classType = (PCEPClassTypeObject) obj;
+ if (!classType.isProcessed()) {
+ msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+ requestRejected = true;
+ }
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPLspObject) {
+ lsp = (PCEPLspObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPLspaObject) {
+ lspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 4:
+ state = 5;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ bandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 5:
+ state = 6;
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 5;
+
+ break;
+ }
+ case 6:
+ state = 8;
+ if (obj instanceof PCEPReportedRouteObject) {
+ rro = (PCEPReportedRouteObject) obj;
+ state = 7;
+ break;
+ }
+ case 7:
+ state = 8;
+ if (obj instanceof PCEPExistingPathBandwidthObject) {
+ rroBandwidth = (PCEPExistingPathBandwidthObject) obj;
+ break;
+ }
+ case 8:
+ state = 9;
+ if (obj instanceof PCEPIncludeRouteObject) {
+ iro = (PCEPIncludeRouteObject) obj;
+ break;
+ }
+ case 9:
+ if (obj instanceof PCEPLoadBalancingObject) {
+ loadBalancing = (PCEPLoadBalancingObject) obj;
+ break;
+ }
+ state = 10;
+ }
+
+ if (state == 10) {
+ break;
+ }
+
+ objects.remove(obj);
+ }
+
+ if (rpObj.isReoptimized() && bandwidth != null && bandwidth.getBandwidth().compareTo(new Bandwidth(0)) > 0 && rro == null) {
+ msgs.add(new PCEPErrorMessage(new CompositeErrorObject(copyRP(rpObj, false), new PCEPErrorObject(PCEPErrors.RRO_MISSING))));
+ requestRejected = true;
+ }
+
+ if (!requestRejected) {
+ requests.add(new CompositeRequestObject(rpObj, endPoints, classType, lsp, lspa, bandwidth, metrics, rro, rroBandwidth, iro, loadBalancing));
+ msgs.add(new PCEPRequestMessage(Collections.unmodifiableList(svecList), Collections.unmodifiableList(requests)));
+ }
+ }
+
+ return msgs;
+ }
+
+ private static CompositeRequestSvecObject getValidSvecComposite(List<PCEPObject> objects) throws PCEPDocumentedException {
+ if (objects == null || objects.isEmpty()) {
+ throw new IllegalArgumentException("List cannot be null or empty.");
+ }
+
+ PCEPSvecObject svec = null;
+ if (objects.get(0) instanceof PCEPSvecObject) {
+ svec = (PCEPSvecObject) objects.get(0);
+ objects.remove(svec);
+ } else
+ return null;
+
+ PCEPObjectiveFunctionObject of = null;
+ PCEPGlobalConstraintsObject gc = null;
+ PCEPExcludeRouteObject xro = null;
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+
+ int state = 1;
+ while (!objects.isEmpty()) {
+ final PCEPObject obj = objects.get(0);
+
+ if (obj instanceof UnknownObject && ((UnknownObject) obj).isProcessed()) {
+ throw new PCEPDocumentedException("Unknown object in SVEC list.", ((UnknownObject) obj).getError());
+ }
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPObjectiveFunctionObject) {
+ of = (PCEPObjectiveFunctionObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPGlobalConstraintsObject) {
+ gc = (PCEPGlobalConstraintsObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPExcludeRouteObject) {
+ xro = (PCEPExcludeRouteObject) obj;
+ break;
+ }
+ case 4:
+ state = 5;
+ if (obj instanceof PCEPMetricObject) {
+ metrics.add((PCEPMetricObject) obj);
+ state = 4;
+
+ break;
+ }
+ }
+
+ if (state == 5)
+ break;
+
+ objects.remove(obj);
+ }
+
+ return new CompositeRequestSvecObject(svec, of, gc, xro, metrics);
+ }
+
+ private static PCEPRequestParameterObject copyRP(PCEPRequestParameterObject origRp, boolean processed) {
+ return new PCEPRequestParameterObject(origRp.isLoose(), origRp.isBidirectional(), origRp.isReoptimized(), origRp.isMakeBeforeBreak(),
+ origRp.isReportRequestOrder(), origRp.isSuplyOFOnResponse(), origRp.isFragmentation(), origRp.isP2mp(), origRp.isEroCompression(),
+ origRp.getPriority(), origRp.getRequestID(), origRp.getTlvs(), processed, origRp.isIgnored());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+
+public class PCEPUpdateRequestMessageParser implements PCEPMessageParser {
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPUpdateRequestMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPUpdateRequestMessage.");
+
+ return PCEPObjectFactory.put(((PCEPUpdateRequestMessage) msg).getAllObjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+import org.opendaylight.protocol.pcep.object.CompositeUpdPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+
+/**
+ * PCEPUpdateRequestMessage validator. Validates message integrity.
+ */
+public class PCEPUpdateRequestMessageValidator extends PCEPMessageValidator {
+
+ private static final Logger logger = LoggerFactory.getLogger(PCEPUpdateRequestMessageValidator.class);
+
+ @Override
+ public List<PCEPMessage> validate(final List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ final List<CompositeUpdateRequestObject> updateRequests = new ArrayList<CompositeUpdateRequestObject>();
+
+ while (!objects.isEmpty()) {
+ if (objects.get(0) instanceof UnknownObject) {
+ logger.warn("Unknown object found (should be Lsp) - {}.", objects.get(0));
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) objects.get(0)).getError())));
+ }
+ if (!(objects.get(0) instanceof PCEPLspObject))
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.LSP_MISSING)));
+
+ final PCEPLspObject lsp = (PCEPLspObject) objects.get(0);
+ objects.remove(0);
+
+ final List<CompositeUpdPathObject> paths = new ArrayList<CompositeUpdPathObject>();
+
+ if (!objects.isEmpty()) {
+ try {
+ CompositeUpdPathObject path;
+ path = this.getValidCompositePath(objects);
+ while (path != null) {
+ paths.add(path);
+ if (objects.isEmpty())
+ break;
+ path = this.getValidCompositePath(objects);
+ }
+ } catch (final PCEPDocumentedException e) {
+ logger.warn("Serializing failed: {}.", e);
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(e.getError())));
+ }
+ }
+
+ updateRequests.add(new CompositeUpdateRequestObject(lsp, paths));
+ }
+
+ if (updateRequests.isEmpty())
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(PCEPErrors.LSP_MISSING)));
+
+ if (!objects.isEmpty())
+ throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+ return Arrays.asList((PCEPMessage) new PCEPUpdateRequestMessage(updateRequests));
+ }
+
+ private CompositeUpdPathObject getValidCompositePath(final List<PCEPObject> objects) throws PCEPDocumentedException {
+ if (!(objects.get(0) instanceof PCEPExplicitRouteObject))
+ return null;
+
+ if (objects.get(0) instanceof UnknownObject)
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) objects.get(0)).getError());
+ final PCEPExplicitRouteObject explicitRoute = (PCEPExplicitRouteObject) objects.get(0);
+ objects.remove(0);
+
+ PCEPLspaObject pathLspa = null;
+ PCEPRequestedPathBandwidthObject pathBandwidth = null;
+ final List<PCEPMetricObject> pathMetrics = new ArrayList<PCEPMetricObject>();
+
+ PCEPObject obj;
+ int state = 1;
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+ if (obj instanceof UnknownObject) {
+ throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+ }
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPLspaObject) {
+ pathLspa = (PCEPLspaObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ if (obj instanceof PCEPRequestedPathBandwidthObject) {
+ pathBandwidth = (PCEPRequestedPathBandwidthObject) obj;
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPMetricObject) {
+ pathMetrics.add((PCEPMetricObject) obj);
+ state = 3;
+ break;
+ }
+ }
+
+ if (state == 4)
+ break;
+
+ objects.remove(0);
+ }
+
+ return new CompositeUpdPathObject(explicitRoute, pathLspa, pathBandwidth, pathMetrics);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+
+/**
+ * Parser for {@link #PCEPXRAddTunnelMessage} PCEPXRAddTunnelMessage
+ */
+public class PCEPXRAddTunnelMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPXRAddTunnelMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPXRAddTunnelMessage.");
+
+ return PCEPObjectFactory.put(((PCEPXRAddTunnelMessage) msg).getAllObjects());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+
+/**
+ * PCEPXRAddTunnelMessage validator. Validates message integrity.
+ */
+public class PCEPXRAddTunnelMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null)
+ throw new IllegalArgumentException("Passed list can't be null.");
+
+ PCEPObject obj;
+ int state = 1;
+
+ PCEPLspObject lsp = null;
+ PCEPEndPointsObject<?> ends = null;
+ PCEPExplicitRouteObject ero = null;
+
+ while (!objects.isEmpty()) {
+ obj = objects.get(0);
+ if (obj instanceof UnknownObject) {
+ return Arrays.asList((PCEPMessage) new PCEPErrorMessage(new PCEPErrorObject(((UnknownObject) obj).getError())));
+ }
+
+ switch (state) {
+ case 1:
+ state = 2;
+ if (obj instanceof PCEPLspObject) {
+ lsp = (PCEPLspObject) obj;
+ break;
+ }
+ case 2:
+ state = 3;
+ //FIXME: add support for ipv6?
+ if (obj instanceof PCEPEndPointsObject<?>) {
+ ends = ((PCEPEndPointsObject<?>) obj);
+ break;
+ }
+ case 3:
+ state = 4;
+ if (obj instanceof PCEPExplicitRouteObject) {
+ ero = (PCEPExplicitRouteObject) obj;
+ break;
+ }
+ }
+
+ objects.remove(0);
+
+ if (state == 4)
+ break;
+ }
+ if (lsp == null || ends == null || ero == null) {
+ throw new PCEPDeserializerException("All objects are mandatory.");
+ }
+
+ if (!objects.isEmpty())
+ throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+
+ PCEPXRAddTunnelMessage msg = null;
+
+ if (ends.getSourceAddress() instanceof IPv4Address && ends.getDestinationAddress() instanceof IPv4Address) {
+ /*
+ * The generic type is checked above.
+ */
+ @SuppressWarnings("unchecked")
+ final PCEPEndPointsObject<IPv4Address> ep = (PCEPEndPointsObject<IPv4Address>) ends;
+ msg = new PCEPXRAddTunnelMessage(lsp, ep, ero);
+ }
+ return Arrays.asList((PCEPMessage) msg);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectFactory;
+import org.opendaylight.protocol.pcep.message.PCEPXRDeleteTunnelMessage;
+
+public class PCEPXRDeleteTunnelMessageParser implements PCEPMessageParser {
+
+ @Override
+ public byte[] put(PCEPMessage msg) {
+ if (!(msg instanceof PCEPXRDeleteTunnelMessage))
+ throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + msg.getClass() + ". Nedded PCEPXRDeleteTunnelMessage.");
+
+ return PCEPObjectFactory.put(((PCEPXRDeleteTunnelMessage) msg).getAllObjects());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.message;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageValidator;
+import org.opendaylight.protocol.pcep.message.PCEPXRDeleteTunnelMessage;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+
+/**
+ * PCEPXRDeleteTunnelMessage validator. Validates message integrity.
+ */
+public class PCEPXRDeleteTunnelMessageValidator extends PCEPMessageValidator {
+
+ @Override
+ public List<PCEPMessage> validate(List<PCEPObject> objects) throws PCEPDeserializerException {
+ if (objects == null || objects.isEmpty())
+ throw new IllegalArgumentException("Passed list can't be null or empty.");
+
+ PCEPObject obj;
+
+ //PCEPRequestParameterObject rp = null;
+ PCEPLspObject lsp = null;
+ // PCEPNoPathObject noPath = null;
+
+ obj = objects.get(0);
+
+ if (obj instanceof PCEPLspObject) {
+ lsp = (PCEPLspObject) obj;
+ }
+
+ if (lsp == null) {
+ throw new PCEPDeserializerException("All objects are mandatory.");
+ }
+
+ return Arrays.asList((PCEPMessage) new PCEPXRDeleteTunnelMessage(lsp));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPBranchNodeListObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+public class PCEPBranchNodeListObjectParser implements PCEPObjectParser {
+
+ @Override
+ public PCEPBranchNodeListObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+ final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+ if (subobjects.isEmpty())
+ throw new PCEPDeserializerException("Empty Branch Node List Object.");
+
+ return new PCEPBranchNodeListObject(subobjects, processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPBranchNodeListObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPBranchNodeListObject.");
+
+ assert !(((PCEPBranchNodeListObject) obj).getSubobjects().isEmpty()) : "Empty Branch Node List Object.";
+
+ return PCEPEROSubobjectParser.put(((PCEPBranchNodeListObject) obj).getSubobjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPClassTypeObject PCEPClassTypeObject}
+ */
+public class PCEPClassTypeObjectParser implements PCEPObjectParser {
+
+ /**
+ * Length of Class Type field in bits.
+ */
+ public static final int CT_F_LENGTH = 3;
+
+ /**
+ * Reserved field bit length.
+ */
+ public static final int RESERVED = 29;
+
+ /**
+ * Size of the object in bytes.
+ */
+ public static final int SIZE = (RESERVED + CT_F_LENGTH) / 8;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored)
+ throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Byte array is mandatory.");
+ if (bytes.length != SIZE)
+ throw new PCEPDeserializerException("Size of byte array doesn't match defined size. Expected: " + SIZE + "; Passed: " + bytes.length);
+ if (!processed)
+ throw new PCEPDocumentedException("Processed bit not set", PCEPErrors.P_FLAG_NOT_SET);
+ final short classType = (short) (bytes[SIZE-1] & 0xFF);
+ if (classType < 0 || classType > 8) {
+ throw new PCEPDocumentedException("Invalid class type " + classType, PCEPErrors.INVALID_CT);
+ }
+ return new PCEPClassTypeObject(classType);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPClassTypeObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPClassTypeObject.");
+
+ final byte[] retBytes = new byte[SIZE];
+ retBytes[SIZE-1] = ByteArray.shortToBytes(((PCEPClassTypeObject) obj).getClassType())[1];
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPCloseObject PCEPCloseObject}
+ */
+public class PCEPCloseObjectParser implements PCEPObjectParser {
+
+ /*
+ * lengths of fields in bytes
+ */
+ public static final int FLAGS_F_LENGTH = 1;
+ public static final int REASON_F_LENGTH = 1;
+
+ /*
+ * offsets of fields in bytes
+ */
+ public static final int FLAGS_F_OFFSET = 2; // added reserved field of size 2 bytes
+ public static final int REASON_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+
+ /*
+ * total size of object in bytes
+ */
+ public static final int TLVS_F_OFFSET = REASON_F_OFFSET + REASON_F_LENGTH;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Byte array is mandatory.");
+
+ if (bytes.length != TLVS_F_OFFSET)
+ throw new PCEPDeserializerException("Size of byte array doesn't match defined size. Expected: " + TLVS_F_OFFSET + "; Passed: " + bytes.length);
+
+ Reason reason;
+ switch ((short) (bytes[REASON_F_OFFSET] & 0xFF)) {
+ case 1:
+ reason = Reason.UNKNOWN;
+ break;
+ case 2:
+ reason = Reason.EXP_DEADTIMER;
+ break;
+ case 3:
+ reason = Reason.MALFORMED_MSG;
+ break;
+ case 4:
+ reason = Reason.TOO_MANY_UNKNOWN_REQ_REP;
+ break;
+ case 5:
+ reason = Reason.TOO_MANY_UNKNOWN_MSG;
+ break;
+ default:
+ reason = Reason.UNKNOWN;
+ break;
+ }
+
+ return new PCEPCloseObject(reason, PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_F_OFFSET)));
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPCloseObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPCloseObject.");
+
+ final byte[] tlvs = PCEPTlvParser.put(((PCEPCloseObject) obj).getTlvs());
+ final byte[] retBytes = new byte[TLVS_F_OFFSET + tlvs.length];
+ ByteArray.copyWhole(tlvs, retBytes, TLVS_F_OFFSET);
+
+ int reason;
+ switch (((PCEPCloseObject) obj).getReason()) {
+ case UNKNOWN:
+ reason = 1;
+ break;
+ case EXP_DEADTIMER:
+ reason = 2;
+ break;
+ case MALFORMED_MSG:
+ reason = 3;
+ break;
+ case TOO_MANY_UNKNOWN_REQ_REP:
+ reason = 4;
+ break;
+ case TOO_MANY_UNKNOWN_MSG:
+ reason = 5;
+ break;
+ default:
+ reason = 1;
+ break;
+ }
+
+ retBytes[REASON_F_OFFSET] = (byte) reason;
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for IPv4 {@link org.opendaylight.protocol.pcep.object.PCEPEndPointsObject
+ * PCEPEndPointsObject}
+ */
+public class PCEPEndPointsIPv4ObjectParser implements PCEPObjectParser {
+
+ /*
+ * fields lengths and offsets for IPv4 in bytes
+ */
+ public static final int SRC4_F_LENGTH = 4;
+ public static final int DEST4_F_LENGTH = 4;
+
+ public static final int SRC4_F_OFFSET = 0;
+ public static final int DEST4_F_OFFSET = SRC4_F_OFFSET + SRC4_F_LENGTH;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory");
+ if (bytes.length != SRC4_F_LENGTH + DEST4_F_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes.");
+
+ //FIXME: create new constructor which allows processed parameter - needed for validation
+ return new PCEPEndPointsObject<IPv4Address>(
+ new IPv4Address(ByteArray.subByte(bytes, SRC4_F_OFFSET, SRC4_F_LENGTH)),
+ new IPv4Address(ByteArray.subByte(bytes, DEST4_F_OFFSET, DEST4_F_LENGTH)));
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPEndPointsObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPEndPointsObject.");
+
+ final PCEPEndPointsObject<?> ePObj = (PCEPEndPointsObject<?>) obj;
+
+ if (!(ePObj.getSourceAddress() instanceof IPv4Address))
+ throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + ePObj.getSourceAddress().getClass() + ". Needed IPv4Address");
+
+ final byte[] retBytes = new byte[SRC4_F_LENGTH + DEST4_F_LENGTH];
+ ByteArray.copyWhole(((IPv4Address) ePObj.getSourceAddress()).getAddress(), retBytes, SRC4_F_OFFSET);
+ ByteArray.copyWhole(((IPv4Address) ePObj.getDestinationAddress()).getAddress(), retBytes, DEST4_F_OFFSET);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for IPv6 {@link org.opendaylight.protocol.pcep.object.PCEPEndPointsObject
+ * PCEPEndPointsObject}
+ */
+public class PCEPEndPointsIPv6ObjectParser implements PCEPObjectParser {
+
+ public static final int SRC6_F_LENGTH = 16;
+ public static final int DEST6_F_LENGT = 16;
+
+ public static final int SRC6_F_OFFSET = 0;
+ public static final int DEST6_F_OFFSET = SRC6_F_OFFSET + SRC6_F_LENGTH;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory");
+ if (bytes.length != SRC6_F_LENGTH + DEST6_F_LENGT)
+ throw new PCEPDeserializerException("Wrong length of array of bytes.");
+
+ if (!processed)
+ throw new PCEPDocumentedException("Processed flag not set", PCEPErrors.P_FLAG_NOT_SET);
+
+ return new PCEPEndPointsObject<IPv6Address>(
+ new IPv6Address(ByteArray.subByte(bytes, SRC6_F_OFFSET, SRC6_F_LENGTH)),
+ new IPv6Address(ByteArray.subByte(bytes, DEST6_F_OFFSET, DEST6_F_LENGT)));
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPEndPointsObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPEndPointsObject.");
+
+ final PCEPEndPointsObject<?> ePObj = (PCEPEndPointsObject<?>) obj;
+
+ if (!(ePObj.getSourceAddress() instanceof IPv6Address))
+ throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + ePObj.getSourceAddress().getClass() + ". Needed IPv6Address");
+
+ final byte[] retBytes = new byte[SRC6_F_LENGTH + DEST6_F_LENGT];
+ ByteArray.copyWhole(((IPv6Address) ePObj.getSourceAddress()).getAddress(), retBytes, SRC6_F_OFFSET);
+ ByteArray.copyWhole(((IPv6Address) ePObj.getDestinationAddress()).getAddress(), retBytes, DEST6_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPErrorObject PCEPErrorObject}
+ */
+public class PCEPErrorObjectParser implements PCEPObjectParser {
+ /**
+ * Caret for combination of Error-type and Error-value
+ */
+ public static class PCEPErrorIdentifier {
+ public final short type;
+ public final short value;
+
+ private PCEPErrorIdentifier(final short type, final short value) {
+ this.type = type;
+ this.value = value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.type;
+ result = prime * result + this.value;
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+ final PCEPErrorIdentifier other = (PCEPErrorIdentifier) obj;
+ if (this.type != other.type)
+ return false;
+ if (this.value != other.value)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "type " + this.type + " value " + this.value;
+ }
+ }
+
+ /**
+ * Bidirectional mapping of {@link org.opendaylight.protocol.pcep.PCEPErrors PCEPErrors}
+ * and
+ * {@link org.opendaylight.protocol.pcep.impl.object.PCEPErrorObjectParser.PCEPErrorIdentifier
+ * ErrorIdentifier}
+ */
+ public static class PCEPErrorsMaping {
+ private static final PCEPErrorsMaping instance = new PCEPErrorsMaping();
+
+ private final Map<PCEPErrors, PCEPErrorIdentifier> errorsMap = new HashMap<PCEPErrors, PCEPErrorIdentifier>();
+ private final Map<PCEPErrorIdentifier, PCEPErrors> errorIdsMap = new HashMap<PCEPErrorIdentifier, PCEPErrors>();
+
+ private PCEPErrorsMaping() {
+ this.fillIn();
+ }
+
+ private void fillIn() {
+ this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 1), PCEPErrors.NON_OR_INVALID_OPEN_MSG);
+ this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 2), PCEPErrors.NO_OPEN_BEFORE_EXP_OPENWAIT);
+ this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 3), PCEPErrors.NON_ACC_NON_NEG_SESSION_CHAR);
+ this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 4), PCEPErrors.NON_ACC_NEG_SESSION_CHAR);
+ this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 5), PCEPErrors.SECOND_OPEN_MSG);
+ this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 6), PCEPErrors.PCERR_NON_ACC_SESSION_CHAR);
+ this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 7), PCEPErrors.NO_MSG_BEFORE_EXP_KEEPWAIT);
+ this.fillIn(new PCEPErrorIdentifier((short) 1, (short) 8), PCEPErrors.PCEP_VERSION_NOT_SUPPORTED);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 2, (short) 0), PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 3, (short) 1), PCEPErrors.UNRECOGNIZED_OBJ_CLASS);
+ this.fillIn(new PCEPErrorIdentifier((short) 3, (short) 2), PCEPErrors.UNRECOGNIZED_OBJ_TYPE);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 4, (short) 1), PCEPErrors.NOT_SUPPORTED_OBJ_CLASS);
+ this.fillIn(new PCEPErrorIdentifier((short) 4, (short) 2), PCEPErrors.NOT_SUPPORTED_OBJ_TYPE);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 1), PCEPErrors.C_BIT_SET);
+ this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 2), PCEPErrors.O_BIT_SET);
+ this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 3), PCEPErrors.OF_NOT_ALLOWED);
+ this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 4), PCEPErrors.OF_BIT_SET);
+ this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 5), PCEPErrors.GCO_NOT_ALLOWED);
+ this.fillIn(new PCEPErrorIdentifier((short) 5, (short) 7), PCEPErrors.P2MP_COMPUTATION_NOT_ALLOWED);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 1), PCEPErrors.RP_MISSING);
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 2), PCEPErrors.RRO_MISSING);
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 3), PCEPErrors.END_POINTS_MISSING);
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 8), PCEPErrors.LSP_MISSING);
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 9), PCEPErrors.ERO_MISSING);
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 10), PCEPErrors.BANDWIDTH_MISSING);
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 11), PCEPErrors.LSPA_MISSING);
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 12), PCEPErrors.DB_VERSION_TLV_MISSING);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 13), PCEPErrors.LSP_CLEANUP_TLV_MISSING);
+ this.fillIn(new PCEPErrorIdentifier((short) 6, (short) 14), PCEPErrors.SYMBOLIC_PATH_NAME_MISSING);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 7, (short) 0), PCEPErrors.SYNC_PATH_COMP_REQ_MISSING);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 8, (short) 0), PCEPErrors.UNKNOWN_REQ_REF);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 9, (short) 0), PCEPErrors.ATTEMPT_2ND_SESSION);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 10, (short) 1), PCEPErrors.P_FLAG_NOT_SET);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 12, (short) 1), PCEPErrors.UNSUPPORTED_CT);
+ this.fillIn(new PCEPErrorIdentifier((short) 12, (short) 2), PCEPErrors.INVALID_CT);
+ this.fillIn(new PCEPErrorIdentifier((short) 12, (short) 3), PCEPErrors.CT_AND_SETUP_PRIORITY_DO_NOT_FORM_TE_CLASS);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 15, (short) 1), PCEPErrors.INSUFFICIENT_MEMORY);
+ this.fillIn(new PCEPErrorIdentifier((short) 15, (short) 2), PCEPErrors.GCO_NOT_SUPPORTED);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 16, (short) 1), PCEPErrors.CANNOT_SATISFY_P2MP_REQUEST_DUE_TO_INSUFFISIENT_MEMMORY);
+ this.fillIn(new PCEPErrorIdentifier((short) 16, (short) 2), PCEPErrors.NOT_CAPPABLE_P2MP_COMPUTATION);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 17, (short) 1), PCEPErrors.P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT2);
+ this.fillIn(new PCEPErrorIdentifier((short) 17, (short) 2), PCEPErrors.P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT3);
+ this.fillIn(new PCEPErrorIdentifier((short) 17, (short) 3), PCEPErrors.P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_LT4);
+ this.fillIn(new PCEPErrorIdentifier((short) 17, (short) 4), PCEPErrors.P2MP_NOT_CAPPABLE_SATISFY_REQ_DUE_INCONSISTENT_EP);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 18, (short) 1), PCEPErrors.P2MP_FRAGMENTATION_FAILRUE);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 19, (short) 1), PCEPErrors.UPDATE_REQ_FOR_NON_LSP);
+ this.fillIn(new PCEPErrorIdentifier((short) 19, (short) 2), PCEPErrors.UPDATE_REQ_FOR_NO_STATEFUL);
+ //TODO: value TBD
+ this.fillIn(new PCEPErrorIdentifier((short) 19, (short) 3), PCEPErrors.LSP_LIMIT_REACHED);
+ this.fillIn(new PCEPErrorIdentifier((short) 19, (short) 4), PCEPErrors.DELEGATION_NOT_REVOKED);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 20, (short) 1), PCEPErrors.CANNOT_PROCESS_STATE_REPORT);
+ this.fillIn(new PCEPErrorIdentifier((short) 20, (short) 2), PCEPErrors.LSP_DB_VERSION_MISMATCH);
+ this.fillIn(new PCEPErrorIdentifier((short) 20, (short) 3), PCEPErrors.DB_VERSION_TLV_MISSING_WHEN_SYNC_ALLOWED);
+
+ this.fillIn(new PCEPErrorIdentifier((short) 23, (short) 1), PCEPErrors.USED_SYMBOLIC_PATH_NAME);
+ }
+
+ private void fillIn(final PCEPErrorIdentifier identifier, final PCEPErrors error) {
+ this.errorsMap.put(error, identifier);
+ this.errorIdsMap.put(identifier, error);
+ }
+
+ public PCEPErrorIdentifier getFromErrorsEnum(final PCEPErrors error) {
+ final PCEPErrorIdentifier ei = this.errorsMap.get(error);
+ if (ei == null) {
+ logger.debug("Unknown PCEPErrors type: {}.", error);
+ throw new NoSuchElementException("Unknown PCEPErrors type: " + error);
+ }
+ return ei;
+ }
+
+ public PCEPErrors getFromErrorIdentifier(final PCEPErrorIdentifier identifier) {
+ final PCEPErrors e = this.errorIdsMap.get(identifier);
+ if (e == null) {
+ logger.debug("Unknown error type/value combination: {}.", identifier);
+ throw new NoSuchElementException("Unknown error type/value combination: " + identifier);
+ }
+ return e;
+ }
+
+ public static PCEPErrorsMaping getInstance() {
+ return instance;
+ }
+ }
+
+ public static final int FLAGS_F_LENGTH = 1;
+ public static final int ET_F_LENGTH = 1;
+ public static final int EV_F_LENGTH = 1;
+
+ public static final int FLAGS_F_OFFSET = 1; //added reserved field of size 1 byte
+ public static final int ET_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+ public static final int EV_F_OFFSET = ET_F_OFFSET + ET_F_LENGTH;
+ public static final int TLVS_OFFSET = EV_F_OFFSET + EV_F_LENGTH;
+
+ private final static Logger logger = LoggerFactory.getLogger(PCEPErrorObjectParser.class);
+
+ @Override
+ public PCEPObject parse(final byte[] bytes, final boolean processed, final boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory.");
+
+ if (bytes.length < TLVS_OFFSET)
+ throw new PCEPDeserializerException("Wrong size of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET);
+
+ final PCEPErrorIdentifier eid = new PCEPErrorIdentifier((short) (bytes[ET_F_OFFSET] & 0xFF), (short) (bytes[EV_F_OFFSET] & 0xFF));
+ final PCEPErrors error;
+
+ try {
+ error = PCEPErrorsMaping.getInstance().getFromErrorIdentifier(eid);
+ } catch (final NoSuchElementException e) {
+ logger.debug("Failed to identify error {}", eid, e);
+ throw new PCEPDeserializerException(e, "Error object has unknown identifier.");
+ }
+
+ return new PCEPErrorObject(error, PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET)));
+ }
+
+ @Override
+ public byte[] put(final PCEPObject obj) {
+ if (!(obj instanceof PCEPErrorObject))
+ throw new IllegalArgumentException("Unknown PCEPObject instance.");
+
+ final PCEPErrorObject errObj = (PCEPErrorObject) obj;
+
+ final byte[] tlvs = PCEPTlvParser.put(errObj.getTlvs());
+ final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+
+ ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+ final PCEPErrorIdentifier identifier = PCEPErrorsMaping.getInstance().getFromErrorsEnum(errObj.getError());
+
+ retBytes[ET_F_OFFSET] = ByteArray.shortToBytes(identifier.type)[1];
+ retBytes[EV_F_OFFSET] = ByteArray.shortToBytes(identifier.value)[1];
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.List;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPXROSubobjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject
+ * PCEPExcludeRouteObject}
+ */
+public class PCEPExcludeRouteObjectParser implements PCEPObjectParser {
+
+ /*
+ * lengths of fields in bytes
+ */
+ public final int FLAGS_F_LENGTH = 2;
+
+ /*
+ * offsets of fields in bytes
+ */
+ public final int FLAGS_F_OFFSET = 2; // added reserved 2 bytes
+ public final int SO_F_OFFSET = this.FLAGS_F_OFFSET + this.FLAGS_F_LENGTH;
+
+ /*
+ * Flag offsets inside flags field in bits
+ */
+ public final int F_FLAG_OFFSET = 15;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+ final BitSet flags = ByteArray.bytesToBitSet(Arrays.copyOfRange(bytes, this.FLAGS_F_OFFSET, this.FLAGS_F_LENGTH));
+
+ final List<ExcludeRouteSubobject> subobjects = PCEPXROSubobjectParser.parse(ByteArray.cutBytes(bytes, this.SO_F_OFFSET));
+ if (subobjects.isEmpty())
+ throw new PCEPDeserializerException("Empty Exclude Route Object.");
+
+ return new PCEPExcludeRouteObject(subobjects, flags.get(this.F_FLAG_OFFSET), processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPExcludeRouteObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPExcludeRouteObject.");
+
+ assert !(((PCEPExcludeRouteObject) obj).getSubobjects().isEmpty()) : "Empty Exclude Route Object.";
+
+ final byte[] subObjsBytes = PCEPXROSubobjectParser.put(((PCEPExcludeRouteObject) obj).getSubobjects());
+ final byte[] retBytes = new byte[this.SO_F_OFFSET + subObjsBytes.length];
+ final BitSet flags = new BitSet(this.FLAGS_F_LENGTH * Byte.SIZE);
+ flags.set(this.F_FLAG_OFFSET, ((PCEPExcludeRouteObject) obj).isFail());
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, this.FLAGS_F_LENGTH), retBytes, this.FLAGS_F_OFFSET);
+ ByteArray.copyWhole(subObjsBytes, retBytes, this.SO_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject
+ * PCEPExistingPathBandwidthObject}
+ */
+public class PCEPExistingPathBandwidthObjectParser implements PCEPObjectParser {
+
+ private static final int BANDWIDTH_F_LENGTH = 4;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory");
+ if (bytes.length != BANDWIDTH_F_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + BANDWIDTH_F_LENGTH + ".");
+
+ return new PCEPExistingPathBandwidthObject(new Bandwidth(ByteArray.bytesToFloat(bytes)), processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPExistingPathBandwidthObject))
+ throw new IllegalArgumentException("Unknown PCEPObject instance.");
+
+ return ByteArray.floatToBytes((float) ((PCEPExistingPathBandwidthObject) obj).getBandwidth().getBytesPerSecond());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject
+ * PCEPExplicitRouteObject}
+ */
+public class PCEPExplicitRouteObjectParser implements PCEPObjectParser {
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+ final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+ if (subobjects.isEmpty())
+ throw new PCEPDeserializerException("Empty Explicit Route Object.");
+
+ return new PCEPExplicitRouteObject(subobjects, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPExplicitRouteObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPExplicitRouteObject.");
+
+ assert !(((PCEPExplicitRouteObject) obj).getSubobjects().isEmpty()) : "Empty Explicit Route Object.";
+
+ return PCEPEROSubobjectParser.put(((PCEPExplicitRouteObject) obj).getSubobjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject
+ * PCEPGlobalConstraints}
+ */
+public class PCEPGlobalConstraintsObjectParser implements PCEPObjectParser {
+
+ private final static int MAX_HOP_F_LENGTH = 1;
+ private final static int MAX_UTIL_F_LENGTH = 1;
+ private final static int MIN_UTIL_F_LENGTH = 1;
+ private final static int OVER_BOOKING_FACTOR_F_LENGTH = 1;
+
+ private final static int MAX_HOP_F_OFFSET = 0;
+ private final static int MAX_UTIL_F_OFFSET = MAX_HOP_F_OFFSET + MAX_HOP_F_LENGTH;
+ private final static int MIN_UTIL_F_OFFSET = MAX_UTIL_F_OFFSET + MAX_UTIL_F_LENGTH;
+ private final static int OVER_BOOKING_FACTOR_F_OFFSET = MIN_UTIL_F_OFFSET + MIN_UTIL_F_LENGTH;
+
+ private final static int TLVS_OFFSET = OVER_BOOKING_FACTOR_F_OFFSET + OVER_BOOKING_FACTOR_F_LENGTH;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (bytes.length < TLVS_OFFSET)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+ return new PCEPGlobalConstraintsObject((short) (bytes[MAX_HOP_F_OFFSET] & 0xFF), (short) (bytes[MAX_UTIL_F_OFFSET] & 0xFF),
+ (short) (bytes[MIN_UTIL_F_OFFSET] & 0xFF), (short) (bytes[OVER_BOOKING_FACTOR_F_OFFSET] & 0xFF), PCEPTlvParser.parse(ByteArray.cutBytes(bytes,
+ TLVS_OFFSET)), processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPGlobalConstraintsObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPGlobalConstraints.");
+
+ final PCEPGlobalConstraintsObject specObj = (PCEPGlobalConstraintsObject) obj;
+
+ final byte[] tlvs = PCEPTlvParser.put(specObj.getTlvs());
+ final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+
+ retBytes[MAX_HOP_F_OFFSET] = (byte) specObj.getMaxHop();
+ retBytes[MAX_UTIL_F_OFFSET] = (byte) specObj.getMaxUtilization();
+ retBytes[MIN_UTIL_F_OFFSET] = (byte) specObj.getMinUtilization();
+ retBytes[OVER_BOOKING_FACTOR_F_OFFSET] = (byte) specObj.getOverBookingFactor();
+
+ ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject
+ * PCEPIncludeRouteObject}
+ */
+public class PCEPIncludeRouteObjectParser implements PCEPObjectParser {
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+ final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+ if (subobjects.isEmpty())
+ throw new PCEPDeserializerException("Empty Include Route Object.");
+
+ return new PCEPIncludeRouteObject(subobjects, processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPIncludeRouteObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPIncludeRouteObject.");
+
+ assert !(((PCEPIncludeRouteObject) obj).getSubobjects().isEmpty()) : "Empty Include Route Object.";
+
+ return PCEPEROSubobjectParser.put(((PCEPIncludeRouteObject) obj).getSubobjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject
+ * PCEPLoadBalancingObject}
+ */
+public class PCEPLoadBalancingObjectParser implements PCEPObjectParser {
+
+ public static final int FLAGS_F_LENGTH = 1;
+ public static final int MAX_LSP_F_LENGTH = 1;
+ public static final int MIN_BAND_F_LENGTH = 4;
+
+ public static final int FLAGS_F_OFFSET = 2;
+ public static final int MAX_LSP_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+ public static final int MIN_BAND_F_OFFSET = MAX_LSP_F_OFFSET + MAX_LSP_F_LENGTH;
+
+ public static final int SIZE = MIN_BAND_F_OFFSET + MIN_BAND_F_LENGTH;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+ if (bytes.length != SIZE)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + SIZE + ".");
+
+ return new PCEPLoadBalancingObject(bytes[MAX_LSP_F_OFFSET] & 0xFF, new Bandwidth(ByteArray.bytesToFloat(ByteArray.subByte(bytes, MIN_BAND_F_OFFSET,
+ MIN_BAND_F_LENGTH))), processed);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPLoadBalancingObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPLoadBalancingObject.");
+
+ final PCEPLoadBalancingObject specObj = (PCEPLoadBalancingObject) obj;
+
+ final byte[] retBytes = new byte[SIZE];
+
+ retBytes[MAX_LSP_F_OFFSET] = ByteArray.intToBytes(specObj.getMaxLSP())[Integer.SIZE / Byte.SIZE - 1];
+ ByteArray.copyWhole(ByteArray.floatToBytes((float) specObj.getMinBandwidth().getBytesPerSecond()), retBytes, MIN_BAND_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPLspObject PCEPLspObject}
+ */
+public class PCEPLspObjectParser implements PCEPObjectParser {
+
+ /*
+ * offset of TLVs offset of other fields are not defined as constants
+ * because of non-standard mapping of bits
+ */
+ public static final int TLVS_OFFSET = 4;
+
+ /*
+ * 12b extended to 16b so first 4b are restricted (belongs to LSP ID)
+ */
+ private static final int DELEGATE_FLAG_OFFSET = 15;
+ private static final int OPERATIONAL_FLAG_OFFSET = 13;
+ private static final int SYNC_FLAG_OFFSET = 14;
+ private static final int REMOVE_FLAG_OFFSET = 12;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (bytes.length < TLVS_OFFSET)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+ final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(bytes, 2, 2));
+
+ return new PCEPLspObject((ByteArray.bytesToShort(ByteArray.subByte(bytes, 0, 2)) & 0xFFFF) << 4 | (bytes[2] & 0xFF) >> 4,
+ flags.get(DELEGATE_FLAG_OFFSET), flags.get(SYNC_FLAG_OFFSET), flags.get(OPERATIONAL_FLAG_OFFSET), flags.get(REMOVE_FLAG_OFFSET),
+ PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET)));
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPLspObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPLspObject.");
+
+ final PCEPLspObject specObj = (PCEPLspObject) obj;
+
+ final byte[] tlvs = PCEPTlvParser.put(specObj.getTlvs());
+
+ final byte[] retBytes = new byte[tlvs.length + TLVS_OFFSET];
+
+ final int lspID = specObj.getLspID();
+ retBytes[0] = (byte) (lspID >> 12);
+ retBytes[1] = (byte) (lspID >> 4);
+ retBytes[2] = (byte) (lspID << 4);
+ if (specObj.isDelegate())
+ retBytes[3] |= 1 << (Byte.SIZE - (DELEGATE_FLAG_OFFSET - Byte.SIZE) - 1);
+ if (specObj.isOperational())
+ retBytes[3] |= 1 << (Byte.SIZE - (OPERATIONAL_FLAG_OFFSET - Byte.SIZE) - 1);
+ if (specObj.isRemove())
+ retBytes[3] |= 1 << (Byte.SIZE - (REMOVE_FLAG_OFFSET - Byte.SIZE) - 1);
+ if (specObj.isSync())
+ retBytes[3] |= 1 << (Byte.SIZE - (SYNC_FLAG_OFFSET - Byte.SIZE) - 1);
+
+ ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPLspaObject PCEPLspaObject}
+ */
+public class PCEPLspaObjectParser implements PCEPObjectParser {
+
+ /*
+ * lenghts of fields in bytes
+ */
+ public static final int EXC_ANY_F_LENGTH = 4;
+ public static final int INC_ANY_F_LENGTH = 4;
+ public static final int INC_ALL_F_LENGTH = 4;
+ public static final int SET_PRIO_F_LENGTH = 1;
+ public static final int HOLD_PRIO_F_LENGTH = 1;
+ public static final int FLAGS_F_LENGTH = 1;
+
+ /*
+ * offsets of flags inside flags field in bits
+ */
+ public static final int S_FLAG_OFFSET = 6;
+ public static final int L_FLAG_OFFSET = 7;
+
+ /*
+ * offsets of fields in bytes
+ */
+ public static final int EXC_ANY_F_OFFSET = 0;
+ public static final int INC_ANY_F_OFFSET = EXC_ANY_F_OFFSET + EXC_ANY_F_LENGTH;
+ public static final int INC_ALL_F_OFFSET = INC_ANY_F_OFFSET + INC_ANY_F_LENGTH;
+ public static final int SET_PRIO_F_OFFSET = INC_ALL_F_OFFSET + INC_ALL_F_LENGTH;
+ public static final int HOLD_PRIO_F_OFFSET = SET_PRIO_F_OFFSET + SET_PRIO_F_LENGTH;
+ public static final int FLAGS_F_OFFSET = HOLD_PRIO_F_OFFSET + HOLD_PRIO_F_LENGTH;
+ public static final int TLVS_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH + 1; //added reserved field of length 1B
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Bytes array is mandatory.");
+
+ final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(bytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+
+ return new PCEPLspaObject(UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, EXC_ANY_F_OFFSET, EXC_ANY_F_LENGTH))),
+ UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, INC_ANY_F_OFFSET, INC_ANY_F_LENGTH))), UnsignedInts.toLong(ByteArray
+ .bytesToInt(ByteArray.subByte(bytes, INC_ALL_F_OFFSET, INC_ALL_F_LENGTH))), (short) (bytes[SET_PRIO_F_OFFSET] & 0xFF),
+ (short) (bytes[HOLD_PRIO_F_OFFSET] & 0xFF), flags.get(S_FLAG_OFFSET), flags.get(L_FLAG_OFFSET), PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_F_OFFSET)), processed,
+ ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPLspaObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPLspaObject.");
+
+ final PCEPLspaObject lspaObj = (PCEPLspaObject) obj;
+
+ final byte[] tlvs = PCEPTlvParser.put(lspaObj.getTlvs());
+ final byte[] retBytes = new byte[TLVS_F_OFFSET + tlvs.length];
+ ByteArray.copyWhole(tlvs, retBytes, TLVS_F_OFFSET);
+
+ System.arraycopy(ByteArray.longToBytes(lspaObj.getExcludeAny()), 4, retBytes, EXC_ANY_F_OFFSET, EXC_ANY_F_LENGTH);
+ System.arraycopy(ByteArray.longToBytes(lspaObj.getIncludeAny()), 4, retBytes, INC_ANY_F_OFFSET, INC_ANY_F_LENGTH);
+ System.arraycopy(ByteArray.longToBytes(lspaObj.getIncludeAll()), 4, retBytes, INC_ALL_F_OFFSET, INC_ALL_F_LENGTH);
+ retBytes[SET_PRIO_F_OFFSET] = ByteArray.shortToBytes(lspaObj.getSetupPriority())[Short.SIZE / Byte.SIZE - 1];
+ retBytes[HOLD_PRIO_F_OFFSET] = ByteArray.shortToBytes(lspaObj.getHoldingPriority())[Short.SIZE / Byte.SIZE - 1];
+
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+ flags.set(S_FLAG_OFFSET, lspaObj.isStandByPath());
+ flags.set(L_FLAG_OFFSET, lspaObj.isLocalProtected());
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.concepts.AbstractMetric;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.concepts.AggregateBandwidthConsumptionMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeIGPCostMetric;
+import org.opendaylight.protocol.pcep.concepts.CumulativeTECostMetric;
+import org.opendaylight.protocol.pcep.concepts.MostLoadedLinkLoadMetric;
+import org.opendaylight.protocol.pcep.concepts.P2MPHopCountMetric;
+import org.opendaylight.protocol.pcep.concepts.P2MPIGPMetric;
+import org.opendaylight.protocol.pcep.concepts.P2MPTEMetric;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPMetricObject
+ * PCEPMetricObject}
+ */
+public class PCEPMetricObjectParser implements PCEPObjectParser {
+
+ /*
+ * lengths of fields in bytes
+ */
+ private static final int FLAGS_F_LENGTH = 1;
+ private static final int TYPE_F_LENGTH = 1;
+ private static final int METRIC_VALUE_F_LENGTH = 4;
+
+ /*
+ * offsets of fields in bytes
+ */
+ public static final int FLAGS_F_OFFSET = 2;
+ public static final int TYPE_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+ public static final int METRIC_VALUE_F_OFFSET = TYPE_F_OFFSET + TYPE_F_LENGTH;
+
+ /*
+ * flags offsets inside flags field in bits
+ */
+ private static final int C_FLAG_OFFSET = 6;
+ private static final int B_FLAG_OFFSET = 7;
+
+ public static final int SIZE = METRIC_VALUE_F_OFFSET + METRIC_VALUE_F_LENGTH;
+
+ /**
+ * Bidirectional mapping for metrics. Maps metric class to integer and
+ * integer to metrics instantiable.
+ */
+ public static class PCEPMetricsMapping {
+ private static final PCEPMetricsMapping instance = new PCEPMetricsMapping();
+
+ private final Map<Class<?>, Integer> metricsMap = new HashMap<Class<?>, Integer>();
+ private final Map<Integer, InstantiableMetric> metrictTypesMap = new HashMap<Integer, InstantiableMetric>();
+
+ private interface InstantiableMetric {
+ public AbstractMetric<?> getMetric(long metric);
+ }
+
+ private PCEPMetricsMapping() {
+ this.fillIn();
+ }
+
+ private void fillIn() {
+ this.fillIn(1, IGPMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new IGPMetric(metric);
+ }
+
+ });
+ this.fillIn(2, TEMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new TEMetric(metric);
+ }
+
+ });
+ this.fillIn(4, AggregateBandwidthConsumptionMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new AggregateBandwidthConsumptionMetric(metric);
+ }
+
+ });
+ this.fillIn(5, MostLoadedLinkLoadMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new MostLoadedLinkLoadMetric(metric);
+ }
+
+ });
+ this.fillIn(6, CumulativeIGPCostMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new CumulativeIGPCostMetric(metric);
+ }
+
+ });
+ this.fillIn(7, CumulativeTECostMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new CumulativeTECostMetric(metric);
+ }
+
+ });
+ this.fillIn(8, P2MPIGPMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new P2MPIGPMetric(metric);
+ }
+
+ });
+ this.fillIn(9, P2MPTEMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new P2MPHopCountMetric(metric);
+ }
+
+ });
+ this.fillIn(10, P2MPHopCountMetric.class, new InstantiableMetric() {
+
+ @Override
+ public AbstractMetric<?> getMetric(long metric) {
+ return new P2MPHopCountMetric(metric);
+ }
+
+ });
+ }
+
+ private void fillIn(int type, Class<?> metricClazz, InstantiableMetric instantiable) {
+ this.metricsMap.put(metricClazz, type);
+ this.metrictTypesMap.put(type, instantiable);
+ }
+
+ public int getFromMetricClass(Class<? extends AbstractMetric<?>> clazz) {
+ final Integer mi = this.metricsMap.get(clazz);
+ if (mi == null)
+ throw new NoSuchElementException("Unknown Metric: " + clazz);
+ return mi;
+ }
+
+ public AbstractMetric<?> getFromMetricTypeIdentifier(int identifier, long metric) {
+ final InstantiableMetric e = this.metrictTypesMap.get(identifier);
+ if (e == null)
+ throw new NoSuchElementException("Unknown metric type identifier. Passed: " + identifier);
+ return e.getMetric(metric);
+ }
+
+ public static PCEPMetricsMapping getInstance() {
+ return instance;
+ }
+ }
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (bytes.length != SIZE)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + SIZE + ".");
+
+ final byte[] flagBytes = { bytes[FLAGS_F_OFFSET] };
+ final BitSet flags = ByteArray.bytesToBitSet(flagBytes);
+ try {
+ return new PCEPMetricObject(flags.get(B_FLAG_OFFSET), flags.get(C_FLAG_OFFSET), PCEPMetricsMapping.getInstance().getFromMetricTypeIdentifier(
+ (short) (bytes[TYPE_F_OFFSET] & 0xFF),
+ (long) ByteArray.bytesToFloat(ByteArray.subByte(bytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH))), processed, ignored);
+ } catch (final NoSuchElementException e) {
+ throw new PCEPDeserializerException(e, "Metric object has unknown identifier.");
+ }
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPMetricObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPMetricObject.");
+
+ final PCEPMetricObject mObj = (PCEPMetricObject) obj;
+
+ final byte[] retBytes = new byte[SIZE];
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+ flags.set(C_FLAG_OFFSET, mObj.isComputedMetric());
+ flags.set(B_FLAG_OFFSET, mObj.isBound());
+
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+ final AbstractMetric<?> metric = mObj.getMetric();
+ @SuppressWarnings("unchecked")
+ final Class<? extends AbstractMetric<?>> metricClazz = (Class<? extends AbstractMetric<?>>) metric.getClass();
+ retBytes[TYPE_F_OFFSET] = (byte) PCEPMetricsMapping.getInstance().getFromMetricClass(metricClazz);
+
+ System.arraycopy(ByteArray.floatToBytes(mObj.getMetric().getValue()), 0, retBytes, METRIC_VALUE_F_OFFSET, METRIC_VALUE_F_LENGTH);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPNoPathObject
+ * PCEPNoPathObject}
+ */
+public class PCEPNoPathObjectParser implements PCEPObjectParser {
+
+ /*
+ * lengths of fields in bytes
+ */
+ public static final int NI_F_LENGTH = 1; //multi-field
+ public static final int FLAGS_F_LENGTH = 2;
+ public static final int RESERVED_F_LENGTH = 1;
+
+ /*
+ * offsets of field in bytes
+ */
+
+ public static final int NI_F_OFFSET = 0;
+ public static final int FLAGS_F_OFFSET = NI_F_OFFSET + NI_F_LENGTH;
+ public static final int RESERVED_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+ public static final int TLVS_OFFSET = RESERVED_F_OFFSET + RESERVED_F_LENGTH;
+
+ /*
+ * defined flags
+ */
+
+ public static final int C_FLAG_OFFSET = 0;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(bytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+
+ if (bytes.length < TLVS_OFFSET)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+ return new PCEPNoPathObject((short) (bytes[NI_F_OFFSET] & 0xFF), flags.get(C_FLAG_OFFSET), PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET)),
+ ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPNoPathObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPNoPathObject.");
+
+ final PCEPNoPathObject nPObj = (PCEPNoPathObject) obj;
+
+ final byte[] tlvs = PCEPTlvParser.put(nPObj.getTlvs());
+ final byte[] retBytes = new byte[tlvs.length + TLVS_OFFSET];
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+ flags.set(C_FLAG_OFFSET, nPObj.isConstrained());
+ retBytes[NI_F_OFFSET] = ByteArray.shortToBytes(nPObj.getNatureOfIssue())[1];
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+ ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPNonBranchNodeListObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+public class PCEPNonBranchNodeListObjectParser implements PCEPObjectParser {
+
+ @Override
+ public PCEPNonBranchNodeListObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+ final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+ if (subobjects.isEmpty())
+ throw new PCEPDeserializerException("Empty Non-Branch Node List Object.");
+
+ return new PCEPNonBranchNodeListObject(subobjects, processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPNonBranchNodeListObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPNonBranchNodeListObject.");
+
+ assert !(((PCEPNonBranchNodeListObject) obj).getSubobjects().isEmpty()) : "Empty Non-Branch Node List Object.";
+
+ return PCEPEROSubobjectParser.put(((PCEPNonBranchNodeListObject) obj).getSubobjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPNotificationObject
+ * PCEPNotificationObject}
+ */
+public class PCEPNotificationObjectParser implements PCEPObjectParser {
+
+ /*
+ * lengths of fields
+ */
+ public static final int FLAGS_F_LENGTH = 1;
+ public static final int NT_F_LENGTH = 1;
+ public static final int NV_F_LENGTH = 1;
+
+ /*
+ * offsets of fields
+ */
+ public static final int FLAGS_F_OFFSET = 1; //added reserved filed of size 1
+ public static final int NT_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+ public static final int NV_F_OFFSET = NT_F_OFFSET + NT_F_LENGTH;
+ public static final int TLVS_OFFSET = NV_F_OFFSET + NV_F_LENGTH;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (bytes.length < TLVS_OFFSET)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+ return new PCEPNotificationObject((short) (bytes[NT_F_OFFSET] & 0xFF), (short) (bytes[NV_F_OFFSET] & 0xFF), PCEPTlvParser.parse(ByteArray.cutBytes(
+ bytes, TLVS_OFFSET)));
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPNotificationObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPNotificationObject.");
+
+ final PCEPNotificationObject notObj = (PCEPNotificationObject) obj;
+
+ final byte[] tlvs = PCEPTlvParser.put(notObj.getTlvs());
+ final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+
+ ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+ retBytes[NT_F_OFFSET] = ByteArray.shortToBytes(notObj.getType())[1];
+ retBytes[NV_F_OFFSET] = ByteArray.shortToBytes(notObj.getValue())[1];
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPOFCodesMapping;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject
+ * PCEPObjectiveFunctionObject}
+ */
+public class PCEPObjectiveFunctionObjectParser implements PCEPObjectParser {
+
+ /*
+ * lengths of fields
+ */
+ public static final int OF_CODE_F_LENGTH = 2;
+
+ /*
+ * offsets of fields
+ */
+ public static final int OF_CODE_F_OFFSET = 0;
+ public static final int TLVS_OFFSET = OF_CODE_F_OFFSET + OF_CODE_F_LENGTH + 2; // added reserved field of size 2
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (bytes.length < TLVS_OFFSET)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+ try {
+ return new PCEPObjectiveFunctionObject(PCEPOFCodesMapping.getInstance().getFromCodeIdentifier(
+ ByteArray.bytesToShort(ByteArray.subByte(bytes, OF_CODE_F_OFFSET, OF_CODE_F_LENGTH)) & 0xFFFF), PCEPTlvParser.parse(ByteArray.cutBytes(
+ bytes, TLVS_OFFSET)), processed, ignored);
+ } catch (final NoSuchElementException e) {
+ throw new PCEPDeserializerException(e, "Objective function object has unknown identifier.");
+ }
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPObjectiveFunctionObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPObjectiveFunction.");
+
+ final PCEPObjectiveFunctionObject specObj = (PCEPObjectiveFunctionObject) obj;
+
+ final byte[] tlvs = PCEPTlvParser.put(specObj.getTlvs());
+ final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+
+ ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+
+ ByteArray.copyWhole(ByteArray.shortToBytes((short) PCEPOFCodesMapping.getInstance().getFromOFCodesEnum(specObj.getCode())), retBytes, OF_CODE_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPOpenObject PCEPOpenObject}
+ */
+
+public class PCEPOpenObjectParser implements PCEPObjectParser {
+
+ /*
+ * lengths of fields in bytes
+ */
+ public static final int VER_FLAGS_MF_LENGTH = 1; // multi-field
+ public static final int KEEPALIVE_F_LENGTH = 1;
+ public static final int DEAD_TIMER_LENGTH = 1;
+ public static final int SID_F_LENGTH = 1;
+
+ /*
+ * lengths of subfields inside multi-field in bits
+ */
+ public static final int VERSION_SF_LENGTH = 3;
+ public static final int FLAGS_SF_LENGTH = 5;
+
+ /*
+ * offsets of field in bytes
+ */
+
+ public static final int VER_FLAGS_MF_OFFSET = 0;
+ public static final int KEEPALIVE_F_OFFSET = VER_FLAGS_MF_OFFSET + VER_FLAGS_MF_LENGTH;
+ public static final int DEAD_TIMER_OFFSET = KEEPALIVE_F_OFFSET + KEEPALIVE_F_LENGTH;
+ public static final int SID_F_OFFSET = DEAD_TIMER_OFFSET + DEAD_TIMER_LENGTH;
+ public static final int TLVS_OFFSET = SID_F_OFFSET + SID_F_LENGTH;
+
+ /*
+ * offsets of subfields inside multi-field in bits
+ */
+
+ public static final int VERSION_SF_OFFSET = 0;
+ public static final int FLAGS_SF_OFFSET = VERSION_SF_LENGTH + VERSION_SF_OFFSET;
+
+ public static final int PADDED_TO = 4;
+
+ @Override
+ public PCEPOpenObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (bytes.length < TLVS_OFFSET)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+ // parse version
+ final int versionValue = ByteArray.copyBitsRange(bytes[VER_FLAGS_MF_OFFSET], VERSION_SF_OFFSET, VERSION_SF_LENGTH);
+
+ if (versionValue != PCEPOpenObject.PCEP_VERSION)
+ throw new PCEPDocumentedException("Unsupported PCEP version " + versionValue, PCEPErrors.PCEP_VERSION_NOT_SUPPORTED);
+
+ final List<PCEPTlv> tlvs = PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET));
+ boolean ofListOccure = false;
+
+ for (final PCEPTlv tlv : tlvs) {
+ if (tlv instanceof OFListTlv) {
+ if (ofListOccure)
+ throw new PCEPDocumentedException("Invalid or unexpected message", PCEPErrors.NON_OR_INVALID_OPEN_MSG);
+
+ ofListOccure = true;
+ }
+ }
+
+ return new PCEPOpenObject(UnsignedBytes.toInt(bytes[KEEPALIVE_F_OFFSET]), UnsignedBytes.toInt(bytes[DEAD_TIMER_OFFSET]),
+ UnsignedBytes.toInt(bytes[SID_F_OFFSET]), tlvs);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPOpenObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPOpenObject.");
+
+ final PCEPOpenObject openObj = (PCEPOpenObject) obj;
+
+ final byte versionFlagMF = (byte) (PCEPOpenObject.PCEP_VERSION << (Byte.SIZE - VERSION_SF_LENGTH));
+
+ final byte[] tlvs = PCEPTlvParser.put(openObj.getTlvs());
+ final byte[] bytes = new byte[TLVS_OFFSET + tlvs.length + Util.getPadding(TLVS_OFFSET + tlvs.length, PADDED_TO)];
+
+ // serialize version_flags multi-field
+ bytes[VER_FLAGS_MF_OFFSET] = versionFlagMF;
+
+ // serialize keepalive
+ bytes[KEEPALIVE_F_OFFSET] = (byte) openObj.getKeepAliveTimerValue();
+
+ // serialize dead timer
+ bytes[DEAD_TIMER_OFFSET] = (byte) openObj.getDeadTimerValue();
+
+ // serialize SID
+ bytes[SID_F_OFFSET] = (byte) openObj.getSessionId();
+
+ // serialize tlvs
+ ByteArray.copyWhole(tlvs, bytes, TLVS_OFFSET);
+
+ return bytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for IPv4 {@link org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject
+ * PCEPP2MPEndPointsObject}
+ */
+public class PCEPP2MPEndPointsIPv4ObjectParser implements PCEPObjectParser {
+
+ /*
+ * fields lengths and offsets for IPv4 in bytes
+ */
+ public static final int LEAF_TYPE_F_LENGTH = 4;
+ public static final int SRC4_F_LENGTH = 4;
+ public static final int DEST4_F_LENGTH = 4;
+
+ public static final int LEAF_TYPE_F_OFFSET = 0;
+ public static final int SRC4_F_OFFSET = LEAF_TYPE_F_OFFSET + LEAF_TYPE_F_LENGTH;
+ public static final int DEST4_F_OFFSET = SRC4_F_OFFSET + SRC4_F_LENGTH;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory");
+ if (bytes.length < LEAF_TYPE_F_LENGTH + SRC4_F_LENGTH + DEST4_F_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes.");
+
+ final long leafType = UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, LEAF_TYPE_F_OFFSET, LEAF_TYPE_F_LENGTH)));
+
+ return new PCEPP2MPEndPointsObject<IPv4Address>(leafType, new IPv4Address(
+ ByteArray.subByte(bytes, SRC4_F_OFFSET, SRC4_F_LENGTH)), Util.parseAddresses(bytes, DEST4_F_OFFSET, IPv4.FAMILY,
+ DEST4_F_LENGTH), processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPP2MPEndPointsObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPP2MPEndPointsObject.");
+
+ final PCEPP2MPEndPointsObject<?> ePObj = (PCEPP2MPEndPointsObject<?>) obj;
+
+ if (!(ePObj.getSourceAddress() instanceof IPv4Address))
+ throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + ePObj.getSourceAddress().getClass() + ". Needed IPv4Address");
+
+ final byte[] retBytes = new byte[LEAF_TYPE_F_LENGTH + SRC4_F_LENGTH + DEST4_F_LENGTH * ePObj.getDestinationAddresses().size()];
+ ByteArray.copyWhole(ByteArray.intToBytes((int) ePObj.getLeafType()), retBytes, LEAF_TYPE_F_OFFSET);
+ ByteArray.copyWhole(((IPv4Address) ePObj.getSourceAddress()).getAddress(), retBytes, SRC4_F_OFFSET);
+ Util.putAddresses(retBytes, DEST4_F_OFFSET, ePObj.getDestinationAddresses(), DEST4_F_LENGTH);
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for IPv4 {@link org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject
+ * PCEPP2MPEndPointsObject}
+ */
+public class PCEPP2MPEndPointsIPv6ObjectParser implements PCEPObjectParser {
+
+ /*
+ * fields lengths and offsets for IPv4 in bytes
+ */
+ public static final int LEAF_TYPE_F_LENGTH = 4;
+ public static final int SRC6_F_LENGTH = 16;
+ public static final int DEST6_F_LENGTH = 16;
+
+ public static final int LEAF_TYPE_F_OFFSET = 0;
+ public static final int SRC6_F_OFFSET = LEAF_TYPE_F_OFFSET + LEAF_TYPE_F_LENGTH;
+ public static final int DEST6_F_OFFSET = SRC6_F_OFFSET + SRC6_F_LENGTH;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory");
+ if (bytes.length < LEAF_TYPE_F_LENGTH + SRC6_F_LENGTH + DEST6_F_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes.");
+
+ final long leafType = UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, LEAF_TYPE_F_OFFSET, LEAF_TYPE_F_LENGTH)));
+
+ return new PCEPP2MPEndPointsObject<IPv6Address>(leafType, new IPv6Address(
+ ByteArray.subByte(bytes, SRC6_F_OFFSET, SRC6_F_LENGTH)), Util.parseAddresses(bytes, DEST6_F_OFFSET, IPv6.FAMILY,
+ DEST6_F_LENGTH), processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPP2MPEndPointsObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPP2MPEndPointsObject.");
+
+ final PCEPP2MPEndPointsObject<?> ePObj = (PCEPP2MPEndPointsObject<?>) obj;
+
+ if (!(ePObj.getSourceAddress() instanceof IPv6Address))
+ throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + ePObj.getSourceAddress().getClass() + ". Needed IPv6Address");
+
+ final byte[] retBytes = new byte[LEAF_TYPE_F_LENGTH + SRC6_F_LENGTH + DEST6_F_LENGTH * ePObj.getDestinationAddresses().size()];
+ ByteArray.copyWhole(ByteArray.intToBytes((int) ePObj.getLeafType()), retBytes, LEAF_TYPE_F_OFFSET);
+ ByteArray.copyWhole(((IPv6Address) ePObj.getSourceAddress()).getAddress(), retBytes, SRC6_F_OFFSET);
+ Util.putAddresses(retBytes, DEST6_F_OFFSET, ePObj.getDestinationAddresses(), DEST6_F_LENGTH);
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPRROSubobjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject
+ * PCEPReportedRouteObject}
+ */
+public class PCEPReportedRouteObjectParser implements PCEPObjectParser {
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+ final List<ReportedRouteSubobject> subobjects = PCEPRROSubobjectParser.parse(bytes);
+ if (subobjects.isEmpty())
+ throw new PCEPDeserializerException("Empty Reported Route Object.");
+
+ return new PCEPReportedRouteObject(subobjects, processed);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+
+ if (!(obj instanceof PCEPReportedRouteObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPReportedRouteObject.");
+
+ assert !(((PCEPReportedRouteObject) obj).getSubobjects().isEmpty()) : "Empty Reported Route Object.";
+
+ return PCEPRROSubobjectParser.put(((PCEPReportedRouteObject) obj).getSubobjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+ * PCEPRequestParameterObject}
+ */
+
+public class PCEPRequestParameterObjectParser implements PCEPObjectParser {
+
+ /*
+ * lengths of fields in bytes
+ */
+ public static final int FLAGS_PRI_MF_LENGTH = 4; //multi-field
+ public static final int RID_F_LENGTH = 4;
+
+ /*
+ * lengths of subfields inside multi-field in bits
+ */
+ public static final int FLAGS_SF_LENGTH = 29;
+ public static final int PRI_SF_LENGTH = 3;
+
+ /*
+ * offsets of field in bytes
+ */
+
+ public static final int FLAGS_PRI_MF_OFFSET = 0;
+ public static final int RID_F_OFFSET = FLAGS_PRI_MF_OFFSET + FLAGS_PRI_MF_LENGTH;
+ public static final int TLVS_OFFSET = RID_F_OFFSET + RID_F_LENGTH;
+
+ /*
+ * offsets of subfields inside multi-field in bits
+ */
+
+ public static final int FLAGS_SF_OFFSET = 0;
+ public static final int PRI_SF_OFFSET = FLAGS_SF_OFFSET + FLAGS_SF_LENGTH;
+
+ /*
+ * flags offsets inside flags sub-field in bits
+ */
+
+ private static final int O_FLAG_OFFSET = 26;
+ private static final int B_FLAG_OFFSET = 27;
+ private static final int R_FLAG_OFFSET = 28;
+
+ /*
+ * GCO extension flags offsets inside flags sub-field in bits
+ */
+ private static final int M_FLAG_OFFSET = 21;
+ private static final int D_FLAG_OFFSET = 22;
+
+ /*
+ * OF extension flags offsets inside flags sub.field in bits
+ */
+
+ private static int S_FLAG_OFFSET = 24; //Supply OF on response
+
+ /*
+ * RFC6006 flags
+ */
+ private static int F_FLAG_OFFSET = 18;
+
+ private static int N_FLAG_OFFSET = 19;
+
+ private static int E_FLAG_OFFSET = 20;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (bytes.length < TLVS_OFFSET)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
+
+ final BitSet flags = ByteArray.bytesToBitSet(Arrays.copyOfRange(bytes, FLAGS_PRI_MF_OFFSET, FLAGS_PRI_MF_OFFSET + FLAGS_PRI_MF_LENGTH));
+ short priority = 0;
+ priority |= flags.get(PRI_SF_OFFSET + 2) ? 1 : 0;
+ priority |= (flags.get(PRI_SF_OFFSET + 1) ? 1 : 0) << 1;
+ priority |= (flags.get(PRI_SF_OFFSET) ? 1 : 0) << 2;
+
+ return new PCEPRequestParameterObject(flags.get(O_FLAG_OFFSET), flags.get(B_FLAG_OFFSET), flags.get(R_FLAG_OFFSET), flags.get(M_FLAG_OFFSET),
+ flags.get(D_FLAG_OFFSET), flags.get(S_FLAG_OFFSET), flags.get(F_FLAG_OFFSET), flags.get(N_FLAG_OFFSET), flags.get(E_FLAG_OFFSET), priority,
+ ByteArray.bytesToLong(Arrays.copyOfRange(bytes, RID_F_OFFSET, RID_F_OFFSET + RID_F_LENGTH)), PCEPTlvParser.parse(ByteArray.cutBytes(bytes,
+ TLVS_OFFSET)), processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPRequestParameterObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPRequestParameterObject.");
+
+ final PCEPRequestParameterObject rPObj = (PCEPRequestParameterObject) obj;
+
+ final BitSet flags_priority = new BitSet(FLAGS_PRI_MF_LENGTH * Byte.SIZE);
+
+ flags_priority.set(R_FLAG_OFFSET, rPObj.isReoptimized());
+ flags_priority.set(B_FLAG_OFFSET, rPObj.isBidirectional());
+ flags_priority.set(O_FLAG_OFFSET, rPObj.isLoose());
+ flags_priority.set(M_FLAG_OFFSET, rPObj.isMakeBeforeBreak());
+ flags_priority.set(D_FLAG_OFFSET, rPObj.isReportRequestOrder());
+ flags_priority.set(S_FLAG_OFFSET, rPObj.isSuplyOFOnResponse());
+ flags_priority.set(F_FLAG_OFFSET, rPObj.isFragmentation());
+ flags_priority.set(N_FLAG_OFFSET, rPObj.isP2mp());
+ flags_priority.set(E_FLAG_OFFSET, rPObj.isEroCompression());
+
+ flags_priority.set(PRI_SF_OFFSET, (rPObj.getPriority() & 1 << 2) != 0);
+ flags_priority.set(PRI_SF_OFFSET + 1, (rPObj.getPriority() & 1 << 1) != 0);
+ flags_priority.set(PRI_SF_OFFSET + 2, (rPObj.getPriority() & 1) != 0);
+
+ final byte[] tlvs = PCEPTlvParser.put(rPObj.getTlvs());
+ final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length];
+ ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags_priority, FLAGS_PRI_MF_LENGTH), retBytes, FLAGS_PRI_MF_OFFSET);
+ ByteArray.copyWhole(ByteArray.subByte(ByteArray.longToBytes(rPObj.getRequestID()), (Long.SIZE / Byte.SIZE) - RID_F_LENGTH, RID_F_LENGTH), retBytes,
+ RID_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject
+ * PCEPRequestedPathBandwidthObject}
+ */
+public class PCEPRequestedPathBandwidthObjectParser implements PCEPObjectParser {
+
+ private static final int BANDWIDTH_F_LENGTH = 4;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (bytes.length != BANDWIDTH_F_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: " + BANDWIDTH_F_LENGTH + ".");
+
+ return new PCEPRequestedPathBandwidthObject(new Bandwidth(ByteArray.bytesToFloat(bytes)), processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPRequestedPathBandwidthObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPRequestedPathBandwidthObject.");
+
+ return ByteArray.floatToBytes((float) ((PCEPRequestedPathBandwidthObject) obj).getBandwidth().getBytesPerSecond());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPEROSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryExplicitRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+public class PCEPSecondaryExplicitRouteObjectParser implements PCEPObjectParser {
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+ final List<ExplicitRouteSubobject> subobjects = PCEPEROSubobjectParser.parse(bytes);
+ if (subobjects.isEmpty())
+ throw new PCEPDeserializerException("Empty Secondary Explicit Route Object.");
+
+ return new PCEPSecondaryExplicitRouteObject(subobjects, processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPSecondaryExplicitRouteObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPSecondaryExplicitRouteObject.");
+
+ assert !(((PCEPSecondaryExplicitRouteObject) obj).getSubobjects().isEmpty()) : "Empty Secondary Explicit Route Object.";
+
+ return PCEPEROSubobjectParser.put(((PCEPSecondaryExplicitRouteObject) obj).getSubobjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.PCEPRROSubobjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryRecordRouteObject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+
+public class PCEPSecondaryRecordRouteObjectParser implements PCEPObjectParser {
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Byte array is mandatory. Can't be null or empty.");
+
+ final List<ReportedRouteSubobject> subobjects = PCEPRROSubobjectParser.parse(bytes);
+ if (subobjects.isEmpty())
+ throw new PCEPDeserializerException("Empty Secondary Recorded Route Object.");
+
+ return new PCEPSecondaryRecordRouteObject(subobjects, processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+
+ if (!(obj instanceof PCEPSecondaryRecordRouteObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPSecondaryRecordRouteObject.");
+
+ assert !(((PCEPSecondaryRecordRouteObject) obj).getSubobjects().isEmpty()) : "Empty Secondary Record Route Object.";
+
+ return PCEPRROSubobjectParser.put(((PCEPSecondaryRecordRouteObject) obj).getSubobjects());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPSvecObject PCEPSvecObject}
+ */
+public class PCEPSvecObjectParser implements PCEPObjectParser {
+
+ /*
+ * field lengths in bytes
+ */
+ public static final int FLAGS_F_LENGTH = 3;
+ public static final int REQ_LIST_ITEM_LENGTH = 4;
+
+ /*
+ * fields offsets in bytes
+ */
+ public static final int FLAGS_F_OFFSET = 1; // aded reserved field of size 1
+ public static final int REQ_ID_LIST_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+
+ /*
+ * flags offsets inside flags field in bits
+ */
+ public static final int S_FLAG_OFFSET = 21;
+ public static final int N_FLAG_OFFSET = 22;
+ public static final int L_FLAG_OFFSET = 23;
+
+ public static final int P_FLAG_OFFSET = 19;
+ public static final int D_FLAG_OFFSET = 20;
+
+ /*
+ * min size in bytes
+ */
+
+ public static final int MIN_SIZE = FLAGS_F_LENGTH + FLAGS_F_OFFSET;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException {
+ if (bytes == null || bytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (bytes.length < MIN_SIZE)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + MIN_SIZE + ".");
+
+ final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(bytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+ final int numOfRIDs = (bytes.length - FLAGS_F_LENGTH - FLAGS_F_OFFSET) / REQ_LIST_ITEM_LENGTH;
+ final List<Long> requestIDs = new ArrayList<Long>(numOfRIDs);
+
+ for (int i = REQ_ID_LIST_OFFSET; i < bytes.length; i += REQ_LIST_ITEM_LENGTH) {
+ requestIDs.add(UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(bytes, i, REQ_LIST_ITEM_LENGTH))));
+ }
+
+ if (requestIDs.isEmpty())
+ throw new PCEPDeserializerException("Empty Svec Object - no request ids.");
+
+ return new PCEPSvecObject(flags.get(L_FLAG_OFFSET), flags.get(N_FLAG_OFFSET), flags.get(S_FLAG_OFFSET), flags.get(P_FLAG_OFFSET),
+ flags.get(D_FLAG_OFFSET), requestIDs, processed);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPSvecObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPSvecObject.");
+
+ final PCEPSvecObject svecObj = (PCEPSvecObject) obj;
+ final byte[] retBytes = new byte[svecObj.getRequestIDs().size() * REQ_LIST_ITEM_LENGTH + REQ_ID_LIST_OFFSET];
+ final List<Long> requestIDs = svecObj.getRequestIDs();
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+ flags.set(L_FLAG_OFFSET, svecObj.isLinkDiversed());
+ flags.set(N_FLAG_OFFSET, svecObj.isNodeDiversed());
+ flags.set(S_FLAG_OFFSET, svecObj.isSrlgDiversed());
+ flags.set(P_FLAG_OFFSET, svecObj.isParitialPathDiversed());
+ flags.set(D_FLAG_OFFSET, svecObj.isLinkDirectionDiversed());
+
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+ for (int i = 0; i < requestIDs.size(); i++) {
+ System.arraycopy(ByteArray.longToBytes(requestIDs.get(i)), 4, retBytes, REQ_LIST_ITEM_LENGTH * i + REQ_ID_LIST_OFFSET, REQ_LIST_ITEM_LENGTH);
+ }
+
+ assert !(requestIDs.isEmpty()) : "Empty Svec Object - no request ids.";
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPUnreachedDestinationObject;
+
+public class PCEPUnreachedIPv4DestinationObjectParser implements PCEPObjectParser {
+
+ /*
+ * fields lengths and offsets for IPv4 in bytes
+ */
+ public static final int DEST4_F_LENGTH = 4;
+
+ public static final int DEST4_F_OFFSET = 0;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory");
+
+ return new PCEPUnreachedDestinationObject<IPv4Address>(Util.parseAddresses(bytes, DEST4_F_OFFSET, IPv4.FAMILY, DEST4_F_LENGTH), processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPUnreachedDestinationObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPUnreachedDestinationObject.");
+
+ final PCEPUnreachedDestinationObject<?> uDObj = (PCEPUnreachedDestinationObject<?>) obj;
+
+ if (uDObj.getUnreachedDestinations().isEmpty())
+ return new byte[0];
+
+ if (!(uDObj.getUnreachedDestinations().get(0) instanceof IPv4Address))
+ throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + uDObj.getUnreachedDestinations().get(0).getClass()
+ + ". Needed IPv4Address");
+
+ final byte[] retBytes = new byte[DEST4_F_LENGTH * uDObj.getUnreachedDestinations().size()];
+ Util.putAddresses(retBytes, DEST4_F_OFFSET, uDObj.getUnreachedDestinations(), DEST4_F_LENGTH);
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.concepts.IPv6;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
+import org.opendaylight.protocol.pcep.impl.Util;
+import org.opendaylight.protocol.pcep.object.PCEPUnreachedDestinationObject;
+
+public class PCEPUnreachedIPv6DestinationObjectParser implements PCEPObjectParser {
+
+ /*
+ * fields lengths and offsets for IPv6 in bytes
+ */
+ public static final int DEST6_F_LENGTH = 16;
+
+ public static final int DEST6_F_OFFSET = 0;
+
+ @Override
+ public PCEPObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
+ if (bytes == null)
+ throw new IllegalArgumentException("Array of bytes is mandatory");
+
+ return new PCEPUnreachedDestinationObject<IPv6Address>(Util.parseAddresses(bytes, DEST6_F_OFFSET, IPv6.FAMILY, DEST6_F_LENGTH), processed, ignored);
+ }
+
+ @Override
+ public byte[] put(PCEPObject obj) {
+ if (!(obj instanceof PCEPUnreachedDestinationObject))
+ throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPUnreachedDestinationObject.");
+
+ final PCEPUnreachedDestinationObject<?> uDObj = (PCEPUnreachedDestinationObject<?>) obj;
+
+ if (uDObj.getUnreachedDestinations().isEmpty())
+ return new byte[0];
+
+ if (!(uDObj.getUnreachedDestinations().get(0) instanceof IPv6Address))
+ throw new IllegalArgumentException("Wrong instance of NetworkAddress. Passed " + uDObj.getUnreachedDestinations().get(0).getClass()
+ + ". Needed IPv6Address");
+
+ final byte[] retBytes = new byte[DEST6_F_LENGTH * uDObj.getUnreachedDestinations().size()];
+ Util.putAddresses(retBytes, DEST6_F_OFFSET, uDObj.getUnreachedDestinations(), DEST6_F_LENGTH);
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.object;
+
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+
+public class UnknownObject extends PCEPObject {
+
+ private final PCEPErrors error;
+
+ public UnknownObject(boolean processed, boolean ignored, PCEPErrors error) {
+ super(processed, ignored);
+
+ this.error = error;
+ }
+
+ public PCEPErrors getError() {
+ return this.error;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject
+ * EROAsNumberSubobject}
+ */
+
+public class EROAsNumberSubobjectParser {
+ public static final int AS_NUMBER_LENGTH = 2;
+
+ public static final int AS_NUMBER_OFFSET = 0;
+
+ public static final int CONTENT_LENGTH = AS_NUMBER_LENGTH + AS_NUMBER_OFFSET;
+
+ public static EROAsNumberSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ return new EROAsNumberSubobject(new ASNumber((ByteArray.bytesToShort(soContentsBytes) & 0xFFFF)), loose);
+ }
+
+ public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof EROAsNumberSubobject))
+ throw new IllegalArgumentException("Unknown ExplicitRouteSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed EROAsNumberSubobject.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ System.arraycopy(ByteArray.longToBytes(((EROAsNumberSubobject) objToSerialize).getASNumber().getAsn()), Long.SIZE / Byte.SIZE - AS_NUMBER_LENGTH,
+ retBytes, AS_NUMBER_OFFSET, AS_NUMBER_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.PCEPXROSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.EROExplicitExclusionRouteSubobject;
+
+public class EROExplicitExclusionRouteSubobjectParser {
+ public static EROExplicitExclusionRouteSubobject parse(byte[] cutBytes, boolean loose) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ return new EROExplicitExclusionRouteSubobject(PCEPXROSubobjectParser.parse(cutBytes));
+ }
+
+ public static byte[] put(EROExplicitExclusionRouteSubobject objToSerialize) {
+ return PCEPXROSubobjectParser.put(objToSerialize.getXroSubobjets());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+
+public class EROGeneralizedLabelSubobjectParser implements EROLabelParser {
+
+ @Override
+ public EROLabelSubobject parse(byte[] cutBytes, boolean upStream, boolean loose) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ return new EROGeneralizedLabelSubobject(cutBytes, upStream, loose);
+ }
+
+ @Override
+ public byte[] put(EROLabelSubobject objToSerialize) {
+ if (!(objToSerialize instanceof EROGeneralizedLabelSubobject))
+ throw new IllegalArgumentException("Unknown EROLabelSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed EROGeneralizedLabelSubobject.");
+ final byte[] retBytes = ((EROGeneralizedLabelSubobject) objToSerialize).getLabel();
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject
+ * EROIPPrefixSubobject<IPv4Prefix>}
+ */
+public class EROIPv4PrefixSubobjectParser {
+ public static final int IP_F_LENGTH = 4;
+ public static final int PREFIX_F_LENGTH = 1;
+
+ public static final int IP_F_OFFSET = 0;
+ public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = PREFIX_F_OFFSET + PREFIX_F_LENGTH + 1; //added reserved field of size 1 byte
+
+ public static EROIPPrefixSubobject<IPv4Prefix> parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ final IPv4Address address = new IPv4Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+ final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+ return new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(address, length), loose);
+ }
+
+ public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof EROIPPrefixSubobject))
+ throw new IllegalArgumentException("Unknown ExplicitRouteSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed EROIPPrefixSubobject.");
+
+ final EROIPPrefixSubobject<?> specObj = (EROIPPrefixSubobject<?>) objToSerialize;
+ final Prefix<?> prefix = specObj.getPrefix();
+
+ if (!(prefix instanceof IPv4Prefix))
+ throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv4Prefix.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+ ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+ retBytes[PREFIX_F_OFFSET] = ByteArray.intToBytes(prefix.getLength())[Integer.SIZE / Byte.SIZE - 1];
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject
+ * EROIPPrefixSubobject<IPv6Prefix>}
+ */
+public class EROIPv6PrefixSubobjectParser {
+ public static final int IP_F_LENGTH = 16;
+ public static final int PREFIX_F_LENGTH = 1;
+
+ public static final int IP_F_OFFSET = 0;
+ public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = PREFIX_F_OFFSET + PREFIX_F_LENGTH + 1; // added reserved field of size 1 byte
+
+ public static EROIPPrefixSubobject<IPv6Prefix> parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ final IPv6Address address = new IPv6Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+ final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+ return new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(address, length), loose);
+ }
+
+ public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof EROIPPrefixSubobject))
+ throw new IllegalArgumentException("Unknown ExplicitRouteSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed EROIPPrefixSubobject.");
+
+ final EROIPPrefixSubobject<?> specObj = (EROIPPrefixSubobject<?>) objToSerialize;
+ final Prefix<?> prefix = specObj.getPrefix();
+
+ if (!(prefix instanceof IPv6Prefix))
+ throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv6Prefix.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+ retBytes[PREFIX_F_OFFSET] = ByteArray.intToBytes(prefix.getLength())[Integer.SIZE / Byte.SIZE - 1];
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+
+public interface EROLabelParser {
+
+ EROLabelSubobject parse(byte[] cutBytes, boolean upStream, boolean loose) throws PCEPDeserializerException;
+
+ byte[] put(EROLabelSubobject objToSerialize);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.Util.BiParsersMap;
+import org.opendaylight.protocol.pcep.subobject.EROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROType1LabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROLabelSubobjectParser {
+
+ public static final int RES_F_LENGTH = 1;
+
+ public static final int C_TYPE_F_LENGTH = 1;
+
+ public static final int RES_F_OFFSET = 0;
+
+ public static final int C_TYPE_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+ public static final int HEADER_LENGTH = C_TYPE_F_OFFSET + C_TYPE_F_LENGTH;
+
+ public static final int U_FLAG_OFFSET = 0;
+
+ private static class MapOfParsers extends BiParsersMap<Class<? extends EROLabelSubobject>, Integer, EROLabelParser> {
+ private final static MapOfParsers instance = new MapOfParsers();
+
+ private MapOfParsers() {
+ this.fillInMap();
+ }
+
+ private void fillInMap() {
+ this.put(EROType1LabelSubobject.class, 1, new EROType1LabelSubobjectParser());
+ this.put(EROGeneralizedLabelSubobject.class, 2, new EROGeneralizedLabelSubobjectParser());
+ this.put(EROWavebandSwitchingLabelSubobject.class, 3, new EROWavebandSwitchingLabelSubobjectParser());
+ }
+
+ public static MapOfParsers getInstance() {
+ return instance;
+ }
+ }
+
+ public static EROLabelSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length < HEADER_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + HEADER_LENGTH + ".");
+
+ final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(soContentsBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+ final int c_type = soContentsBytes[C_TYPE_F_OFFSET] & 0xFF;
+
+ final EROLabelParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+ if (parser == null) {
+ throw new PCEPDeserializerException("Unknown C-TYPE for ero label subobject. Passed: " + c_type);
+ }
+
+ return parser.parse(ByteArray.cutBytes(soContentsBytes, HEADER_LENGTH), reserved.get(U_FLAG_OFFSET), loose);
+ }
+
+ public static byte[] put(EROLabelSubobject objToSerialize) {
+ final Integer c_type = MapOfParsers.getInstance().getKeyValueFromKey(objToSerialize.getClass());
+ final EROLabelParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+ if (c_type == null || parser == null)
+ throw new IllegalArgumentException("Unknown EROLabelSubobject instance. Passed " + objToSerialize.getClass());
+
+ final byte[] labelbytes = parser.put(objToSerialize);
+
+ final byte[] retBytes = new byte[labelbytes.length + HEADER_LENGTH];
+
+ System.arraycopy(labelbytes, 0, retBytes, HEADER_LENGTH, labelbytes.length);
+
+ final BitSet reserved = new BitSet();
+ reserved.set(U_FLAG_OFFSET, objToSerialize.isUpStream());
+ System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+ retBytes[C_TYPE_F_OFFSET] = (byte) c_type.intValue();
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROPathKeyWith128PCEIDSubobjectParser {
+
+ public static final int PK_F_LENGTH = 2;
+ public static final int PCE_ID_F_LENGTH = 16;
+
+ public static final int PK_F_OFFSET = 0;
+ public static final int PCE_ID_F_OFFSET = PK_F_OFFSET + PK_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = PCE_ID_F_OFFSET + PCE_ID_F_LENGTH;
+
+ public static EROPathKeyWith128PCEIDSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+ final int pathKey = ByteArray.bytesToShort(Arrays.copyOfRange(soContentsBytes, PK_F_OFFSET, PCE_ID_F_OFFSET)) & 0xFFFF;
+
+ final byte[] pceId = Arrays.copyOfRange(soContentsBytes, PCE_ID_F_OFFSET, CONTENT_LENGTH);
+
+ return new EROPathKeyWith128PCEIDSubobject(pathKey, pceId, loose);
+ }
+
+ public static byte[] put(EROPathKeyWith128PCEIDSubobject objToSerialize) {
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ System.arraycopy(ByteArray.shortToBytes((short) objToSerialize.getPathKey()), 0, retBytes, PK_F_OFFSET, PK_F_LENGTH);
+
+ if (objToSerialize.getPceId().length != PCE_ID_F_LENGTH)
+ throw new IllegalArgumentException("Wrong length of pce id. Passed: " + objToSerialize.getPceId().length + ". Expected: =" + PCE_ID_F_LENGTH);
+ System.arraycopy(objToSerialize.getPceId(), 0, retBytes, PCE_ID_F_OFFSET, PCE_ID_F_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROPathKeyWith32PCEIDSubobjectParser {
+
+ public static final int PK_F_LENGTH = 2;
+ public static final int PCE_ID_F_LENGTH = 4;
+
+ public static final int PK_F_OFFSET = 0;
+ public static final int PCE_ID_F_OFFSET = PK_F_OFFSET + PK_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = PCE_ID_F_OFFSET + PCE_ID_F_LENGTH;
+
+ public static EROPathKeyWith32PCEIDSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+ final int pathKey = ByteArray.bytesToShort(Arrays.copyOfRange(soContentsBytes, PK_F_OFFSET, PCE_ID_F_OFFSET)) & 0xFFFF;
+
+ final byte[] pceId = Arrays.copyOfRange(soContentsBytes, PCE_ID_F_OFFSET, CONTENT_LENGTH);
+
+ return new EROPathKeyWith32PCEIDSubobject(pathKey, pceId, loose);
+ }
+
+ public static byte[] put(EROPathKeyWith32PCEIDSubobject objToSerialize) {
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ System.arraycopy(ByteArray.shortToBytes((short) objToSerialize.getPathKey()), 0, retBytes, PK_F_OFFSET, PK_F_LENGTH);
+
+ if (objToSerialize.getPceId().length != PCE_ID_F_LENGTH)
+ throw new IllegalArgumentException("Wrong length of pce id. Passed: " + objToSerialize.getPceId().length + ". Expected: =" + PCE_ID_F_LENGTH);
+ System.arraycopy(objToSerialize.getPceId(), 0, retBytes, PCE_ID_F_OFFSET, PCE_ID_F_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+
+public interface EROProtectionParser {
+
+ EROProtectionSubobject parse(byte[] cutBytes, boolean loose) throws PCEPDeserializerException;
+
+ byte[] put(EROProtectionSubobject objToSerialize);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.Util.BiParsersMap;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType1Subobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType2Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROProtectionSubobjectParser {
+
+ public static final int RES_F_LENGTH = 1;
+
+ public static final int C_TYPE_F_LENGTH = 1;
+
+ public static final int RES_F_OFFSET = 0;
+
+ public static final int C_TYPE_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+ public static final int HEADER_LENGTH = C_TYPE_F_OFFSET + C_TYPE_F_LENGTH;
+
+ public static final int U_FLAG_OFFSET = 0;
+
+ private static class MapOfParsers extends BiParsersMap<Class<? extends EROProtectionSubobject>, Integer, EROProtectionParser> {
+ private final static MapOfParsers instance = new MapOfParsers();
+
+ private MapOfParsers() {
+ this.fillInMap();
+ }
+
+ private void fillInMap() {
+ this.put(EROProtectionType1Subobject.class, 1, new EROProtectionType1SubobjectParser());
+ this.put(EROProtectionType2Subobject.class, 2, new EROProtectionType2SubobjectParser());
+ }
+
+ public static MapOfParsers getInstance() {
+ return instance;
+ }
+ }
+
+ public static EROProtectionSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length < HEADER_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + HEADER_LENGTH + ".");
+
+ final int c_type = soContentsBytes[C_TYPE_F_OFFSET] & 0xFF;
+
+ final EROProtectionParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+ if (parser == null) {
+ throw new PCEPDeserializerException("Unknown C-TYPE for ero protection subobject. Passed: " + c_type);
+ }
+
+ return parser.parse(ByteArray.cutBytes(soContentsBytes, HEADER_LENGTH), loose);
+ }
+
+ public static byte[] put(EROProtectionSubobject objToSerialize) {
+ final Integer c_type = MapOfParsers.getInstance().getKeyValueFromKey(objToSerialize.getClass());
+ final EROProtectionParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+ if (c_type == null || parser == null)
+ throw new IllegalArgumentException("Unknown EROProtectionSubobject instance. Passed " + objToSerialize.getClass());
+
+ final byte[] protBytes = parser.put(objToSerialize);
+
+ final byte[] retBytes = new byte[protBytes.length + HEADER_LENGTH];
+
+ System.arraycopy(protBytes, 0, retBytes, HEADER_LENGTH, protBytes.length);
+
+ retBytes[C_TYPE_F_OFFSET] = (byte) c_type.intValue();
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType1Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROProtectionType1SubobjectParser implements EROProtectionParser {
+
+ public static final int RES_F_LENGTH = 4;
+
+ public static final int RES_F_OFFSET = 0;
+
+ public static final int CONTENT_LENGTH = RES_F_OFFSET + RES_F_LENGTH;
+
+ /*
+ * offsets of flags inside reserved field
+ */
+ public static final int S_FLAG_OFFSET = 0;
+
+ @Override
+ public EROProtectionSubobject parse(byte[] cutBytes, boolean loose) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (cutBytes.length < CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+ final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(cutBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+ final byte linkFlags = (byte) (cutBytes[3] & 0x3F);
+
+ return new EROProtectionType1Subobject(reserved.get(S_FLAG_OFFSET), linkFlags, loose);
+ }
+
+ @Override
+ public byte[] put(EROProtectionSubobject objToSerialize) {
+ if (!(objToSerialize instanceof EROProtectionType1Subobject))
+ throw new IllegalArgumentException("Unknown EROProtectionSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed EROProtectionType1Subobject.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ final BitSet reserved = new BitSet();
+ reserved.set(S_FLAG_OFFSET, ((EROProtectionType1Subobject) objToSerialize).isSecondary());
+ System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+ retBytes[3] |= ((EROProtectionType1Subobject) objToSerialize).getLinkFlags() & 0x3F;
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType2Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class EROProtectionType2SubobjectParser implements EROProtectionParser {
+
+ public static final int RES_F_LENGTH = 8;
+
+ public static final int RES_F_OFFSET = 0;
+
+ public static final int CONTENT_LENGTH = RES_F_OFFSET + RES_F_LENGTH;
+
+ /*
+ * offsets of flags inside reserved field
+ */
+ public static final int S_FLAG_OFFSET = 0;
+ public static final int P_FLAG_OFFSET = 1;
+ public static final int N_FLAG_OFFSET = 2;
+ public static final int O_FLAG_OFFSET = 3;
+
+ public static final int I_FLAG_OFFSET = 32;
+ public static final int R_FLAG_OFFSET = 33;
+
+ @Override
+ public EROProtectionSubobject parse(byte[] cutBytes, boolean loose) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (cutBytes.length < CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+ final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(cutBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+ final byte linkFlags = (byte) (cutBytes[3] & 0x3F);
+ final byte lspFlags = (byte) (cutBytes[1] & 0x3F);
+ final byte segFlags = (byte) (cutBytes[5] & 0x3F);
+
+ return new EROProtectionType2Subobject(reserved.get(S_FLAG_OFFSET), reserved.get(P_FLAG_OFFSET), reserved.get(N_FLAG_OFFSET),
+ reserved.get(N_FLAG_OFFSET), lspFlags, linkFlags, reserved.get(I_FLAG_OFFSET), reserved.get(R_FLAG_OFFSET), segFlags, loose);
+ }
+
+ @Override
+ public byte[] put(EROProtectionSubobject objToSerialize) {
+ if (!(objToSerialize instanceof EROProtectionType2Subobject))
+ throw new IllegalArgumentException("Unknown EROProtectionSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed EROProtectionType2Subobject.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ final BitSet reserved = new BitSet();
+ reserved.set(S_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isSecondaryLsp());
+ reserved.set(P_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isProtectionLsp());
+ reserved.set(N_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isNotification());
+ reserved.set(O_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isOperational());
+ reserved.set(I_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isInPlace());
+ reserved.set(R_FLAG_OFFSET, ((EROProtectionType2Subobject) objToSerialize).isRequired());
+ System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+ retBytes[3] |= ((EROProtectionType2Subobject) objToSerialize).getLinkFlags() & 0x3F;
+ retBytes[1] |= ((EROProtectionType2Subobject) objToSerialize).getLspFlags() & 0x3F;
+ retBytes[5] |= ((EROProtectionType2Subobject) objToSerialize).getSegFlags() & 0x3F;
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROType1LabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+public class EROType1LabelSubobjectParser implements EROLabelParser {
+
+ public static final int LABEL_LENGTH = 4;
+
+ @Override
+ public EROLabelSubobject parse(byte[] cutBytes, boolean upStream, boolean loose) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (cutBytes.length != LABEL_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: " + LABEL_LENGTH + ".");
+
+ return new EROType1LabelSubobject(UnsignedInts.toLong(ByteArray.bytesToInt(cutBytes)), upStream, loose);
+ }
+
+ @Override
+ public byte[] put(EROLabelSubobject objToSerialize) {
+ if (!(objToSerialize instanceof EROType1LabelSubobject))
+ throw new IllegalArgumentException("Unknown EROLabelSubobject instance. Passed " + objToSerialize.getClass() + ". Needed EROType1LabelSubobject.");
+
+ return ByteArray.intToBytes((int) ((EROType1LabelSubobject) objToSerialize).getLabel());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for
+ * {@link org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject
+ * EROUnnumberedInterfaceSubobject}
+ */
+public class EROUnnumberedInterfaceSubobjectParser {
+ public static final int ROUTER_ID_NUMBER_LENGTH = 4;
+ public static final int INTERFACE_ID_NUMBER_LENGTH = 4;
+
+ public static final int ROUTER_ID_NUMBER_OFFSET = 2; // added reserved field of size 2
+ public static final int INTERFACE_ID_NUMBER_OFFSET = ROUTER_ID_NUMBER_OFFSET + ROUTER_ID_NUMBER_LENGTH;
+
+ public static final int CONTENT_LENGTH = INTERFACE_ID_NUMBER_OFFSET + INTERFACE_ID_NUMBER_LENGTH;
+
+ public static EROUnnumberedInterfaceSubobject parse(byte[] soContentsBytes, boolean loose) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ return new EROUnnumberedInterfaceSubobject(new IPv4Address(ByteArray.subByte(soContentsBytes, ROUTER_ID_NUMBER_OFFSET, ROUTER_ID_NUMBER_LENGTH)), new UnnumberedInterfaceIdentifier(
+ UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(soContentsBytes, INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH)))), loose);
+ }
+
+ public static byte[] put(ExplicitRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof EROUnnumberedInterfaceSubobject))
+ throw new IllegalArgumentException("Unknown ExplicitRouteSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed EROUnnumberedInterfaceSubobject.");
+
+ byte[] retBytes;
+ retBytes = new byte[CONTENT_LENGTH];
+ final EROUnnumberedInterfaceSubobject specObj = (EROUnnumberedInterfaceSubobject) objToSerialize;
+
+ ByteArray.copyWhole(specObj.getRouterID().getAddress(), retBytes, ROUTER_ID_NUMBER_OFFSET);
+ System.arraycopy(ByteArray.longToBytes(specObj.getInterfaceID().getInterfaceId()), Long.SIZE / Byte.SIZE - INTERFACE_ID_NUMBER_LENGTH, retBytes,
+ INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+public class EROWavebandSwitchingLabelSubobjectParser implements EROLabelParser {
+
+ public static int WAVEB_F_LENGTH = 4;
+ public static int START_F_LENGTH = 4;
+ public static int END_F_LENGTH = 4;
+
+ public static int WAVEB_F_OFFSET = 0;
+ public static int START_F_OFFSET = WAVEB_F_OFFSET + WAVEB_F_LENGTH;
+ public static int END_F_OFFSET = START_F_OFFSET + START_F_LENGTH;
+
+ public static int CONTENT_LENGTH = END_F_OFFSET + END_F_LENGTH;
+
+ @Override
+ public EROLabelSubobject parse(byte[] cutBytes, boolean upStream, boolean loose) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (cutBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ return new EROWavebandSwitchingLabelSubobject(UnsignedInts.toLong(ByteArray.bytesToInt(Arrays.copyOfRange(cutBytes, WAVEB_F_OFFSET, START_F_OFFSET))),
+ UnsignedInts.toLong(ByteArray.bytesToInt(Arrays.copyOfRange(cutBytes, START_F_OFFSET, END_F_OFFSET))), UnsignedInts.toLong(ByteArray
+ .bytesToInt(Arrays.copyOfRange(cutBytes, END_F_OFFSET, CONTENT_LENGTH))), upStream, loose);
+ }
+
+ @Override
+ public byte[] put(EROLabelSubobject objToSerialize) {
+ if (!(objToSerialize instanceof EROWavebandSwitchingLabelSubobject))
+ throw new IllegalArgumentException("Unknown EROLabelSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed EROWavebandSwitchingLabelSubobject.");
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ final EROWavebandSwitchingLabelSubobject obj = (EROWavebandSwitchingLabelSubobject) objToSerialize;
+
+ System.arraycopy(ByteArray.intToBytes((int) obj.getWavebandId()), 0, retBytes, WAVEB_F_OFFSET, WAVEB_F_LENGTH);
+ System.arraycopy(ByteArray.intToBytes((int) obj.getStartLabel()), 0, retBytes, START_F_OFFSET, START_F_LENGTH);
+ System.arraycopy(ByteArray.intToBytes((int) obj.getEndLabel()), 0, retBytes, END_F_OFFSET, END_F_LENGTH);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.RROAsNumberSubobject
+ * RROAsNumberSubobject}
+ */
+
+public class RROAsNumberSubobjectParser {
+ public static final int AS_NUMBER_LENGTH = 2;
+
+ public static final int AS_NUMBER_OFFSET = 0;
+
+ public static final int CONTENT_LENGTH = AS_NUMBER_LENGTH + AS_NUMBER_OFFSET;
+
+ public static RROAsNumberSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ return new RROAsNumberSubobject(new ASNumber((ByteArray.bytesToShort(soContentsBytes) & 0xFFFF)));
+ }
+
+ public static byte[] put(ReportedRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof RROAsNumberSubobject))
+ throw new IllegalArgumentException("Unknown ReportedRouteSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed RROAsNumberSubobject.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ System.arraycopy(ByteArray.longToBytes(((RROAsNumberSubobject) objToSerialize).getASNumber().getAsn()), Long.SIZE / Byte.SIZE - AS_NUMBER_LENGTH,
+ retBytes, AS_NUMBER_OFFSET, AS_NUMBER_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROAttributesSubobject;
+
+public class RROAttributesSubobjectParser {
+
+ public static final int RES_F_LENGTH = 2;
+
+ public static final int RES_F_OFFSET = 0;
+ public static final int ATTRS_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+ public static RROAttributesSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length <= RES_F_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + RES_F_LENGTH + ".");
+
+ final byte[] attributes = Arrays.copyOfRange(soContentsBytes, ATTRS_F_OFFSET, soContentsBytes.length);
+
+ return new RROAttributesSubobject(attributes);
+ }
+
+ public static byte[] put(RROAttributesSubobject objToSerialize) {
+ final byte[] retBytes = new byte[RES_F_LENGTH + objToSerialize.getAttributes().length];
+
+ final byte[] attrs = objToSerialize.getAttributes();
+
+ System.arraycopy(attrs, 0, retBytes, ATTRS_F_OFFSET, attrs.length);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+
+public class RROGeneralizedLabelSubobjectParser implements RROLabelParser {
+
+ @Override
+ public RROLabelSubobject parse(byte[] cutBytes, boolean upStream) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ return new RROGeneralizedLabelSubobject(cutBytes, upStream);
+ }
+
+ @Override
+ public byte[] put(RROLabelSubobject objToSerialize) {
+ if (!(objToSerialize instanceof RROGeneralizedLabelSubobject))
+ throw new IllegalArgumentException("Unknown RROLabelSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed RROGeneralizedLabelSubobject.");
+ final byte[] retBytes = ((RROGeneralizedLabelSubobject) objToSerialize).getLabel();
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject
+ * RROIPAddressSubobject<IPv4Prefix>}
+ */
+public class RROIPv4AddressSubobjectParser {
+ public static final int IP_F_LENGTH = 4;
+ public static final int PREFIX_F_LENGTH = 1;
+ public static final int FLAGS_F_LENGTH = 1;
+
+ public static final int IP_F_OFFSET = 0;
+ public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+ public static final int FLAGS_F_OFFSET = PREFIX_F_OFFSET + PREFIX_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+
+ /*
+ * flags offset in bits
+ */
+ public static final int LPA_F_OFFSET = 7;
+ public static final int LPIU_F_OFFSET = 6;
+
+ public static RROIPAddressSubobject<IPv4Prefix> parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ final IPv4Address address = new IPv4Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+ final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+ final BitSet flags = ByteArray.bytesToBitSet(Arrays.copyOfRange(soContentsBytes, FLAGS_F_OFFSET, FLAGS_F_OFFSET + FLAGS_F_LENGTH));
+
+ return new RROIPAddressSubobject<IPv4Prefix>(new IPv4Prefix(address, length), flags.get(LPA_F_OFFSET), flags.get(LPIU_F_OFFSET));
+ }
+
+ public static byte[] put(ReportedRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof RROIPAddressSubobject))
+ throw new IllegalArgumentException("Unknown ReportedRouteSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed RROIPAddressSubobject.");
+
+ final RROIPAddressSubobject<?> specObj = (RROIPAddressSubobject<?>) objToSerialize;
+ final Prefix<?> prefix = specObj.getPrefix();
+
+ if (!(prefix instanceof IPv4Prefix))
+ throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv4Prefix.");
+
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+
+ flags.set(LPA_F_OFFSET, specObj.isLocalProtectionAvailable());
+ flags.set(LPIU_F_OFFSET, specObj.isLocalProtectionInUse());
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+ ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+ retBytes[PREFIX_F_OFFSET] = ByteArray.intToBytes(prefix.getLength())[Integer.SIZE / Byte.SIZE - 1];
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject
+ * RROIPAddressSubobject<IPv6Prefix>}
+ */
+public class RROIPv6AddressSubobjectParser {
+ public static final int IP_F_LENGTH = 16;
+ public static final int PREFIX_F_LENGTH = 1;
+ public static final int FLAGS_F_LENGTH = 1;
+
+ public static final int IP_F_OFFSET = 0;
+ public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+ public static final int FLAGS_F_OFFSET = PREFIX_F_OFFSET + PREFIX_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+
+ /*
+ * flags offset in bits
+ */
+ public static final int LPA_F_OFFSET = 7;
+ public static final int LPIU_F_OFFSET = 6;
+
+ public static RROIPAddressSubobject<IPv6Prefix> parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ final IPv6Address address = new IPv6Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+ final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+ final BitSet flags = ByteArray.bytesToBitSet(Arrays.copyOfRange(soContentsBytes, FLAGS_F_OFFSET, FLAGS_F_OFFSET + FLAGS_F_LENGTH));
+
+ return new RROIPAddressSubobject<IPv6Prefix>(new IPv6Prefix(address, length), flags.get(LPA_F_OFFSET), flags.get(LPIU_F_OFFSET));
+ }
+
+ public static byte[] put(ReportedRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof RROIPAddressSubobject))
+ throw new IllegalArgumentException("Unknown ReportedRouteSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed RROIPAddressSubobject.");
+
+ final RROIPAddressSubobject<?> specObj = (RROIPAddressSubobject<?>) objToSerialize;
+ final Prefix<?> prefix = specObj.getPrefix();
+
+ if (!(prefix instanceof IPv6Prefix))
+ throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv6Prefix.");
+
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+
+ flags.set(LPA_F_OFFSET, specObj.isLocalProtectionAvailable());
+ flags.set(LPIU_F_OFFSET, specObj.isLocalProtectionInUse());
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+ ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+ retBytes[PREFIX_F_OFFSET] = ByteArray.intToBytes(prefix.getLength())[Integer.SIZE / Byte.SIZE - 1];
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+
+public interface RROLabelParser {
+ RROLabelSubobject parse(byte[] cutBytes, boolean upStream) throws PCEPDeserializerException;
+
+ byte[] put(RROLabelSubobject objToSerialize);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.Util.BiParsersMap;
+import org.opendaylight.protocol.pcep.subobject.RROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROType1LabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROLabelSubobjectParser {
+
+ public static final int RES_F_LENGTH = 1;
+
+ public static final int C_TYPE_F_LENGTH = 1;
+
+ public static final int RES_F_OFFSET = 0;
+
+ public static final int C_TYPE_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+ public static final int HEADER_LENGTH = C_TYPE_F_OFFSET + C_TYPE_F_LENGTH;
+
+ public static final int U_FLAG_OFFSET = 0;
+
+ private static class MapOfParsers extends BiParsersMap<Class<? extends RROLabelSubobject>, Integer, RROLabelParser> {
+ private final static MapOfParsers instance = new MapOfParsers();
+
+ private MapOfParsers() {
+ this.fillInMap();
+ }
+
+ private void fillInMap() {
+ this.put(RROType1LabelSubobject.class, 1, new RROType1LabelSubobjectParser());
+ this.put(RROGeneralizedLabelSubobject.class, 2, new RROGeneralizedLabelSubobjectParser());
+ this.put(RROWavebandSwitchingLabelSubobject.class, 3, new RROWavebandSwitchingLabelSubobjectParser());
+ }
+
+ public static MapOfParsers getInstance() {
+ return instance;
+ }
+ }
+
+ public static RROLabelSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length < HEADER_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + HEADER_LENGTH + ".");
+
+ final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(soContentsBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+ final int c_type = soContentsBytes[C_TYPE_F_OFFSET] & 0xFF;
+
+ final RROLabelParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+ if (parser == null) {
+ throw new PCEPDeserializerException("Unknown C-TYPE for ero label subobject. Passed: " + c_type);
+ }
+
+ return parser.parse(ByteArray.cutBytes(soContentsBytes, HEADER_LENGTH), reserved.get(U_FLAG_OFFSET));
+ }
+
+ public static byte[] put(RROLabelSubobject objToSerialize) {
+ final Integer c_type = MapOfParsers.getInstance().getKeyValueFromKey(objToSerialize.getClass());
+ final RROLabelParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+ if (c_type == null || parser == null)
+ throw new IllegalArgumentException("Unknown RROLabelSubobject instance. Passed " + objToSerialize.getClass());
+
+ final byte[] labelbytes = parser.put(objToSerialize);
+
+ final byte[] retBytes = new byte[labelbytes.length + HEADER_LENGTH];
+
+ System.arraycopy(labelbytes, 0, retBytes, HEADER_LENGTH, labelbytes.length);
+
+ final BitSet reserved = new BitSet();
+ reserved.set(U_FLAG_OFFSET, objToSerialize.isUpStream());
+ System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+ retBytes[C_TYPE_F_OFFSET] = (byte) c_type.intValue();
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROPathKeyWith128PCEIDSubobjectParser {
+
+ public static final int PK_F_LENGTH = 2;
+ public static final int PCE_ID_F_LENGTH = 16;
+
+ public static final int PK_F_OFFSET = 0;
+ public static final int PCE_ID_F_OFFSET = PK_F_OFFSET + PK_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = PCE_ID_F_OFFSET + PCE_ID_F_LENGTH;
+
+ public static RROPathKeyWith128PCEIDSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+ final int pathKey = ByteArray.bytesToShort(Arrays.copyOfRange(soContentsBytes, PK_F_OFFSET, PCE_ID_F_OFFSET)) & 0xFFFF;
+
+ final byte[] pceId = Arrays.copyOfRange(soContentsBytes, PCE_ID_F_OFFSET, CONTENT_LENGTH);
+
+ return new RROPathKeyWith128PCEIDSubobject(pathKey, pceId);
+ }
+
+ public static byte[] put(RROPathKeyWith128PCEIDSubobject objToSerialize) {
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ System.arraycopy(ByteArray.shortToBytes((short) objToSerialize.getPathKey()), 0, retBytes, PK_F_OFFSET, PK_F_LENGTH);
+
+ if (objToSerialize.getPceId().length != PCE_ID_F_LENGTH)
+ throw new IllegalArgumentException("Wrong length of pce id. Passed: " + objToSerialize.getPceId().length + ". Expected: =" + PCE_ID_F_LENGTH);
+ System.arraycopy(objToSerialize.getPceId(), 0, retBytes, PCE_ID_F_OFFSET, PCE_ID_F_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROPathKeyWith32PCEIDSubobjectParser {
+
+ public static final int PK_F_LENGTH = 2;
+ public static final int PCE_ID_F_LENGTH = 4;
+
+ public static final int PK_F_OFFSET = 0;
+ public static final int PCE_ID_F_OFFSET = PK_F_OFFSET + PK_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = PCE_ID_F_OFFSET + PCE_ID_F_LENGTH;
+
+ public static RROPathKeyWith32PCEIDSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: =" + CONTENT_LENGTH + ".");
+
+ final int pathKey = ByteArray.bytesToShort(Arrays.copyOfRange(soContentsBytes, PK_F_OFFSET, PCE_ID_F_OFFSET)) & 0xFFFF;
+
+ final byte[] pceId = Arrays.copyOfRange(soContentsBytes, PCE_ID_F_OFFSET, CONTENT_LENGTH);
+
+ return new RROPathKeyWith32PCEIDSubobject(pathKey, pceId);
+ }
+
+ public static byte[] put(RROPathKeyWith32PCEIDSubobject objToSerialize) {
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ System.arraycopy(ByteArray.shortToBytes((short) objToSerialize.getPathKey()), 0, retBytes, PK_F_OFFSET, PK_F_LENGTH);
+
+ if (objToSerialize.getPceId().length != PCE_ID_F_LENGTH)
+ throw new IllegalArgumentException("Wrong length of pce id. Passed: " + objToSerialize.getPceId().length + ". Expected: =" + PCE_ID_F_LENGTH);
+ System.arraycopy(objToSerialize.getPceId(), 0, retBytes, PCE_ID_F_OFFSET, PCE_ID_F_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+
+public interface RROProtectionParser {
+
+ RROProtectionSubobject parse(byte[] cutBytes) throws PCEPDeserializerException;
+
+ byte[] put(RROProtectionSubobject objToSerialize);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.Util.BiParsersMap;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType1Subobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType2Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROProtectionSubobjectParser {
+
+ public static final int RES_F_LENGTH = 1;
+
+ public static final int C_TYPE_F_LENGTH = 1;
+
+ public static final int RES_F_OFFSET = 0;
+
+ public static final int C_TYPE_F_OFFSET = RES_F_OFFSET + RES_F_LENGTH;
+
+ public static final int HEADER_LENGTH = C_TYPE_F_OFFSET + C_TYPE_F_LENGTH;
+
+ public static final int U_FLAG_OFFSET = 0;
+
+ private static class MapOfParsers extends BiParsersMap<Class<? extends RROProtectionSubobject>, Integer, RROProtectionParser> {
+ private final static MapOfParsers instance = new MapOfParsers();
+
+ private MapOfParsers() {
+ this.fillInMap();
+ }
+
+ private void fillInMap() {
+ this.put(RROProtectionType1Subobject.class, 1, new RROProtectionType1SubobjectParser());
+ this.put(RROProtectionType2Subobject.class, 2, new RROProtectionType2SubobjectParser());
+ }
+
+ public static MapOfParsers getInstance() {
+ return instance;
+ }
+ }
+
+ public static RROProtectionSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length < HEADER_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: >" + HEADER_LENGTH + ".");
+
+ final int c_type = soContentsBytes[C_TYPE_F_OFFSET] & 0xFF;
+
+ final RROProtectionParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+ if (parser == null) {
+ throw new PCEPDeserializerException("Unknown C-TYPE for ero protection subobject. Passed: " + c_type);
+ }
+
+ return parser.parse(ByteArray.cutBytes(soContentsBytes, HEADER_LENGTH));
+ }
+
+ public static byte[] put(RROProtectionSubobject objToSerialize) {
+ final Integer c_type = MapOfParsers.getInstance().getKeyValueFromKey(objToSerialize.getClass());
+ final RROProtectionParser parser = MapOfParsers.getInstance().getValueFromKeyValue(c_type);
+
+ if (c_type == null || parser == null)
+ throw new IllegalArgumentException("Unknown EROProtectionSubobject instance. Passed " + objToSerialize.getClass());
+
+ final byte[] protBytes = parser.put(objToSerialize);
+
+ final byte[] retBytes = new byte[protBytes.length + HEADER_LENGTH];
+
+ System.arraycopy(protBytes, 0, retBytes, HEADER_LENGTH, protBytes.length);
+
+ retBytes[C_TYPE_F_OFFSET] = (byte) c_type.intValue();
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType1Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROProtectionType1SubobjectParser implements RROProtectionParser {
+
+ public static final int RES_F_LENGTH = 4;
+
+ public static final int RES_F_OFFSET = 0;
+
+ public static final int CONTENT_LENGTH = RES_F_OFFSET + RES_F_LENGTH;
+
+ /*
+ * offsets of flags inside reserved field
+ */
+ public static final int S_FLAG_OFFSET = 0;
+
+ @Override
+ public RROProtectionSubobject parse(byte[] cutBytes) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (cutBytes.length < CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+ final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(cutBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+ final byte linkFlags = (byte) (cutBytes[3] & 0x3F);
+
+ return new RROProtectionType1Subobject(reserved.get(S_FLAG_OFFSET), linkFlags);
+ }
+
+ @Override
+ public byte[] put(RROProtectionSubobject objToSerialize) {
+ if (!(objToSerialize instanceof RROProtectionType1Subobject))
+ throw new IllegalArgumentException("Unknown RROProtectionSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed RROProtectionType1Subobject.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ final BitSet reserved = new BitSet();
+ reserved.set(S_FLAG_OFFSET, ((RROProtectionType1Subobject) objToSerialize).isSecondary());
+ System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+ retBytes[3] |= ((RROProtectionType1Subobject) objToSerialize).getLinkFlags() & 0x3F;
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType2Subobject;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class RROProtectionType2SubobjectParser implements RROProtectionParser {
+
+ public static final int RES_F_LENGTH = 8;
+
+ public static final int RES_F_OFFSET = 0;
+
+ public static final int CONTENT_LENGTH = RES_F_OFFSET + RES_F_LENGTH;
+
+ /*
+ * offsets of flags inside reserved field
+ */
+ public static final int S_FLAG_OFFSET = 0;
+ public static final int P_FLAG_OFFSET = 1;
+ public static final int N_FLAG_OFFSET = 2;
+ public static final int O_FLAG_OFFSET = 3;
+
+ public static final int I_FLAG_OFFSET = 32;
+ public static final int R_FLAG_OFFSET = 33;
+
+ @Override
+ public RROProtectionSubobject parse(byte[] cutBytes) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (cutBytes.length < CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: >" + CONTENT_LENGTH + ".");
+
+ final BitSet reserved = ByteArray.bytesToBitSet(Arrays.copyOfRange(cutBytes, RES_F_OFFSET, RES_F_LENGTH));
+
+ final byte linkFlags = (byte) (cutBytes[3] & 0x3F);
+ final byte lspFlags = (byte) (cutBytes[1] & 0x3F);
+ final byte segFlags = (byte) (cutBytes[5] & 0x3F);
+
+ return new RROProtectionType2Subobject(reserved.get(S_FLAG_OFFSET), reserved.get(P_FLAG_OFFSET), reserved.get(N_FLAG_OFFSET),
+ reserved.get(N_FLAG_OFFSET), lspFlags, linkFlags, reserved.get(I_FLAG_OFFSET), reserved.get(R_FLAG_OFFSET), segFlags);
+ }
+
+ @Override
+ public byte[] put(RROProtectionSubobject objToSerialize) {
+ if (!(objToSerialize instanceof RROProtectionType2Subobject))
+ throw new IllegalArgumentException("Unknown RROProtectionSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed RROProtectionType2Subobject.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ final BitSet reserved = new BitSet();
+ reserved.set(S_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isSecondaryLsp());
+ reserved.set(P_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isProtectionLsp());
+ reserved.set(N_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isNotification());
+ reserved.set(O_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isOperational());
+ reserved.set(I_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isInPlace());
+ reserved.set(R_FLAG_OFFSET, ((RROProtectionType2Subobject) objToSerialize).isRequired());
+ System.arraycopy(ByteArray.bitSetToBytes(reserved, RES_F_LENGTH), 0, retBytes, RES_F_OFFSET, RES_F_LENGTH);
+
+ retBytes[3] |= ((RROProtectionType2Subobject) objToSerialize).getLinkFlags() & 0x3F;
+ retBytes[1] |= ((RROProtectionType2Subobject) objToSerialize).getLspFlags() & 0x3F;
+ retBytes[5] |= ((RROProtectionType2Subobject) objToSerialize).getSegFlags() & 0x3F;
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROType1LabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+public class RROType1LabelSubobjectParser implements RROLabelParser {
+
+ public static final int LABEL_LENGTH = 4;
+
+ @Override
+ public RROLabelSubobject parse(byte[] cutBytes, boolean upStream) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (cutBytes.length != LABEL_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: " + LABEL_LENGTH + ".");
+
+ return new RROType1LabelSubobject(UnsignedInts.toLong(ByteArray.bytesToInt(cutBytes)), upStream);
+ }
+
+ @Override
+ public byte[] put(RROLabelSubobject objToSerialize) {
+ if (!(objToSerialize instanceof RROType1LabelSubobject))
+ throw new IllegalArgumentException("Unknown RROLabelSubobject instance. Passed " + objToSerialize.getClass() + ". Needed RROType1LabelSubobject.");
+
+ return ByteArray.intToBytes((int) ((RROType1LabelSubobject) objToSerialize).getLabel());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for
+ * {@link org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject
+ * RROUnnumberedInterfaceSubobject}
+ */
+public class RROUnnumberedInterfaceSubobjectParser {
+ public static final int ROUTER_ID_NUMBER_LENGTH = 4;
+ public static final int INTERFACE_ID_NUMBER_LENGTH = 4;
+
+ public static final int ROUTER_ID_NUMBER_OFFSET = 2; // added reserved field of size 2
+ public static final int INTERFACE_ID_NUMBER_OFFSET = ROUTER_ID_NUMBER_OFFSET + ROUTER_ID_NUMBER_LENGTH;
+
+ public static final int CONTENT_LENGTH = INTERFACE_ID_NUMBER_OFFSET + INTERFACE_ID_NUMBER_LENGTH;
+
+ public static RROUnnumberedInterfaceSubobject parse(byte[] soContentsBytes) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ return new RROUnnumberedInterfaceSubobject(new IPv4Address(
+ ByteArray.subByte(soContentsBytes, ROUTER_ID_NUMBER_OFFSET, ROUTER_ID_NUMBER_LENGTH)), new UnnumberedInterfaceIdentifier(
+ UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(soContentsBytes, INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH)))));
+ }
+
+ public static byte[] put(ReportedRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof RROUnnumberedInterfaceSubobject))
+ throw new IllegalArgumentException("Unknown ReportedRouteSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed RROUnnumberedInterfaceSubobject.");
+
+ byte[] retBytes;
+ retBytes = new byte[CONTENT_LENGTH];
+ final RROUnnumberedInterfaceSubobject specObj = (RROUnnumberedInterfaceSubobject) objToSerialize;
+
+ ByteArray.copyWhole(specObj.getRouterID().getAddress(), retBytes, ROUTER_ID_NUMBER_OFFSET);
+ System.arraycopy(ByteArray.longToBytes(specObj.getInterfaceID().getInterfaceId()), Long.SIZE / Byte.SIZE - INTERFACE_ID_NUMBER_LENGTH, retBytes,
+ INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.Arrays;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.util.ByteArray;
+import com.google.common.primitives.UnsignedInts;
+
+public class RROWavebandSwitchingLabelSubobjectParser implements RROLabelParser {
+
+ public static int WAVEB_F_LENGTH = 4;
+ public static int START_F_LENGTH = 4;
+ public static int END_F_LENGTH = 4;
+
+ public static int WAVEB_F_OFFSET = 0;
+ public static int START_F_OFFSET = WAVEB_F_OFFSET + WAVEB_F_LENGTH;
+ public static int END_F_OFFSET = START_F_OFFSET + START_F_LENGTH;
+
+ public static int CONTENT_LENGTH = END_F_OFFSET + END_F_LENGTH;
+
+ @Override
+ public RROLabelSubobject parse(byte[] cutBytes, boolean upStream) throws PCEPDeserializerException {
+ if (cutBytes == null || cutBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (cutBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + cutBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ return new RROWavebandSwitchingLabelSubobject(UnsignedInts.toLong(ByteArray.bytesToInt(Arrays.copyOfRange(cutBytes, WAVEB_F_OFFSET, START_F_OFFSET))),
+ UnsignedInts.toLong(ByteArray.bytesToInt(Arrays.copyOfRange(cutBytes, START_F_OFFSET, END_F_OFFSET))), UnsignedInts.toLong(ByteArray
+ .bytesToInt(Arrays.copyOfRange(cutBytes, END_F_OFFSET, CONTENT_LENGTH))), upStream);
+ }
+
+ @Override
+ public byte[] put(RROLabelSubobject objToSerialize) {
+ if (!(objToSerialize instanceof RROWavebandSwitchingLabelSubobject))
+ throw new IllegalArgumentException("Unknown RROLabelSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed RROWavebandSwitchingLabelSubobject.");
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ final RROWavebandSwitchingLabelSubobject obj = (RROWavebandSwitchingLabelSubobject) objToSerialize;
+
+ System.arraycopy(ByteArray.intToBytes((int) obj.getWavebandId()), 0, retBytes, WAVEB_F_OFFSET, WAVEB_F_LENGTH);
+ System.arraycopy(ByteArray.intToBytes((int) obj.getStartLabel()), 0, retBytes, START_F_OFFSET, START_F_LENGTH);
+ System.arraycopy(ByteArray.intToBytes((int) obj.getEndLabel()), 0, retBytes, END_F_OFFSET, END_F_LENGTH);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject
+ * XROAsNumberSubobject}
+ */
+
+public class XROAsNumberSubobjectParser {
+ public static final int AS_NUMBER_LENGTH = 2;
+
+ public static final int AS_NUMBER_OFFSET = 0;
+
+ public static final int CONTENT_LENGTH = AS_NUMBER_LENGTH + AS_NUMBER_OFFSET;
+
+ public static XROAsNumberSubobject parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ return new XROAsNumberSubobject(new ASNumber((ByteArray.bytesToShort(soContentsBytes) & 0xFFFF)), mandatory);
+ }
+
+ public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof XROAsNumberSubobject))
+ throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass() + ". Needed XROAsNumberSubobject.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ System.arraycopy(ByteArray.longToBytes(((XROAsNumberSubobject) objToSerialize).getASNumber().getAsn()), Long.SIZE / Byte.SIZE - AS_NUMBER_LENGTH,
+ retBytes, AS_NUMBER_OFFSET, AS_NUMBER_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject
+ * XROIPPrefixSubobject<IPv4Prefix>}
+ */
+public class XROIPv4PrefixSubobjectParser {
+ public static final int IP_F_LENGTH = 4;
+ public static final int PREFIX_F_LENGTH = 1;
+ public static final int ATTRIBUTE_LENGTH = 1;
+
+ public static final int IP_F_OFFSET = 0;
+ public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+ public static final int ATTRIBUTE_OFFSET = PREFIX_F_OFFSET + PREFIX_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = ATTRIBUTE_OFFSET + ATTRIBUTE_LENGTH;
+
+ public static XROIPPrefixSubobject<IPv4Prefix> parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ final IPv4Address address = new IPv4Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+ final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+ return new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(address, length), mandatory, XROSubobjectAttributeMapping.getInstance()
+ .getFromAttributeIdentifier((short) (soContentsBytes[ATTRIBUTE_OFFSET] & 0xFF)));
+ }
+
+ public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof XROIPPrefixSubobject))
+ throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass() + ". Needed XROIPPrefixSubobject.");
+
+ final XROIPPrefixSubobject<?> specObj = (XROIPPrefixSubobject<?>) objToSerialize;
+ final Prefix<?> prefix = specObj.getPrefix();
+
+ if (!(prefix instanceof IPv4Prefix))
+ throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv4Prefix.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+ ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+ retBytes[PREFIX_F_OFFSET] = (byte) prefix.getLength();
+ retBytes[ATTRIBUTE_OFFSET] = (byte) XROSubobjectAttributeMapping.getInstance().getFromAttributeEnum(specObj.getAttribute());
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import com.google.common.primitives.UnsignedBytes;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject
+ * XROIPPrefixSubobject<IPv6Prefix>}
+ */
+public class XROIPv6PrefixSubobjectParser {
+ public static final int IP_F_LENGTH = 16;
+ public static final int PREFIX_F_LENGTH = 1;
+ public static final int ATTRIBUTE_LENGTH = 1;
+
+ public static final int IP_F_OFFSET = 0;
+ public static final int PREFIX_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+ public static final int ATTRIBUTE_OFFSET = PREFIX_F_OFFSET + PREFIX_F_LENGTH;
+
+ public static final int CONTENT_LENGTH = ATTRIBUTE_OFFSET + ATTRIBUTE_LENGTH;
+
+ public static XROIPPrefixSubobject<IPv6Prefix> parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ final IPv6Address address = new IPv6Address(ByteArray.subByte(soContentsBytes, IP_F_OFFSET, IP_F_LENGTH));
+ final int length = UnsignedBytes.toInt(soContentsBytes[PREFIX_F_OFFSET]);
+
+ return new XROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(address, length), mandatory, XROSubobjectAttributeMapping.getInstance()
+ .getFromAttributeIdentifier((short) (soContentsBytes[ATTRIBUTE_OFFSET] & 0xFF)));
+ }
+
+ public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof XROIPPrefixSubobject))
+ throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass() + ". Needed XROIPPrefixSubobject.");
+
+ final XROIPPrefixSubobject<?> specObj = (XROIPPrefixSubobject<?>) objToSerialize;
+ final Prefix<?> prefix = specObj.getPrefix();
+
+ if (!(prefix instanceof IPv6Prefix))
+ throw new IllegalArgumentException("Unknown AbstractPrefix instance. Passed " + prefix.getClass() + ". Needed IPv6Prefix.");
+
+ final byte[] retBytes = new byte[CONTENT_LENGTH];
+
+ ByteArray.copyWhole(prefix.getAddress().getAddress(), retBytes, IP_F_OFFSET);
+ retBytes[PREFIX_F_OFFSET] = (byte) prefix.getLength();
+ retBytes[ATTRIBUTE_OFFSET] = (byte) XROSubobjectAttributeMapping.getInstance().getFromAttributeEnum(specObj.getAttribute());
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.subobject. XROSRLGSubobject
+ * XROSRLGSubobject}
+ */
+public class XROSRLGSubobjectParser {
+ public static final int SRLG_ID_NUMBER_LENGTH = 4;
+ public static final int ATTRIBUTE_LENGTH = 1;
+
+ public static final int SRLG_ID_NUMBER_OFFSET = 0;
+ public static final int ATTRIBUTE_OFFSET = SRLG_ID_NUMBER_OFFSET + SRLG_ID_NUMBER_LENGTH + 1; // added reserved field of size 1
+
+ public static final int CONTENT_LENGTH = ATTRIBUTE_OFFSET + ATTRIBUTE_LENGTH;
+
+ public static XROSRLGSubobject parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ return new XROSRLGSubobject(new SharedRiskLinkGroup(UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(soContentsBytes, SRLG_ID_NUMBER_OFFSET,
+ SRLG_ID_NUMBER_LENGTH)))), mandatory);
+ }
+
+ public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof XROSRLGSubobject))
+ throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass() + ". Needed XROSRLGSubobject.");
+
+ byte[] retBytes;
+ retBytes = new byte[CONTENT_LENGTH];
+ final XROSRLGSubobject specObj = (XROSRLGSubobject) objToSerialize;
+
+ ByteArray.copyWhole(ByteArray.intToBytes((int) specObj.getSrlgId().getValue()), retBytes, SRLG_ID_NUMBER_OFFSET);
+ retBytes[ATTRIBUTE_OFFSET] = (byte) XROSubobjectAttributeMapping.getInstance().getFromAttributeEnum(specObj.getAttribute());
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+
+/**
+ * Bidirectional mapping for XROSubobjectAttribute and appropriate identifier.
+ */
+public class XROSubobjectAttributeMapping {
+ private static final XROSubobjectAttributeMapping instance = new XROSubobjectAttributeMapping();
+
+ private final Map<XROSubobjectAttribute, Integer> ofCodesMap = new EnumMap<XROSubobjectAttribute, Integer>(XROSubobjectAttribute.class);
+ private final Map<Integer, XROSubobjectAttribute> ofCodeIdsMap = new HashMap<Integer, XROSubobjectAttribute>();
+
+ private XROSubobjectAttributeMapping() {
+ this.fillIn();
+ }
+
+ private void fillIn() {
+ this.fillIn(0, XROSubobjectAttribute.INTERFACE);
+ this.fillIn(1, XROSubobjectAttribute.NODE);
+ this.fillIn(2, XROSubobjectAttribute.SRLG);
+ }
+
+ private void fillIn(int identifier, XROSubobjectAttribute ofCode) {
+ this.ofCodesMap.put(ofCode, identifier);
+ this.ofCodeIdsMap.put(identifier, ofCode);
+ }
+
+ public int getFromAttributeEnum(XROSubobjectAttribute ofCode) {
+ final Integer ofci = this.ofCodesMap.get(ofCode);
+ if (ofci == null)
+ throw new NoSuchElementException("Unknown XROSubobjectAttribute type: " + ofCode);
+ return ofci;
+ }
+
+ public XROSubobjectAttribute getFromAttributeIdentifier(int identifier) {
+ final XROSubobjectAttribute ofc = this.ofCodeIdsMap.get(identifier);
+ if (ofc == null)
+ throw new NoSuchElementException("Unknown XROSubobjectAttribute identifier.");
+ return ofc;
+ }
+
+ public static XROSubobjectAttributeMapping getInstance() {
+ return instance;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.subobject;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Parser for
+ * {@link org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject
+ * XROUnnumberedInterfaceSubobject}
+ */
+public class XROUnnumberedInterfaceSubobjectParser {
+ public static final int ATTRIBUTE_LENGTH = 1;
+ public static final int ROUTER_ID_NUMBER_LENGTH = 4;
+ public static final int INTERFACE_ID_NUMBER_LENGTH = 4;
+
+ public static final int ATTRIBUTE_OFFSET = 1;// added reserved field of size 1
+ public static final int ROUTER_ID_NUMBER_OFFSET = ATTRIBUTE_OFFSET + ATTRIBUTE_LENGTH;
+ public static final int INTERFACE_ID_NUMBER_OFFSET = ROUTER_ID_NUMBER_OFFSET + ROUTER_ID_NUMBER_LENGTH;
+
+ public static final int CONTENT_LENGTH = INTERFACE_ID_NUMBER_OFFSET + INTERFACE_ID_NUMBER_LENGTH;
+
+ public static XROUnnumberedInterfaceSubobject parse(byte[] soContentsBytes, boolean mandatory) throws PCEPDeserializerException {
+ if (soContentsBytes == null || soContentsBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+ if (soContentsBytes.length != CONTENT_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + soContentsBytes.length + "; Expected: " + CONTENT_LENGTH + ".");
+
+ return new XROUnnumberedInterfaceSubobject(new IPv4Address(
+ ByteArray.subByte(soContentsBytes, ROUTER_ID_NUMBER_OFFSET, ROUTER_ID_NUMBER_LENGTH)), new UnnumberedInterfaceIdentifier(
+ UnsignedInts.toLong(ByteArray.bytesToInt(ByteArray.subByte(soContentsBytes, INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH)))),
+ mandatory, XROSubobjectAttributeMapping.getInstance().getFromAttributeIdentifier((short) (soContentsBytes[ATTRIBUTE_OFFSET] & 0xFF)));
+ }
+
+ public static byte[] put(ExcludeRouteSubobject objToSerialize) {
+ if (!(objToSerialize instanceof XROUnnumberedInterfaceSubobject))
+ throw new IllegalArgumentException("Unknown PCEPXROSubobject instance. Passed " + objToSerialize.getClass()
+ + ". Needed XROUnnumberedInterfaceSubobject.");
+
+ byte[] retBytes;
+ retBytes = new byte[CONTENT_LENGTH];
+ final XROUnnumberedInterfaceSubobject specObj = (XROUnnumberedInterfaceSubobject) objToSerialize;
+
+ retBytes[ATTRIBUTE_OFFSET] = (byte) XROSubobjectAttributeMapping.getInstance().getFromAttributeEnum(specObj.getAttribute());
+ ByteArray.copyWhole(specObj.getRouterID().getAddress(), retBytes, ROUTER_ID_NUMBER_OFFSET);
+ System.arraycopy(ByteArray.longToBytes(specObj.getInterfaceID().getInterfaceId()), Long.SIZE / Byte.SIZE - INTERFACE_ID_NUMBER_LENGTH, retBytes,
+ INTERFACE_ID_NUMBER_OFFSET, INTERFACE_ID_NUMBER_LENGTH);
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.tlv;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.IPv4ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.tlv.IPv4LSPIdentifiersTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.LSPIdentifiersTlv LSPIdentifiersTlv}
+ * parameterized as IPv4Address
+ */
+public class LSPIdentifierIPv4TlvParser {
+
+ private static final int IP_F_LENGTH = 4;
+ private static final int LSP_ID_F_LENGTH = 2;
+ private static final int TUNNEL_ID_F_LENGTH = 2;
+ private static final int EX_TUNNEL_ID_F_LENGTH = 4;
+
+ private static final int IP_F_OFFSET = 0;
+ private static final int LSP_ID_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+ private static final int TUNNLE_ID_F_OFFSET = LSP_ID_F_OFFSET + LSP_ID_F_LENGTH;
+ private static final int EX_TUNNEL_ID_F_OFFSET = TUNNLE_ID_F_OFFSET + TUNNEL_ID_F_LENGTH;
+
+ private static final int SIZE = EX_TUNNEL_ID_F_OFFSET + EX_TUNNEL_ID_F_LENGTH;
+
+ public static IPv4LSPIdentifiersTlv parse(byte[] valueBytes) throws PCEPDeserializerException {
+ if (valueBytes == null || valueBytes.length == 0)
+ throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+ if (valueBytes.length != SIZE)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: " + SIZE + ".");
+
+ return new IPv4LSPIdentifiersTlv(new IPv4Address(
+ ByteArray.subByte(valueBytes, IP_F_OFFSET, IP_F_LENGTH)), new LSPIdentifier(ByteArray.subByte(valueBytes, LSP_ID_F_OFFSET, LSP_ID_F_LENGTH)),
+ new TunnelIdentifier(ByteArray.subByte(valueBytes, TUNNLE_ID_F_OFFSET, TUNNEL_ID_F_LENGTH)),
+ new IPv4ExtendedTunnelIdentifier(new IPv4Address(ByteArray.subByte(valueBytes, EX_TUNNEL_ID_F_OFFSET, EX_TUNNEL_ID_F_LENGTH))));
+ }
+
+ public static byte[] put(IPv4LSPIdentifiersTlv objToSerialize) {
+ if (objToSerialize == null)
+ throw new IllegalArgumentException("IPv4LSPIdentifiersTlv is mandatory.");
+
+ final byte[] retBytes = new byte[SIZE];
+
+ ByteArray.copyWhole(objToSerialize.getSenderAddress().getAddress(), retBytes, IP_F_OFFSET);
+ ByteArray.copyWhole(objToSerialize.getLspID().getLspId(), retBytes, LSP_ID_F_OFFSET);
+ ByteArray.copyWhole(objToSerialize.getTunnelID().getBytes(), retBytes, TUNNLE_ID_F_OFFSET);
+ ByteArray.copyWhole(objToSerialize.getExtendedTunnelID().getIdentifier().getAddress(), retBytes, EX_TUNNEL_ID_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.tlv;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.IPv6ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.tlv.IPv6LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPIdentifiersTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.LSPIdentifiersTlv LSPIdentifiersTlv}
+ * parameterized as IPv6Address
+ */
+public class LSPIdentifierIPv6TlvParser {
+
+ private static final int IP_F_LENGTH = 16;
+ private static final int LSP_ID_F_LENGTH = 2;
+ private static final int TUNNEL_ID_F_LENGTH = 2;
+ private static final int EX_TUNNEL_ID_F_LENGTH = 16;
+
+ private static final int IP_F_OFFSET = 0;
+ private static final int LSP_ID_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+ private static final int TUNNLE_ID_F_OFFSET = LSP_ID_F_OFFSET + LSP_ID_F_LENGTH;
+ private static final int EX_TUNNEL_ID_F_OFFSET = TUNNLE_ID_F_OFFSET + TUNNEL_ID_F_LENGTH;
+
+ private static final int SIZE = EX_TUNNEL_ID_F_OFFSET + EX_TUNNEL_ID_F_LENGTH;
+
+ public static LSPIdentifiersTlv<IPv6Address> parse(byte[] valueBytes) throws PCEPDeserializerException {
+ if (valueBytes == null || valueBytes.length == 0)
+ throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+ if (valueBytes.length != SIZE)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: " + SIZE + ".");
+
+ return new IPv6LSPIdentifiersTlv(new IPv6Address(
+ ByteArray.subByte(valueBytes, IP_F_OFFSET, IP_F_LENGTH)), new LSPIdentifier(ByteArray.subByte(valueBytes, LSP_ID_F_OFFSET, LSP_ID_F_LENGTH)),
+ new TunnelIdentifier(ByteArray.subByte(valueBytes, TUNNLE_ID_F_OFFSET, TUNNEL_ID_F_LENGTH)),
+ new IPv6ExtendedTunnelIdentifier(new IPv6Address(ByteArray.subByte(valueBytes, EX_TUNNEL_ID_F_OFFSET, EX_TUNNEL_ID_F_LENGTH))));
+ }
+
+ public static byte[] put(IPv6LSPIdentifiersTlv objToSerialize) {
+ if (objToSerialize == null)
+ throw new IllegalArgumentException("IPv6LSPIdentifiersTlv is mandatory.");
+
+ final byte[] retBytes = new byte[SIZE];
+
+ ByteArray.copyWhole(objToSerialize.getSenderAddress().getAddress(), retBytes, IP_F_OFFSET);
+ ByteArray.copyWhole(objToSerialize.getLspID().getLspId(), retBytes, LSP_ID_F_OFFSET);
+ ByteArray.copyWhole(objToSerialize.getTunnelID().getBytes(), retBytes, TUNNLE_ID_F_OFFSET);
+ ByteArray.copyWhole(objToSerialize.getExtendedTunnelID().getIdentifier().getAddress(), retBytes, EX_TUNNEL_ID_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.tlv;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv NoPathVectorTlv}
+ */
+public class NoPathVectorTlvParser {
+
+ public static final int FLAGS_F_LENGTH = 4;
+
+ /*
+ * flags offsets inside flags field in bits
+ */
+ public static final int PCE_UNAVAILABLE = 31;
+ public static final int UNKNOWN_DEST = 30;
+ public static final int UNKNOWN_SRC = 29;
+
+ /*
+ * flags offsets of flags added by GCO extension
+ */
+ public static final int NO_GCO_SOLUTION = 25;
+ public static final int NO_GCO_MIGRATION_PATH = 26;
+
+ /*
+ * flags offsets of flags added by RFC 6006
+ */
+ public static final int REACHABLITY_PROBLEM = 24;
+
+ public static NoPathVectorTlv parse(byte[] valueBytes) throws PCEPDeserializerException {
+ if (valueBytes == null || valueBytes.length == 0)
+ throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
+
+ if (valueBytes.length != FLAGS_F_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: >=" + FLAGS_F_LENGTH + ".");
+
+ final BitSet flags = ByteArray.bytesToBitSet(valueBytes);
+ return new NoPathVectorTlv(flags.get(PCE_UNAVAILABLE), flags.get(UNKNOWN_DEST), flags.get(UNKNOWN_SRC), flags.get(NO_GCO_SOLUTION),
+ flags.get(NO_GCO_MIGRATION_PATH), flags.get(REACHABLITY_PROBLEM));
+ }
+
+ public static byte[] put(NoPathVectorTlv obj) {
+ if (obj == null)
+ throw new IllegalArgumentException("NoPathVectorTlv is mandatory.");
+
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+
+ flags.set(PCE_UNAVAILABLE, obj.isPceUnavailable());
+ flags.set(UNKNOWN_DEST, obj.isUnknownDest());
+ flags.set(UNKNOWN_SRC, obj.isUnknownSrc());
+ flags.set(NO_GCO_SOLUTION, obj.isNoGCOSolution());
+ flags.set(NO_GCO_MIGRATION_PATH, obj.isNoGCOMigrationPath());
+ flags.set(REACHABLITY_PROBLEM, obj.isReachablityProblem());
+
+ return ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.tlv;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.impl.PCEPOFCodesMapping;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.OFListTlv OFListTlv}
+ */
+public class OFListTlvParser {
+
+ private static final int OF_CODE_ELEMENT_LENGTH = 2;
+
+ public static OFListTlv parse(byte[] valueBytes) throws PCEPDeserializerException {
+ if (valueBytes == null || valueBytes.length == 0)
+ throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+ if (valueBytes.length % OF_CODE_ELEMENT_LENGTH != 0)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + ".");
+
+ final List<PCEPOFCodes> ofCodes = new ArrayList<PCEPOFCodes>();
+ for (int i = 0; i < valueBytes.length; i += OF_CODE_ELEMENT_LENGTH) {
+ try {
+ ofCodes.add(PCEPOFCodesMapping.getInstance().getFromCodeIdentifier(
+ ByteArray.bytesToShort(Arrays.copyOfRange(valueBytes, i, i + OF_CODE_ELEMENT_LENGTH)) & 0xFFFF));
+ } catch (final NoSuchElementException nsee) {
+ throw new PCEPDeserializerException(nsee, "Unknown OF Code inside OF Code list Tlv.");
+ }
+ }
+
+ return new OFListTlv(ofCodes);
+ }
+
+ public static byte[] put(OFListTlv objToSerialize) {
+ if (objToSerialize == null)
+ throw new IllegalArgumentException("OFListTlv is mandatory.");
+
+ final List<PCEPOFCodes> ofCodes = objToSerialize.getOfCodes();
+ final byte[] retBytes = new byte[ofCodes.size() * OF_CODE_ELEMENT_LENGTH];
+
+ final int size = ofCodes.size();
+ for (int i = 0; i < size; i++) {
+ ByteArray.copyWhole(ByteArray.shortToBytes((short) PCEPOFCodesMapping.getInstance().getFromOFCodesEnum(ofCodes.get(i))), retBytes, i
+ * OF_CODE_ELEMENT_LENGTH);
+ }
+
+ return retBytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.tlv;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv
+ * PCEStatefulCapabilityTlv}
+ *
+ * @see <a
+ * href="http://www.ietf.org/id/draft-crabbe-pce-pce-initiated-lsp-00.txt#section-4.1">
+ * Stateful PCE Capability TLV</a>
+ */
+public final class PCEStatefulCapabilityTlvParser {
+ /*
+ * Flags field length in Bytes
+ */
+ public static final int FLAGS_F_LENGTH = 4;
+
+ /*
+ * Offsets inside flags field in bits;
+ */
+ public static final int I_FLAG_OFFSET = 29;
+ public static final int S_FLAG_OFFSET = 30;
+ public static final int U_FLAG_OFFSET = 31;
+
+ public static PCEStatefulCapabilityTlv deserializeValueField(byte[] valueBytes) throws PCEPDeserializerException {
+ if (valueBytes == null || valueBytes.length == 0)
+ throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+ if (valueBytes.length < FLAGS_F_LENGTH)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: >= " + FLAGS_F_LENGTH + ".");
+
+ final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(valueBytes, 0, FLAGS_F_LENGTH));
+ return new PCEStatefulCapabilityTlv(flags.get(I_FLAG_OFFSET), flags.get(U_FLAG_OFFSET), flags.get(S_FLAG_OFFSET));
+ }
+
+ public static byte[] serializeValueField(PCEStatefulCapabilityTlv objToSerialize) {
+ if (objToSerialize == null)
+ throw new IllegalArgumentException("PCEStatefulCapabilityTlv is mandatory.");
+
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+ flags.set(I_FLAG_OFFSET, objToSerialize.isInstantiated());
+ flags.set(U_FLAG_OFFSET, objToSerialize.isUpdate());
+ flags.set(S_FLAG_OFFSET, objToSerialize.isVersioned());
+
+ return ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.tlv;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv RSVPErrorSpecTlv}
+ * parameterized as IPv4Address
+ */
+public class RSVPErrorSpecIPv4TlvParser {
+
+ private static final int IP_F_LENGTH = 4;
+ private static final int FLAGS_F_LENGTH = 1;
+ private static final int ERROR_CODE_F_LENGTH = 1;
+ private static final int ERROR_VALUE_F_LENGTH = 2;
+
+ private static final int IP_F_OFFSET = 0;
+ private static final int FLAGS_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+ private static final int ERROR_CODE_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+ private static final int ERROR_VALUE_F_OFFSET = ERROR_CODE_F_OFFSET + ERROR_CODE_F_LENGTH;
+
+ private static final int SIZE = ERROR_VALUE_F_OFFSET + ERROR_VALUE_F_LENGTH;
+
+ /*
+ * flags offsets inside flags field in bits
+ */
+ private static final int IN_PLACE_FLAG_OFFSET = 7;
+ private static final int NOT_GUILTY_FLAGS_OFFSET = 6;
+
+ public static RSVPErrorSpecTlv<IPv4Address> parse(byte[] valueBytes) throws PCEPDeserializerException {
+ if (valueBytes == null || valueBytes.length == 0)
+ throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+ if (valueBytes.length != SIZE)
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: " + SIZE + ".");
+
+ final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(valueBytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+
+ return new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(
+ ByteArray.subByte(valueBytes, IP_F_OFFSET, IP_F_LENGTH)), flags.get(IN_PLACE_FLAG_OFFSET), flags.get(NOT_GUILTY_FLAGS_OFFSET),
+ valueBytes[ERROR_CODE_F_OFFSET] & 0xFF,
+ ByteArray.bytesToShort(ByteArray.subByte(valueBytes, ERROR_VALUE_F_OFFSET, ERROR_VALUE_F_LENGTH)) & 0xFFFF);
+ }
+
+ public static byte[] put(RSVPErrorSpecTlv<?> objToSerialize) {
+ if (objToSerialize == null)
+ throw new IllegalArgumentException("RSVPErrorSpecTlv is mandatory.");
+
+ if (!(((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress() instanceof IPv4Address))
+ throw new IllegalArgumentException("Unknown parametrized type of RSVPErrorSpecTlv. Passed "
+ + ((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress().getClass() + ". Needed IPv4Address.");
+
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+ flags.set(IN_PLACE_FLAG_OFFSET, objToSerialize.isInPlace());
+ flags.set(NOT_GUILTY_FLAGS_OFFSET, objToSerialize.isGuilty());
+
+ final byte[] retBytes = new byte[SIZE];
+
+ ByteArray.copyWhole(((IPv4Address) objToSerialize.getErrorNodeAddress()).getAddress(), retBytes, IP_F_OFFSET);
+ retBytes[ERROR_CODE_F_OFFSET] = ByteArray.intToBytes(objToSerialize.getErrorCode())[Integer.SIZE / Byte.SIZE - 1];
+ System.arraycopy(ByteArray.intToBytes(objToSerialize.getErrorValue()), Integer.SIZE / Byte.SIZE - ERROR_VALUE_F_LENGTH, retBytes, ERROR_VALUE_F_OFFSET,
+ ERROR_VALUE_F_LENGTH);
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.tlv;
+
+import java.util.BitSet;
+
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+/**
+ * Parser for {@link org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv RSVPErrorSpecTlv}
+ * parameterized as IPv6Address
+ */
+public class RSVPErrorSpecIPv6TlvParser {
+
+ private static final int IP_F_LENGTH = 16;
+ private static final int FLAGS_F_LENGTH = 1;
+ private static final int ERROR_CODE_F_LENGTH = 1;
+ private static final int ERROR_VALUE_F_LENGTH = 2;
+
+ private static final int IP_F_OFFSET = 0;
+ private static final int FLAGS_F_OFFSET = IP_F_OFFSET + IP_F_LENGTH;
+ private static final int ERROR_CODE_F_OFFSET = FLAGS_F_OFFSET + FLAGS_F_LENGTH;
+ private static final int ERROR_VALUE_F_OFFSET = ERROR_CODE_F_OFFSET + ERROR_CODE_F_LENGTH;
+
+ private static final int SIZE = ERROR_VALUE_F_OFFSET + ERROR_VALUE_F_LENGTH;
+
+ /*
+ * flags offsets inside flags field in bits
+ */
+ private static final int IN_PLACE_FLAG_OFFSET = 7;
+ private static final int NOT_GUILTY_FLAGS_OFFSET = 6;
+
+ public static RSVPErrorSpecTlv<IPv6Address> parse(byte[] valueBytes) throws PCEPDeserializerException {
+ if (valueBytes == null || valueBytes.length == 0)
+ throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
+ if (valueBytes.length != SIZE) {
+ throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + valueBytes.length + "; Expected: " + SIZE + ".");
+ }
+
+ final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(valueBytes, FLAGS_F_OFFSET, FLAGS_F_LENGTH));
+
+ return new RSVPErrorSpecTlv<IPv6Address>(new IPv6Address(
+ ByteArray.subByte(valueBytes, IP_F_OFFSET, IP_F_LENGTH)), flags.get(IN_PLACE_FLAG_OFFSET), flags.get(NOT_GUILTY_FLAGS_OFFSET),
+ valueBytes[ERROR_CODE_F_OFFSET] & 0xFF,
+ ByteArray.bytesToShort(ByteArray.subByte(valueBytes, ERROR_VALUE_F_OFFSET, ERROR_VALUE_F_LENGTH)) & 0xFFFF);
+ }
+
+ public static byte[] put(RSVPErrorSpecTlv<?> objToSerialize) {
+ if (objToSerialize == null)
+ throw new IllegalArgumentException("RSVPErrorSpecTlv is mandatory.");
+
+ if (!(((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress() instanceof IPv6Address))
+ throw new IllegalArgumentException("Unknown parametrized type of RSVPErrorSpecTlv. Passed "
+ + ((RSVPErrorSpecTlv<?>) objToSerialize).getErrorNodeAddress().getClass() + ". Needed IPv6Address.");
+
+ final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
+ flags.set(IN_PLACE_FLAG_OFFSET, objToSerialize.isInPlace());
+ flags.set(NOT_GUILTY_FLAGS_OFFSET, objToSerialize.isGuilty());
+
+ final byte[] retBytes = new byte[SIZE];
+
+ ByteArray.copyWhole(((IPv6Address) objToSerialize.getErrorNodeAddress()).getAddress(), retBytes, IP_F_OFFSET);
+ retBytes[ERROR_CODE_F_OFFSET] = ByteArray.intToBytes(objToSerialize.getErrorCode())[Integer.SIZE / Byte.SIZE - 1];
+ System.arraycopy(ByteArray.intToBytes(objToSerialize.getErrorValue()), Integer.SIZE / Byte.SIZE - ERROR_VALUE_F_LENGTH, retBytes, ERROR_VALUE_F_OFFSET,
+ ERROR_VALUE_F_LENGTH);
+ ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH), retBytes, FLAGS_F_OFFSET);
+
+ return retBytes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.CompositePathObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.CompositeRptPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.tlv.LSPCleanupTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+
+public class CompositeTest {
+
+ public PCEPExplicitRouteObject ero;
+ public PCEPClassTypeObject ct;
+ public PCEPLspaObject lspa;
+ public List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+ public PCEPIncludeRouteObject iro = new PCEPIncludeRouteObject(new ArrayList<ExplicitRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new EROAsNumberSubobject(new ASNumber(0L), true));
+ }
+ }, false, false);
+ public PCEPRequestParameterObject requestParameter;
+ public PCEPNoPathObject noPath;
+ public PCEPRequestedPathBandwidthObject bandwidth;
+
+ public List<PCEPRequestParameterObject> requestParameters = new ArrayList<PCEPRequestParameterObject>();
+ public PCEPErrorObject error;
+ public List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+
+ public PCEPNotificationObject notification;
+ public List<PCEPNotificationObject> notifications = new ArrayList<PCEPNotificationObject>();
+
+ private PCEPReportedRouteObject reportedRoute;
+ private PCEPExistingPathBandwidthObject rroBandwidth;
+ private PCEPIncludeRouteObject includeRoute;
+ private PCEPLoadBalancingObject loadBalancing;
+ private PCEPEndPointsObject<?> endPoints;
+
+ private PCEPLspObject lsp;
+ private final List<CompositePathObject> compositePaths = new ArrayList<CompositePathObject>();
+ private final List<CompositeRptPathObject> compositeRptPaths = new ArrayList<CompositeRptPathObject>();
+ private final List<CompositeUpdPathObject> compositeUpdPaths = new ArrayList<CompositeUpdPathObject>();
+ public PCEPReportedRouteObject rro = new PCEPReportedRouteObject(new ArrayList<ReportedRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new RROAsNumberSubobject(new ASNumber(0L)));
+ }
+ }, false);
+
+ @Before
+ public void setUp() {
+ this.ero = new PCEPExplicitRouteObject(new ArrayList<ExplicitRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new EROAsNumberSubobject(new ASNumber(0L), true));
+ }
+ }, false);
+ this.ct = new PCEPClassTypeObject((short) 5);
+ this.lspa = new PCEPLspaObject(0, 0, 0, (short) 0, (short) 0, false, false, false, false);
+ this.metrics.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+ this.metrics.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+
+ this.requestParameter = new PCEPRequestParameterObject(false, false, false, false, false, false, false, false, (short) 0, 0, false, false);
+ this.noPath = new PCEPNoPathObject((short) 2, false, false);
+ this.bandwidth = new PCEPRequestedPathBandwidthObject(new Bandwidth(0), false, false);
+
+ this.requestParameters.add(this.requestParameter);
+ this.requestParameters.add(this.requestParameter);
+
+ this.error = new PCEPErrorObject(PCEPErrors.BANDWIDTH_MISSING);
+
+ this.errors.add(this.error);
+ this.errors.add(this.error);
+ this.errors.add(this.error);
+
+ this.notification = new PCEPNotificationObject((short) 1, (short) 1);
+
+ this.notifications.add(this.notification);
+ this.notifications.add(this.notification);
+
+ final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>();
+ eroSubobjects.add(new EROAsNumberSubobject(new ASNumber(0x0L), false));
+ eroSubobjects.add(new EROAsNumberSubobject(new ASNumber(0x0L), false));
+ eroSubobjects.add(new EROAsNumberSubobject(new ASNumber(0x0L), false));
+
+ final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>();
+ rroSubobjects.add(new RROAsNumberSubobject(new ASNumber(0x0L)));
+ rroSubobjects.add(new RROAsNumberSubobject(new ASNumber(0x0L)));
+ rroSubobjects.add(new RROAsNumberSubobject(new ASNumber(0x0L)));
+
+ this.reportedRoute = new PCEPReportedRouteObject(rroSubobjects, true);
+ this.rroBandwidth = new PCEPExistingPathBandwidthObject(new Bandwidth(Float.intBitsToFloat(0xFF)), true, false);
+ this.includeRoute = new PCEPIncludeRouteObject(eroSubobjects, true, false);
+ this.loadBalancing = new PCEPLoadBalancingObject(0x0, new Bandwidth(Float.intBitsToFloat(0x0)), false);
+ final byte[] ipbytes = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ this.endPoints = new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipbytes), new IPv4Address(ipbytes));
+
+ this.lsp = new PCEPLspObject(0, false, false, true, true, null);
+ this.compositePaths.add(new CompositePathObject(new PCEPExplicitRouteObject(eroSubobjects, true), this.lspa, this.bandwidth, this.metrics,
+ this.includeRoute));
+ this.compositePaths.add(new CompositePathObject(new PCEPExplicitRouteObject(eroSubobjects, true)));
+
+ this.compositeUpdPaths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(eroSubobjects, true), this.lspa, this.bandwidth, this.metrics));
+ this.compositeUpdPaths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(eroSubobjects, true)));
+
+ }
+
+ @Test
+ public void testCompositePathObject() {
+ final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+ objects.add(this.ero);
+ objects.add(this.lspa);
+ objects.add(this.metrics.get(0));
+ objects.add(this.metrics.get(1));
+ objects.add(this.iro);
+ objects.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+ final CompositePathObject path = CompositePathObject.getCompositeFromList(objects);
+ assertEquals(path.getExcludedRoute(), this.ero);
+ assertEquals(path.getLspa(), this.lspa);
+ assertNull(path.getBandwidth());
+ assertEquals(path.getMetrics().get(0), this.metrics.get(0));
+ assertEquals(path.getMetrics().get(1), this.metrics.get(1));
+ assertEquals(path.getIncludeRoute(), this.iro);
+ }
+
+ @Test
+ public void testCompositeRptPathObject() {
+ final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+ objects.add(this.ero);
+ objects.add(this.lspa);
+ objects.add(this.rro);
+ objects.add(this.metrics.get(0));
+ objects.add(this.metrics.get(1));
+ objects.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+ final CompositeRptPathObject path = CompositeRptPathObject.getCompositeFromList(objects);
+ assertEquals(path.getExcludedRoute(), this.ero);
+ assertEquals(path.getLspa(), this.lspa);
+ assertNull(path.getBandwidth());
+ assertEquals(path.getMetrics().get(0), this.metrics.get(0));
+ assertEquals(path.getMetrics().get(1), this.metrics.get(1));
+ assertEquals(path.getReportedRoute(), this.rro);
+ }
+
+ @Test
+ public void testCompositeResponseObject() {
+ final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+ objects.add(this.requestParameter);
+ objects.add(this.noPath);
+ objects.add(this.bandwidth);
+ objects.add(this.metrics.get(0));
+ objects.add(this.metrics.get(1));
+ objects.add(this.iro);
+ // add one path
+ objects.add(this.ero);
+ objects.add(this.lspa);
+ objects.add(this.metrics.get(0));
+ objects.add(this.metrics.get(1));
+ objects.add(this.iro);
+ // add another path
+ objects.add(this.ero);
+ objects.add(this.lspa);
+ objects.add(this.metrics.get(0));
+ objects.add(new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+ objects.add(this.iro);
+ //
+ objects.add(this.requestParameter);
+ final List<CompositeResponseObject> list = new ArrayList<CompositeResponseObject>();
+ while (!objects.isEmpty()) {
+ list.add(CompositeResponseObject.getCompositeFromList(objects));
+ }
+ assertEquals(2, list.size());
+ final CompositeResponseObject response = list.get(0);
+
+ assertEquals(response.getRequestParameter(), this.requestParameter);
+ assertEquals(response.getNoPath(), this.noPath);
+ assertNull(response.getLspa());
+ assertEquals(response.getBandwidth(), this.bandwidth);
+ assertEquals(response.getMetrics().get(0), this.metrics.get(0));
+ assertEquals(response.getMetrics().get(1), this.metrics.get(1));
+ assertEquals(response.getIncludeRoute(), this.iro);
+ // check path
+ CompositePathObject path = response.getPaths().get(0);
+ assertEquals(path.getExcludedRoute(), this.ero);
+ assertEquals(path.getLspa(), this.lspa);
+ assertNull(path.getBandwidth());
+ assertEquals(path.getMetrics().get(0), this.metrics.get(0));
+ assertEquals(path.getMetrics().get(1), this.metrics.get(1));
+ assertEquals(path.getIncludeRoute(), this.iro);
+ // check path
+ path = response.getPaths().get(1);
+ assertEquals(path.getExcludedRoute(), this.ero);
+ assertEquals(path.getLspa(), this.lspa);
+ assertNull(path.getBandwidth());
+ assertEquals(path.getMetrics().get(0), this.metrics.get(0));
+ assertEquals(path.getMetrics().get(1), new PCEPMetricObject(false, false, new TEMetric(1000), false, false));
+ assertEquals(path.getIncludeRoute(), this.iro);
+ }
+
+ @Test
+ public void testCompositeErrorObject() {
+ final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+ CompositeErrorObject compositeErrors;
+
+ objects.addAll(this.requestParameters);
+ objects.addAll(this.errors);
+ compositeErrors = new CompositeErrorObject(this.requestParameters.subList(0, this.requestParameters.size()), this.errors.subList(0, this.errors.size()));
+ assertEquals(compositeErrors, CompositeErrorObject.getCompositeFromList(objects));
+
+ objects.clear();
+ objects.addAll(this.errors);
+ compositeErrors = new CompositeErrorObject(null, this.errors.subList(0, this.errors.size()));
+ assertEquals(compositeErrors, CompositeErrorObject.getCompositeFromList(objects));
+
+ }
+
+ @Test
+ public void testCompositeNotifyObject() {
+ final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+ CompositeNotifyObject compositeNotifications;
+
+ objects.addAll(this.requestParameters);
+ objects.addAll(this.notifications);
+ compositeNotifications = new CompositeNotifyObject(this.requestParameters.subList(0, this.requestParameters.size()), this.notifications.subList(0,
+ this.notifications.size()));
+ assertEquals(compositeNotifications, CompositeNotifyObject.getCompositeFromList(objects));
+
+ objects.clear();
+ // first
+ objects.addAll(this.requestParameters);
+ objects.addAll(this.notifications);
+ // second
+ objects.addAll(this.requestParameters);
+ objects.addAll(this.notifications);
+ while (!objects.isEmpty()) {
+ assertEquals(compositeNotifications, CompositeNotifyObject.getCompositeFromList(objects));
+ }
+
+ objects.clear();
+ objects.addAll(this.notifications);
+ compositeNotifications = new CompositeNotifyObject(null, this.notifications.subList(0, this.notifications.size()));
+ assertEquals(compositeNotifications, CompositeNotifyObject.getCompositeFromList(objects));
+
+ }
+
+ @Test
+ public void testCompositeRequestObject() {
+ final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+ CompositeRequestObject compositeRequest;
+
+ objects.add(this.requestParameter);
+ objects.add(this.endPoints);
+ objects.add(this.ct);
+ objects.add(this.lsp);
+ objects.add(this.lspa);
+ objects.add(this.bandwidth);
+ objects.addAll(this.metrics);
+ objects.add(this.reportedRoute);
+ objects.add(this.rroBandwidth);
+ objects.add(this.includeRoute);
+ objects.add(this.loadBalancing);
+
+ compositeRequest = new CompositeRequestObject(this.requestParameter, this.endPoints, this.ct, this.lsp, this.lspa, this.bandwidth,
+ this.metrics.subList(0, this.metrics.size()), this.reportedRoute, this.rroBandwidth, this.includeRoute, this.loadBalancing);
+ assertEquals(compositeRequest, CompositeRequestObject.getCompositeFromList(objects));
+
+ objects.clear();
+ // first
+ objects.add(this.requestParameter);
+ objects.add(this.endPoints);
+ objects.add(this.ct);
+ objects.add(this.lsp);
+ objects.add(this.lspa);
+ objects.add(this.bandwidth);
+ objects.addAll(this.metrics);
+ objects.add(this.reportedRoute);
+ objects.add(this.rroBandwidth);
+ objects.add(this.includeRoute);
+ objects.add(this.loadBalancing);
+ // second
+ objects.add(this.requestParameter);
+ objects.add(this.endPoints);
+ objects.add(this.ct);
+ objects.add(this.lsp);
+ objects.add(this.lspa);
+ objects.add(this.bandwidth);
+ objects.addAll(this.metrics);
+ objects.add(this.reportedRoute);
+ objects.add(this.rroBandwidth);
+ objects.add(this.includeRoute);
+ objects.add(this.loadBalancing);
+ while (!objects.isEmpty()) {
+ assertEquals(compositeRequest, CompositeRequestObject.getCompositeFromList(objects));
+ }
+
+ objects.clear();
+ objects.add(this.requestParameter);
+ objects.add(this.endPoints);
+ compositeRequest = new CompositeRequestObject(this.requestParameter, this.endPoints);
+ assertEquals(compositeRequest, CompositeRequestObject.getCompositeFromList(objects));
+
+ }
+
+ @Test
+ public void testCompositeStateReportObject() {
+ final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+ CompositeStateReportObject compositeStateReport;
+
+ objects.add(this.lsp);
+ for (final CompositeRptPathObject compositeRptPath : this.compositeRptPaths) {
+ objects.addAll(compositeRptPath.getCompositeAsList());
+ }
+
+ compositeStateReport = new CompositeStateReportObject(this.lsp, this.compositeRptPaths);
+ assertEquals(compositeStateReport, CompositeStateReportObject.getCompositeFromList(objects));
+
+ objects.clear();
+ // first
+ objects.add(this.lsp);
+ for (final CompositeRptPathObject compositeRptPath : this.compositeRptPaths) {
+ objects.addAll(compositeRptPath.getCompositeAsList());
+ }
+ // second
+ objects.add(this.lsp);
+ for (final CompositeRptPathObject compositeRptPath : this.compositeRptPaths) {
+ objects.addAll(compositeRptPath.getCompositeAsList());
+ }
+ while (!objects.isEmpty()) {
+ assertEquals(compositeStateReport, CompositeStateReportObject.getCompositeFromList(objects));
+ }
+
+ objects.clear();
+ objects.add(this.lsp);
+ for (final CompositeRptPathObject compositeRptPath : this.compositeRptPaths) {
+ objects.addAll(compositeRptPath.getCompositeAsList());
+ }
+ compositeStateReport = new CompositeStateReportObject(this.lsp, this.compositeRptPaths);
+ assertEquals(compositeStateReport, CompositeStateReportObject.getCompositeFromList(objects));
+
+ }
+
+ @Test
+ public void testCompositeUpdateRequestObject() {
+ final List<PCEPObject> objects = new ArrayList<PCEPObject>();
+ CompositeUpdateRequestObject compositeStateReport;
+
+ objects.add(this.lsp);
+ for (final CompositeUpdPathObject compositePath : this.compositeUpdPaths) {
+ objects.addAll(compositePath.getCompositeAsList());
+ }
+
+ compositeStateReport = new CompositeUpdateRequestObject(this.lsp, this.compositeUpdPaths);
+ assertEquals(compositeStateReport, CompositeUpdateRequestObject.getCompositeFromList(objects));
+
+ objects.clear();
+ // first
+ objects.add(this.lsp);
+ for (final CompositeUpdPathObject compositePath : this.compositeUpdPaths) {
+ objects.addAll(compositePath.getCompositeAsList());
+ }
+ // second
+ objects.add(this.lsp);
+ for (final CompositeUpdPathObject compositePath : this.compositeUpdPaths) {
+ objects.addAll(compositePath.getCompositeAsList());
+ }
+ while (!objects.isEmpty()) {
+ assertEquals(compositeStateReport, CompositeUpdateRequestObject.getCompositeFromList(objects));
+ }
+
+ objects.clear();
+ objects.add(this.lsp);
+ for (final CompositeUpdPathObject compositePath : this.compositeUpdPaths) {
+ objects.addAll(compositePath.getCompositeAsList());
+ }
+ compositeStateReport = new CompositeUpdateRequestObject(this.lsp, this.compositeUpdPaths);
+ assertEquals(compositeStateReport, CompositeUpdateRequestObject.getCompositeFromList(objects));
+
+ }
+
+ @SuppressWarnings("resource")
+ @Test
+ public void testSessionProposalCheckerFactory() {
+ assertTrue(new PCEPSessionProposalCheckerFactoryImpl().getPreferencesChecker(null).checkSessionCharacteristics(null));
+ assertEquals(new PCEPSessionPreferences(new PCEPOpenObject(30, 120, 0, null)), new PCEPSessionProposalCheckerFactoryImpl().getPreferencesChecker(null).getNewProposal(null));
+ }
+
+ @Test
+ public void testSessionProposalFactory() throws IOException {
+ final PCEPSessionProposalFactoryImpl spf = new PCEPSessionProposalFactoryImpl(10, 2, true, false, true, true, 5);
+ try {
+ final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+ tlvs.add(new PCEStatefulCapabilityTlv(true, false, true));
+ tlvs.add(new LSPCleanupTlv(5));
+ assertEquals(new PCEPSessionPreferences(new PCEPOpenObject(2, 10, 0, tlvs)), spf.getSessionProposal(null, 0).getProposal());
+ } finally {
+ spf.close();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class FiniteStateMachineTest {
+
+ private ServerSessionMock serverSession;
+
+ private final SimpleSessionListener serverListener = new SimpleSessionListener();
+
+ private MockPCE client;
+
+ @Before
+ public void setUp() {
+ this.client = new MockPCE();
+ this.serverSession = new ServerSessionMock(this.serverListener, this.client);
+ this.client.addSession(this.serverSession);
+ }
+
+ /**
+ * Both PCEs accept session characteristics. Also tests KeepAliveTimer and
+ * error message and when pce attempts to establish pce session for the 2nd
+ * time.
+ *
+ * @throws InterruptedException
+ */
+ @Test
+ public void testSessionCharsAccBoth() throws InterruptedException {
+ this.serverSession.startSession();
+ assertEquals(1, this.client.getListMsg().size());
+ assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+ this.client.sendMessage(new PCEPOpenMessage(new PCEPOpenObject(3, 9, 2)));
+ assertEquals(2, this.client.getListMsg().size());
+ assertTrue(this.client.getListMsg().get(1) instanceof PCEPKeepAliveMessage);
+ this.client.sendMessage(new PCEPKeepAliveMessage());
+ synchronized (this.serverListener) {
+ while (!this.serverListener.up)
+ try {
+ this.serverListener.wait();
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ assertTrue(this.serverListener.up);
+// Thread.sleep(PCEPSessionImpl.KEEP_ALIVE_TIMER_VALUE * 1000);
+// assertEquals(3, this.client.getListMsg().size());
+// assertTrue(this.client.getListMsg().get(2) instanceof PCEPKeepAliveMessage); // test of keepalive timer
+ this.client.sendMessage(new PCEPOpenMessage(new PCEPOpenObject(1, 1, 1)));
+ assertEquals(3, this.client.getListMsg().size());
+ assertTrue(this.client.getListMsg().get(2) instanceof PCEPErrorMessage);
+ for (final PCEPMessage m : this.client.getListMsg()) {
+ if (m instanceof PCEPErrorMessage) {
+ final PCEPErrorObject obj = ((PCEPErrorMessage) m).getErrorObjects().get(0);
+ assertEquals(PCEPErrors.ATTEMPT_2ND_SESSION, obj.getError()); // test of error type 9
+ }
+ }
+ }
+
+ /**
+ * Mock PCE does not accept session characteristics the first time.
+ *
+ * @throws InterruptedException
+ */
+ @Test
+ public void testSessionCharsAccMe() throws InterruptedException {
+ this.serverSession.startSession();
+ this.client.sendMessage(new PCEPOpenMessage(new PCEPOpenObject(4, 9, 2)));
+ assertEquals(2, this.client.getListMsg().size());
+ assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+ assertTrue(this.client.getListMsg().get(1) instanceof PCEPKeepAliveMessage);
+ this.client.sendErrorMessage(PCEPErrors.NON_ACC_NEG_SESSION_CHAR, new PCEPOpenObject(3, 7, 2, null));
+ assertEquals(3, this.client.getListMsg().size());
+ assertTrue(this.client.getListMsg().get(2) instanceof PCEPOpenMessage);
+ this.client.sendMessage(new PCEPKeepAliveMessage());
+ synchronized (this.serverListener) {
+ while (!this.serverListener.up)
+ try {
+ this.serverListener.wait();
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ assertTrue(this.serverListener.up);
+ }
+
+ /**
+ * Sending different PCEP Message than Open in session establishment phase.
+ *
+ * @throws InterruptedException
+ */
+ @Test
+ public void testErrorOneOne() throws InterruptedException {
+ this.serverSession.startSession();
+ assertEquals(1, this.client.getListMsg().size());
+ assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+ this.client.sendMessage(new PCEPNotificationMessage(new ArrayList<CompositeNotifyObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositeNotifyObject(new ArrayList<PCEPNotificationObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPNotificationObject((short) 1, (short) 1));
+ }
+ }));
+ }
+ }));
+ for (final PCEPMessage m : this.client.getListMsg()) {
+ if (m instanceof PCEPErrorMessage) {
+ final PCEPErrorObject obj = ((PCEPErrorMessage) m).getErrorObjects().get(0);
+ assertEquals(PCEPErrors.NON_OR_INVALID_OPEN_MSG, obj.getError());
+ }
+ }
+ }
+
+ /************* Tests commented because of their long duration (tested timers) **************/
+
+ /**
+ * OpenWait timer expired.
+ *
+ * @throws InterruptedException
+ */
+ @Test
+ @Ignore
+ public void testErrorOneTwo() throws InterruptedException {
+ this.serverSession.startSession();
+ assertEquals(1, this.client.getListMsg().size());
+ assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+ Thread.sleep(PCEPSessionImpl.OPEN_WAIT_TIMER_VALUE * 1000);
+ for (final PCEPMessage m : this.client.getListMsg()) {
+ if (m instanceof PCEPErrorMessage) {
+ final PCEPErrorObject obj = ((PCEPErrorMessage) m).getErrorObjects().get(0);
+ assertEquals(PCEPErrors.NO_OPEN_BEFORE_EXP_OPENWAIT, obj.getError());
+ }
+ }
+ }
+
+ /**
+ * KeepWaitTimer expired.
+ *
+ * @throws InterruptedException
+ */
+ @Test
+ @Ignore
+ public void testErrorOneSeven() throws InterruptedException {
+ this.serverSession.startSession();
+ assertEquals(1, this.client.getListMsg().size());
+ assertTrue(this.client.getListMsg().get(0) instanceof PCEPOpenMessage);
+ this.client.sendMessage(new PCEPOpenMessage(new PCEPOpenObject(3, 9, 2)));
+ Thread.sleep(PCEPSessionImpl.KEEP_WAIT_TIMER_VALUE * 1000);
+ for (final PCEPMessage m : this.client.getListMsg()) {
+ if (m instanceof PCEPErrorMessage) {
+ final PCEPErrorObject obj = ((PCEPErrorMessage) m).getErrorObjects().get(0);
+ assertEquals(PCEPErrors.NO_MSG_BEFORE_EXP_KEEPWAIT, obj.getError());
+ }
+ }
+ }
+
+ @Test
+ @Ignore
+ public void testUnknownMessage() throws InterruptedException {
+ this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+ assertEquals(1, this.serverSession.unknownMessagesTimes.size());
+ Thread.sleep(10000);
+ this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+ assertEquals(2, this.serverSession.unknownMessagesTimes.size());
+ Thread.sleep(10000);
+ this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+ assertEquals(3, this.serverSession.unknownMessagesTimes.size());
+ Thread.sleep(20000);
+ this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+ assertEquals(4, this.serverSession.unknownMessagesTimes.size());
+ Thread.sleep(30000);
+ this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+ assertEquals(3, this.serverSession.unknownMessagesTimes.size());
+ Thread.sleep(10000);
+ this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+ assertEquals(3, this.serverSession.unknownMessagesTimes.size());
+ Thread.sleep(5000);
+ this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+ assertEquals(4, this.serverSession.unknownMessagesTimes.size());
+ Thread.sleep(1000);
+ this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+ assertEquals(5, this.serverSession.unknownMessagesTimes.size());
+ Thread.sleep(1000);
+ this.serverSession.handleMalformedMessage(PCEPErrors.CAPABILITY_NOT_SUPPORTED);
+ synchronized (this.client) {
+ while (!this.client.down)
+ try {
+ this.client.wait();
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ assertTrue(this.client.down);
+ }
+
+ @After
+ public void tearDown() {
+ this.serverSession.close();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.io.IOException;
+
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.SessionParent;
+
+/**
+ *
+ */
+public class MockDispatcher implements SessionParent {
+
+ @Override
+ public void onSessionClosed(ProtocolSession session) {
+
+ }
+
+ @Override
+ public void checkOutputBuffer(ProtocolSession session) {
+
+ }
+
+ @Override
+ public void close() throws IOException {
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ *
+ */
+public class MockPCE extends PCEPSessionListener {
+
+ private final List<PCEPMessage> listMsg = new ArrayList<PCEPMessage>();
+
+ private PCEPSessionImpl session = null;
+
+ public boolean up = false;
+
+ private static final Logger logger = LoggerFactory.getLogger(MockPCE.class);
+
+ public boolean down = false;
+
+ public MockPCE() {
+ }
+
+ public void sendMessage(PCEPMessage msg) {
+ this.session.handleMessage(msg);
+ }
+
+ public void sendErrorMessage(PCEPErrors value,
+ PCEPOpenObject open) {
+ final PCEPErrorObject error = new PCEPErrorObject(value);
+ final List<PCEPErrorObject> errors = new ArrayList<PCEPErrorObject>();
+ errors.add(error);
+ this.sendMessage(new PCEPErrorMessage(open, errors, null));
+ }
+
+ public List<PCEPMessage> getListMsg() {
+ return this.listMsg;
+ }
+
+ public void addSession(PCEPSessionImpl l) {
+ this.session = l;
+ }
+
+ @Override
+ public void onMessage(PCEPSession session, PCEPMessage message) {
+ this.listMsg.add(message);
+ logger.debug("Message received:" + message);
+ }
+
+ @Override
+ public void onSessionUp(PCEPSession session, PCEPOpenObject local,
+ PCEPOpenObject remote) {
+ logger.debug("Session Up");
+ this.up = true;
+ this.notifyAll();
+ }
+
+ @Override
+ public void onSessionDown(PCEPSession session, PCEPCloseObject reason, Exception e) {
+ logger.debug("Session Down");
+ this.down = true;
+ //this.notifyAll();
+ }
+
+ @Override
+ public void onSessionTerminated(PCEPSession session,
+ TerminationReason cause) {
+ logger.debug("Session terminated. Cause : " + cause.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.impl.object.PCEPClassTypeObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPErrorObjectParser;
+import org.opendaylight.protocol.pcep.impl.object.PCEPErrorObjectParser.PCEPErrorIdentifier;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.object.PCEPBranchNodeListObject;
+import org.opendaylight.protocol.pcep.object.PCEPClassTypeObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNonBranchNodeListObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPSecondaryRecordRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.pcep.object.PCEPUnreachedDestinationObject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import org.opendaylight.protocol.pcep.tlv.OverloadedDurationTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+
+/**
+ * Used resources<br/>
+ * <br/>
+ * PCEPOpenObject3.bin<br/>
+ * objClass: 1<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * keepAlive: 30<br/>
+ * deadTimer: 120<br/>
+ * sessionId: 1<br/>
+ * tlvs:NO<br/>
+ * <br/>
+ * PCEPBandwidthObject1LowerBounds.bin<br/>
+ * objClass: 5 <br/>
+ * objType: 1<br/>
+ * objLength: 16<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Bandwidth: 0<br/>
+ * <br/>
+ * PCEPBandwidthObject2UpperBounds.bin<br/>
+ * objClass: 5 <br/>
+ * objType: 1<br/>
+ * objLength: 16<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Bandwidth: 0xFFFFFFFF<br/>
+ * <br/>
+ * PCEPEndPointsObject1IPv4.bin<br/>
+ * objClass: 4 <br/>
+ * objType: 1<br/>
+ * objLength: 12<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * src IP: 0xA2F5110E <br/>
+ * dest IP: 0xFFFFFFFF <br/>
+ * <br/>
+ * PCEPEndPointsObject2IPv6.bin<br/>
+ * objClass: 4 <br/>
+ * objType: 2<br/>
+ * objLength: 36<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * src IP: 0xFFFFFFFFF FFFFFFFFF FFFFFFFFF FFFFFFFFF<br/>
+ * dest IP: 0x00025DD2 FFECA1B6 581E9F50 00000000 <br/>
+ * <br/>
+ * PCEPErrorObject1.bin<br/>
+ * objClass: 13 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Error-type: 1<br/>
+ * Error-value: 1<br/>
+ * Tlvs: NO<br/>
+ * <br/>
+ * PCEPErrorObject2Invalid.bin<br/>
+ * objClass: 13 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Error-type: 3<br/>
+ * Error-value: 0<br/>
+ * Tlvs: NO<br/>
+ * <br/>
+ * PCEPErrorObject3.bin<br/>
+ * objClass: 13 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Error-type: 2<br/>
+ * Error-value: 0<br/>
+ * Tlvs: NO<br/>
+ * <br/>
+ * PCEPLspaObject1LowerBounds.bin<br/>
+ * objClass: 9<br/>
+ * objType: 1<br/>
+ * objLength: 20<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Exclude-any: 0x00000000L<br/>
+ * Include-any: 0x00000000L<br/>
+ * Include-all: 0x00000000L<br/>
+ * Setup Prio: 0x00<br/>
+ * Holding Prio: 0x00<br/>
+ * Flags: - L : false<br/>
+ * <br/>
+ * PCEPLspaObject2UpperBounds.bin<br/>
+ * objClass: 9<br/>
+ * objType: 1<br/>
+ * objLength: 20<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Exclude-any: 0xFFFFFFFFL<br/>
+ * Include-any: 0xFFFFFFFFL<br/>
+ * Include-all: 0xFFFFFFFFL<br/>
+ * Setup Prio: 0xFF<br/>
+ * Holding Prio: 0xFF<br/>
+ * Flags: - L : true<br/>
+ * <br/>
+ * PCEPLspaObject3RandVals.bin<br/>
+ * objClass: 9<br/>
+ * objType: 1<br/>
+ * objLength: 20<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Exclude-any: 0x20A1FEE3L<br/>
+ * Include-any: 0x1A025CC7L<br/>
+ * Include-all: 0x2BB66532L<br/>
+ * Setup Prio: 0x03<br/>
+ * Holding Prio: 0x02<br/>
+ * Flags: - L : true<br/>
+ * <br/>
+ * NoPathObject1WithTLV.bin<br/>
+ * objClass: 3 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 16<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Nature of Issue: 2<br/>
+ * No-Path flags:<br/>
+ * - C: true<br/>
+ * <br/>
+ * tlvs:<br/>
+ * -- NO-PATH-VECTOR<br/>
+ * - flags (0x4000):<br/>
+ * - PCE currently unavailable: false<br/>
+ * - unknown destination: true<br/>
+ * - unknown source: false<br/>
+ *
+ * <br/>
+ * NoPathObject2WithoutTLV.bin<br/>
+ * objClass: 3 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: true<br/>
+ * <br/>
+ * Nature of Issue: 16<br/>
+ * No-Path flags:<br/>
+ * - C: false<br/>
+ * <br/>
+ * tlvs:NO<br/>
+ * <br/>
+ * PCEPNotificationObject1WithTlv.bin <br/>
+ * objClass: 12<br/>
+ * objType: 1<br/>
+ * objLength: 16<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * NT: 1<br/>
+ * NV: 1<br/>
+ * Tlvs:<br/>
+ * - OverloaderDuration(0xFF0000A2L)<br/>
+ * <br/>
+ * PCEPNotificationObject2WithoutTlv.bin <br/>
+ * objClass: 12<br/>
+ * objType: 1<br/>
+ * objLength: 8<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * NT: 0xFF<br/>
+ * NV: 0xFF<br/>
+ * Tlvs: NO<br/>
+ * <br/>
+ * PCEPOpenObject1.bin<br/>
+ * objClass: 1<br/>
+ * objType: 1<br/>
+ * objLength: 28<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * keepAlive: 30<br/>
+ * deadTimer: 120<br/>
+ * sessionId: 1<br/>
+ * tlvs:<br/>
+ * - PCEPStatefulCapability<br/>
+ * - LSPStateDBVersionTlv<br/>
+ * - NodeIdentifierTlv<br/>
+ * <br/>
+ * PCEPOpenObject2UpperBoundsNoTlv.bin<br/>
+ * objClass: 1<br/>
+ * objType: 1<br/>
+ * objLength: 34<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * keepAlive: 0xFF<br/>
+ * deadTimer: 0xFF<br/>
+ * sessionId: 0xFF<br/>
+ * tlvs: NO<br/>
+ * <br/>
+ * PCEPRPObject1.bin<br/>
+ * objClass: 2 (RP)<br/>
+ * objType: 1<br/>
+ * objLength: 12<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * RP flags:<br/>
+ * - loose/strict: true<br/>
+ * - Bi-directional: false<br/>
+ * - Reoptimization: false<br/>
+ * - Priority: 5<br/>
+ * Request ID: 0xDEADBEEF<br/>
+ * tlvs: NO<br/>
+ * <br/>
+ * PCEPSvecObject1_10ReqIDs.bin <br/>
+ * objClass: 11<br/>
+ * objType: 1<br/>
+ * objLength: 48<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: true<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Flags:<br/>
+ * - Link diverse: true<br/>
+ * - Node diverse: false<br/>
+ * - SRLG diverse: true<br/>
+ * Reques-ID-numbers:<br/>
+ * #1 - 0xFFFFFFFFL<br/>
+ * #2 - 0x00000000L<br/>
+ * #3 - 0x01234567L<br/>
+ * #4 - 0x89ABCDEFL<br/>
+ * #5 - 0xFEDCBA98L<br/>
+ * #6 - 0x76543210L<br/>
+ * #7 - 0x15825266L<br/>
+ * #8 - 0x48120BBEL<br/>
+ * #9 - 0x25FB7E52L<br/>
+ * #10 - 0xB2F2546BL<br/>
+ * <br/>
+ * PCEPSvecObject2.bin <br/>
+ * objClass: 11<br/>
+ * objType: 1<br/>
+ * objLength: 08<br/>
+ * version: 1<br/>
+ * Flags:<br/>
+ * - processing: false<br/>
+ * - ignored: false<br/>
+ * <br/>
+ * Flags:<br/>
+ * - Link diverse: false<br/>
+ * - Node diverse: false<br/>
+ * - SRLG diverse: false<br/>
+ * Reques-ID-numbers:<br/>
+ * #1 - 0x000000FFL<br/>
+ * PCEPExcludeRouteObject.1.bin <br/>
+ * objClass: 17 <br/>
+ * objType: 1 <br/>
+ * objLength: 20 <br/>
+ * version: 1 <br/>
+ * Flags: <br/>
+ * - fail: true <br/>
+ * Subobjects: <br/>
+ * - XROIPv4PreffixSubobject(192.168.0.0/16, exclude, node) <br/>
+ * - XROASnumber(0x1234) <br/>
+ */
+
+public class PCEPObjectParserTest {
+
+ IPv4Address ipv4addr = new IPv4Address(new byte[] { (byte) 192, (byte) 168, 1, 8 });
+
+ IPv6Address ipv6addr = new IPv6Address(new byte[] { (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168,
+ 2, 1, (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1 });
+
+ @SuppressWarnings("unchecked")
+ private static <T extends PCEPObject> void serDeserTest(final String srcFile, final T specObject) throws IOException,
+ PCEPDeserializerException, PCEPDocumentedException {
+ final byte[] bytesFromFile = ByteArray.fileToBytes(srcFile);
+ final T deserSpecObj = (T) PCEPObjectFactory.parseObjects(bytesFromFile).get(0);
+ final byte[] serSpecObj = PCEPObjectFactory.put(Arrays.asList((PCEPObject) specObject));
+
+ assertEquals(specObject, deserSpecObj);
+ assertArrayEquals(bytesFromFile, serSpecObj);
+ }
+
+ /**
+ * Standard serialization test<br/>
+ * Used resources:<br/>
+ * - PCEPOpenObject1.bin<br/>
+ *
+ * @throws PCEPDeserializerException
+ * @throws IOException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ @Ignore //FIXME: temporary
+ public void testObjectDeserialization() throws PCEPDeserializerException, IOException,
+ PCEPDocumentedException {
+ PCEPObjectFactory.parseObjects(ByteArray.fileToBytes("src/test/resources/PCEPOpenObject1.bin"));
+ }
+
+ @Test
+ public void testUnknownClass() throws PCEPDeserializerException, IOException, PCEPDocumentedException {
+
+ final PCEPObject obj = PCEPObjectFactory.parseObjects(
+ ByteArray.fileToBytes("src/test/resources/PCEPObject1UnknownClass.bin")).get(0);
+
+ assertTrue(obj instanceof UnknownObject);
+ assertEquals(((UnknownObject) obj).getError(), PCEPErrors.UNRECOGNIZED_OBJ_CLASS);
+ }
+
+ @Test
+ public void testUnknownType() throws PCEPDeserializerException, IOException, PCEPDocumentedException {
+ final PCEPObject obj = PCEPObjectFactory.parseObjects(
+ ByteArray.fileToBytes("src/test/resources/PCEPObject2UnknownType.bin")).get(0);
+
+ assertTrue(obj instanceof UnknownObject);
+ assertEquals(((UnknownObject) obj).getError(), PCEPErrors.UNRECOGNIZED_OBJ_TYPE);
+ }
+
+ @Test
+ public void testCloseObjSerDeser() throws IOException, PCEPDeserializerException, PCEPDocumentedException {
+ serDeserTest("src/test/resources/PCEPCloseObject1.bin", new PCEPCloseObject(
+ Reason.TOO_MANY_UNKNOWN_MSG));
+ }
+
+ @Test
+ public void testLoadBalancingObjSerDeser() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ serDeserTest("src/test/resources/PCEPLoadBalancingObject1.bin", new PCEPLoadBalancingObject(0xF1,
+ new Bandwidth(Float.intBitsToFloat(0xFFFFFFFF)), true));
+ }
+
+ @Test
+ public void testLspObjectSerDeser() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ serDeserTest("src/test/resources/PCEPLspObject1NoTlvsUpperBounds.bin", new PCEPLspObject(0xFFFFF,
+ true, false, true, false, null));
+ }
+
+ @Test
+ public void testERObjectSerDeser() throws IOException, PCEPDeserializerException, PCEPDocumentedException {
+ final byte[] bytesFromFile = ByteArray
+ .fileToBytes("src/test/resources/PCEPExplicitRouteObject1PackOfSubobjects.bin");
+
+ final PCEPExplicitRouteObject specObj = (PCEPExplicitRouteObject) PCEPObjectFactory.parseObjects(
+ bytesFromFile).get(0);
+
+ assertEquals(8, specObj.getSubobjects().size());
+
+ final byte[] bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) specObj));
+ assertArrayEquals(bytesFromFile, bytesActual);
+ }
+
+ @Test
+ public void testIRObjectSerDeser() throws IOException, PCEPDeserializerException, PCEPDocumentedException {
+ final byte[] bytesFromFile = ByteArray
+ .fileToBytes("src/test/resources/PCEPIncludeRouteObject1PackOfSubobjects.bin");
+
+ final PCEPIncludeRouteObject specObj = (PCEPIncludeRouteObject) PCEPObjectFactory.parseObjects(
+ bytesFromFile).get(0);
+
+ assertEquals(8, specObj.getSubobjects().size());
+
+ final byte[] bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) specObj));
+ assertArrayEquals(bytesFromFile, bytesActual);
+ }
+
+ @Test
+ public void tesRRObjectSerDeser() throws IOException, PCEPDeserializerException, PCEPDocumentedException {
+ final byte[] bytesFromFile = ByteArray
+ .fileToBytes("src/test/resources/PCEPReportedRouteObject1PackOfSubobjects.bin");
+
+ final PCEPReportedRouteObject specObj = (PCEPReportedRouteObject) PCEPObjectFactory.parseObjects(
+ bytesFromFile).get(0);
+
+ assertEquals(6, specObj.getSubobjects().size());
+
+ final byte[] bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) specObj));
+ assertArrayEquals(bytesFromFile, bytesActual);
+ }
+
+ /**
+ * Test for upper/lower bounds (Serialization/Deserialization)<br/>
+ * Used resources:<br/>
+ * - PCEPBandwidthObject2UpperBounds.bin<br/>
+ * - PCEPBandwidthObject1LowerBounds.bin<br/>
+ *
+ * @throws IOException
+ * @throws PCEPDeserializerException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testBandwidthObjectBounds() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ final byte[] bytesFloat = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ serDeserTest("src/test/resources/PCEPBandwidthObject2UpperBounds.bin",
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(ByteArray.bytesToFloat(bytesFloat)), true,
+ true));
+ serDeserTest("src/test/resources/PCEPBandwidthObject1LowerBounds.bin",
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(0), true, true));
+ }
+
+ /**
+ * Test for upper/lower bounds of IPv4 EndPoints
+ * (Serialization/Deserialization)<br/>
+ * Used resources:<br/>
+ * - PCEPEndPointsObject1IPv4.bin<br/>
+ *
+ * @throws IOException
+ * @throws PCEPDeserializerException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testEndPointsObjectSerDeserIPv4() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ final byte[] srcIPBytes = { (byte) 0xA2, (byte) 0xF5, (byte) 0x11, (byte) 0x0E };
+ final byte[] destIPBytes = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ serDeserTest("src/test/resources/PCEPEndPointsObject1IPv4.bin", new PCEPEndPointsObject<IPv4Address>(
+ new IPv4Address(srcIPBytes), new IPv4Address(destIPBytes)));
+ }
+
+ /**
+ * Test for upper/lower bounds of IPv6 EndPoints
+ * (Serialization/Deserialization)<br/>
+ * Used resources:<br/>
+ * - PCEPEndPointsObject2IPv6.bin<br/>
+ *
+ * @throws IOException
+ * @throws PCEPDeserializerException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testEndPointsObjectSerDeserIPv6() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ final byte[] destIPBytes = { (byte) 0x00, (byte) 0x02, (byte) 0x5D, (byte) 0xD2, (byte) 0xFF,
+ (byte) 0xEC, (byte) 0xA1, (byte) 0xB6, (byte) 0x58, (byte) 0x1E, (byte) 0x9F, (byte) 0x50,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, };
+ final byte[] srcIPBytes = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+
+ serDeserTest("src/test/resources/PCEPEndPointsObject2IPv6.bin", new PCEPEndPointsObject<IPv6Address>(
+ new IPv6Address(srcIPBytes), new IPv6Address(destIPBytes)));
+ }
+
+ /**
+ * Test of Serialization/Deserialization of PCEPErrorObjectParser.<br/>
+ * <br/>
+ * Used resources:<br/>
+ * - PCEPErrorObject1.bin<br/>
+ * - PCEPErrorObject3.bin<br/>
+ *
+ * @throws PCEPDeserializerException
+ * @throws IOException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testErrorObjectSerDeserWithTlv() throws PCEPDeserializerException, IOException,
+ PCEPDocumentedException {
+ serDeserTest("src/test/resources/PCEPErrorObject1.bin", new PCEPErrorObject(
+ PCEPErrors.NON_OR_INVALID_OPEN_MSG));
+ serDeserTest("src/test/resources/PCEPErrorObject3.bin", new PCEPErrorObject(
+ PCEPErrors.CAPABILITY_NOT_SUPPORTED));
+ }
+
+ /**
+ * Test of validity of PCEPErrorObjectParser. Expect throwed
+ * NoSuchElementException.<br/>
+ * <br/>
+ * Used resources:<br/>
+ * - PCEPErrorObject2Invalid.bin<br/>
+ *
+ * @throws NoSuchElementException
+ * @throws IOException
+ * @throws PCEPDocumentedException
+ */
+ @Test(expected = PCEPDeserializerException.class)
+ public void testUnknownError() throws PCEPDeserializerException, IOException, PCEPDocumentedException {
+ PCEPObjectFactory.parseObjects(
+ ByteArray.fileToBytes("src/test/resources/PCEPErrorObject2Invalid.bin")).get(0);
+ }
+
+ /**
+ * Test for upper/lower bounds of PCEPLspaObject
+ * (Serialization/Deserialization)<br/>
+ * Used resources:<br/>
+ * - PCEPLspaObject1LowerBounds.bin<br/>
+ * - PCEPLspaObject2UpperBounds.bin<br/>
+ * - PCEPLspaObject3RandVals.bin<br/>
+ *
+ * @throws IOException
+ * @throws PCEPDeserializerException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testLspaObjectSerDeser() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ serDeserTest("src/test/resources/PCEPLspaObject2UpperBounds.bin", new PCEPLspaObject(0xFFFFFFFFL,
+ 0xFFFFFFFFL, 0xFFFFFFFFL, (short) 0xFF, (short) 0xFF, false, true, true, true));
+ serDeserTest("src/test/resources/PCEPLspaObject1LowerBounds.bin", new PCEPLspaObject(0x00000000L,
+ 0x00000000L, 0x00000000L, (short) 0x00, (short) 0x00, false, false, true, true));
+ serDeserTest("src/test/resources/PCEPLspaObject3RandVals.bin", new PCEPLspaObject(0x20A1FEE3L,
+ 0x1A025CC7L, 0x2BB66532L, (short) 0x03, (short) 0x02, false, true, true, true));
+ }
+
+ @Test
+ public void testMetricObjectSerDeserBounds() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ final byte[] bytesFromFileUB = ByteArray
+ .fileToBytes("src/test/resources/PCEPMetricObject2UpperBounds.bin");
+ final byte[] bytesFromFileLB = ByteArray
+ .fileToBytes("src/test/resources/PCEPMetricObject1LowerBounds.bin");
+
+ final PCEPMetricObject metricObjectLB = (PCEPMetricObject) PCEPObjectFactory.parseObjects(
+ bytesFromFileLB).get(0);
+ final PCEPMetricObject metricObjectUB = (PCEPMetricObject) PCEPObjectFactory.parseObjects(
+ bytesFromFileUB).get(0);
+
+ assertEquals(new PCEPMetricObject(false, false, new IGPMetric(0), true, true), metricObjectLB);
+ assertEquals(new PCEPMetricObject(false, true, new TEMetric(4026531840L), true, true), metricObjectUB);
+
+ final byte[] bytesActualLB = PCEPObjectFactory.put(Arrays.asList((PCEPObject) metricObjectLB));
+ final byte[] bytesActualUB = PCEPObjectFactory.put(Arrays.asList((PCEPObject) metricObjectUB));
+ assertArrayEquals(bytesFromFileLB, bytesActualLB);
+ assertArrayEquals(bytesFromFileUB, bytesActualUB);
+ }
+
+ /**
+ * Standard deserialization test + specific test without tlv<br/>
+ * Used resources:<br/>
+ * - NoPathObject1WithTLV.bin<br/>
+ * - NoPathObject2WithoutTLV.bin<br/>
+ *
+ * @throws PCEPDeserializerException
+ * @throws IOException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testNoPathObjectDeserialization() throws PCEPDeserializerException, IOException,
+ PCEPDocumentedException {
+ final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>(1);
+ tlvs.add(new NoPathVectorTlv(false, false, true, false, false, false));
+ serDeserTest("src/test/resources/NoPathObject1WithTLV.bin", new PCEPNoPathObject((short) 2, true,
+ tlvs, false));
+ serDeserTest("src/test/resources/NoPathObject2WithoutTLV.bin", new PCEPNoPathObject((short) 0x10,
+ false, true));
+
+ }
+
+ /**
+ * Standard serialization test + without tlv<br/>
+ * Used resources:<br/>
+ * - NoPathObject1WithTLV.bin<br/>
+ * - NoPathObject2WithoutTLV.bin<br/>
+ *
+ * @throws PCEPDeserializerException
+ * @throws IOException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testNoPathObjectSerialization() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/NoPathObject2WithoutTLV.bin");
+ PCEPNoPathObject noPathObject = (PCEPNoPathObject) PCEPObjectFactory.parseObjects(bytesFromFile).get(
+ 0);
+ byte[] bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) noPathObject));
+ assertArrayEquals(bytesFromFile, bytesActual);
+
+ bytesFromFile = ByteArray.fileToBytes("src/test/resources/NoPathObject1WithTLV.bin");
+ noPathObject = (PCEPNoPathObject) PCEPObjectFactory.parseObjects(bytesFromFile).get(0);
+ bytesActual = PCEPObjectFactory.put(Arrays.asList((PCEPObject) noPathObject));
+ assertArrayEquals(bytesFromFile, bytesActual);
+ }
+
+ /**
+ * Specific test with/without tlvs (Ser/Deser)<br/>
+ * Used resources:<br/>
+ * - PCEPNotificationObject1WithTlv.bin -
+ * PCEPNotificationObject2WithoutTlv.bin
+ *
+ * @throws PCEPDeserializerException
+ * @throws IOException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testNotifyObjectSerDeserWithTlv() throws PCEPDeserializerException, IOException,
+ PCEPDocumentedException {
+ final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>(1);
+ tlvs.add(new OverloadedDurationTlv(0xFF0000A2));
+ serDeserTest("src/test/resources/PCEPNotificationObject1WithTlv.bin", new PCEPNotificationObject(
+ (short) 1, (short) 1, tlvs));
+ serDeserTest("src/test/resources/PCEPNotificationObject2WithoutTlv.bin", new PCEPNotificationObject(
+ (short) 0xFF, (short) 0xFF));
+ }
+
+ /**
+ * Standard ser deser test<br/>
+ * used resources:<br/>
+ * - PCEPOpenObject1.bin
+ *
+ * @throws PCEPDeserializerException
+ * @throws IOException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ @Ignore //FIXME: temporary
+ public void testOpenObjectSerDeser() throws PCEPDeserializerException, IOException,
+ PCEPDocumentedException {
+ final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+ tlvs.add(new PCEStatefulCapabilityTlv(false, true, true));
+ tlvs.add(new LSPStateDBVersionTlv(0x80));
+ final byte[] valueBytes = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9A,
+ (byte) 0xBC, (byte) 0xDE, (byte) 0xF0 };
+ tlvs.add(new NodeIdentifierTlv(valueBytes));
+ final PCEPOpenObject specObject = new PCEPOpenObject(30, 120, 1, tlvs);
+
+ serDeserTest("src/test/resources/PCEPOpenObject1.bin", specObject);
+ }
+
+ /**
+ * Specific test for upper bounds and without tlvs<br/>
+ * Used resources:<br/>
+ * - PCEPOpenObject2UpperBoundsNoTlv.bin
+ *
+ * @throws PCEPDeserializerException
+ * @throws IOException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testOpenObjectBoundsWithoutTlvs() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+ serDeserTest("src/test/resources/PCEPOpenObject2UpperBoundsNoTlv.bin", new PCEPOpenObject(0xFF, 0xFF,
+ 0xFF, tlvs));
+ serDeserTest("src/test/resources/PCEPOpenObject2UpperBoundsNoTlv.bin", new PCEPOpenObject(0xFF, 0xFF,
+ 0xFF, null));
+ }
+
+ /**
+ * Standard deserialization test<br/>
+ * Used resources:<br/>
+ * - PCEPRPObject1.bin
+ *
+ * @throws PCEPDeserializerException
+ * @throws IOException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testRPObjectSerDeser() throws PCEPDeserializerException, IOException, PCEPDocumentedException {
+ serDeserTest("src/test/resources/PCEPRPObject1.bin", new PCEPRequestParameterObject(true, false,
+ true, true, false, false, false, false, (short) 5, 0xdeadbeefL, false, false));
+ serDeserTest("src/test/resources/PCEPRPObject2.bin", new PCEPRequestParameterObject(true, false,
+ false, false, true, false, true, false, true, (short) 5, 0xdeadbeefL,
+ new ArrayList<PCEPTlv>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new OrderTlv(0xFFFFFFFFL, 0x00000001L));
+ }
+ }, false, false));
+ }
+
+ /**
+ * Test for upper/lower bounds of PCEPSvecObject
+ * (Serialization/Deserialization)<br/>
+ * Used resources:<br/>
+ * - PCEPSvecObject1_10ReqIDs.bin<br/>
+ *
+ * @throws IOException
+ * @throws PCEPDeserializerException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testSvecObjectSerDeser() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ final List<Long> requestIDs = new ArrayList<Long>(10);
+ requestIDs.add(0xFFFFFFFFL);
+ requestIDs.add(0x00000000L);
+ requestIDs.add(0x01234567L);
+ requestIDs.add(0x89ABCDEFL);
+ requestIDs.add(0xFEDCBA98L);
+ requestIDs.add(0x76543210L);
+ requestIDs.add(0x15825266L);
+ requestIDs.add(0x48120BBEL);
+ requestIDs.add(0x25FB7E52L);
+ requestIDs.add(0xB2F2546BL);
+
+ serDeserTest("src/test/resources/PCEPSvecObject1_10ReqIDs.bin", new PCEPSvecObject(true, false, true,
+ false, true, requestIDs, true));
+ }
+
+ /**
+ * Test for lowest bounds of PCEPSvecObject (Serialization/Deserialization)<br/>
+ * Used resources:<br/>
+ * - PCEPSvecObject2.bin<br/>
+ *
+ * @throws IOException
+ * @throws PCEPDeserializerException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testSvecObjectSerDeserNoReqIDs() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ final List<Long> requestIDs = new ArrayList<Long>();
+ requestIDs.add(0xFFL);
+ serDeserTest("src/test/resources/PCEPSvecObject2.bin", new PCEPSvecObject(false, false, false, false,
+ false, requestIDs, false));
+ }
+
+ @Test
+ public void testClassTypeObject() throws PCEPDeserializerException, PCEPDocumentedException {
+ final PCEPClassTypeObject ct = new PCEPClassTypeObject((short) 4);
+ final PCEPClassTypeObjectParser parser = new PCEPClassTypeObjectParser();
+ final byte[] bytes = parser.put(ct);
+ assertEquals(ct, parser.parse(bytes, true, false));
+ }
+
+ /**
+ * Test PCEPExcludeRouteObjectObject (Serialization/Deserialization)<br/>
+ * Used resources:<br/>
+ * - PCEPExcludeRouteObject.1.bin<br/>
+ *
+ * @throws IOException
+ * @throws PCEPDeserializerException
+ * @throws PCEPDocumentedException
+ */
+ @Test
+ public void testExcludeRouteObject() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ final List<ExcludeRouteSubobject> xroSubobjects = new ArrayList<ExcludeRouteSubobject>();
+ xroSubobjects.add(new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] {
+ (byte) 192, (byte) 168, (byte) 100, (byte) 100 }), 16), true, XROSubobjectAttribute.NODE));
+ xroSubobjects.add(new XROAsNumberSubobject(new ASNumber(0x1234L), false));
+
+ }
+
+ @Test
+ public void tesObjectiveFunctionObject() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ serDeserTest("src/test/resources/PCEPObjectiveFunctionObject.1.bin", new PCEPObjectiveFunctionObject(
+ PCEPOFCodes.MBC, true, false));
+ }
+
+ @Test
+ public void tesGlobalConstraintsObject() throws IOException, PCEPDeserializerException,
+ PCEPDocumentedException {
+ serDeserTest("src/test/resources/PCEPGlobalConstraintsObject.1.bin", new PCEPGlobalConstraintsObject(
+ (short) 1, (short) 0, (short) 100, (short) 0xFF, true, false));
+ }
+
+ // FIXME: add at least one test with true value
+ @Test
+ public void openObjectWithTlv() throws PCEPDeserializerException, PCEPDocumentedException {
+ this.testOpenObjectWithSpecTlv(new PCEStatefulCapabilityTlv(false, false, false));
+ this.testOpenObjectWithSpecTlv(new PCEStatefulCapabilityTlv(false, false, true));
+ this.testOpenObjectWithSpecTlv(new PCEStatefulCapabilityTlv(false, true, false));
+ this.testOpenObjectWithSpecTlv(new PCEStatefulCapabilityTlv(false, true, true));
+ }
+
+ private void testOpenObjectWithSpecTlv(final PCEPTlv tlv) throws PCEPDeserializerException,
+ PCEPDocumentedException {
+ final List<PCEPObject> objs = new ArrayList<PCEPObject>();
+ final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+ tlvs.add(tlv);
+ final PCEPOpenObject oo = new PCEPOpenObject(30, 120, 0, tlvs);
+ objs.add(oo);
+ final byte[] bytes = PCEPObjectFactory.put(objs);
+ final PCEPObject obj = PCEPObjectFactory.parseObjects(bytes).get(0);
+ assertEquals(oo, obj);
+ }
+
+ @Test
+ public void testErrorsMapping() {
+ final PCEPErrorObjectParser.PCEPErrorsMaping mapper = PCEPErrorObjectParser.PCEPErrorsMaping
+ .getInstance();
+
+ for (final PCEPErrors error : PCEPErrors.values()) {
+ final PCEPErrorIdentifier errorId = mapper.getFromErrorsEnum(error);
+ assertEquals(error, mapper.getFromErrorIdentifier(errorId));
+ }
+ }
+
+ @Test
+ public void testOFCodesMapping() {
+ final PCEPOFCodesMapping mapper = PCEPOFCodesMapping.getInstance();
+
+ for (final PCEPOFCodes ofCode : PCEPOFCodes.values()) {
+ final int ofCodeId = mapper.getFromOFCodesEnum(ofCode);
+ assertEquals(ofCode, mapper.getFromCodeIdentifier(ofCodeId));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T extends PCEPObject> void serDeserTestWithoutBin(final T object)
+ throws PCEPDeserializerException, PCEPDocumentedException {
+ final byte[] serBytes = PCEPObjectFactory.put(Arrays.asList((PCEPObject) object));
+ final T deserObj = (T) PCEPObjectFactory.parseObjects(serBytes).get(0);
+
+ assertEquals(object, deserObj);
+ }
+
+ /*
+ * tests without the need of binary files
+ */
+ @Test
+ public void testBranchNodeObjects() throws PCEPDocumentedException, PCEPDeserializerException {
+ final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>();
+ eroSubobjects.add(new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] {
+ (byte) 192, (byte) 168, 1, 8 }), 16), false));
+ eroSubobjects.add(new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(new byte[] {
+ (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1,
+ (byte) 192, (byte) 168, 2, 1 }), 64), false));
+
+ serDeserTestWithoutBin(new PCEPBranchNodeListObject(eroSubobjects, true, false));
+ serDeserTestWithoutBin(new PCEPNonBranchNodeListObject(eroSubobjects, true, false));
+
+ }
+
+ @Test
+ public void testSERObjects() throws PCEPDocumentedException, PCEPDeserializerException {
+ final List<ExplicitRouteSubobject> eroSubobjects = new ArrayList<ExplicitRouteSubobject>();
+ eroSubobjects.add(new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(new byte[] {
+ (byte) 192, (byte) 168, 1, 8 }), 16), false));
+ eroSubobjects.add(new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(new byte[] {
+ (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1, (byte) 192, (byte) 168, 2, 1,
+ (byte) 192, (byte) 168, 2, 1 }), 64), false));
+
+ serDeserTestWithoutBin(new PCEPSecondaryExplicitRouteObject(eroSubobjects, true, false));
+ }
+
+ @Test
+ public void testSRRObject() throws PCEPDocumentedException, PCEPDeserializerException {
+ final List<ReportedRouteSubobject> rroSubobjects = new ArrayList<ReportedRouteSubobject>();
+ rroSubobjects.add(new RROIPAddressSubobject<IPv4Prefix>(new IPv4Prefix(this.ipv4addr, 16), true,
+ false));
+ rroSubobjects.add(new RROIPAddressSubobject<IPv6Prefix>(new IPv6Prefix(this.ipv6addr, 64), false,
+ true));
+
+ serDeserTestWithoutBin(new PCEPSecondaryRecordRouteObject(rroSubobjects, true, false));
+ }
+
+ @Test
+ public void testP2MPEndpointsObjects() throws PCEPDeserializerException, PCEPDocumentedException {
+ serDeserTestWithoutBin(new PCEPP2MPEndPointsObject<IPv4Address>(2, this.ipv4addr, Arrays.asList(
+ this.ipv4addr, this.ipv4addr, this.ipv4addr), true, false));
+ serDeserTestWithoutBin(new PCEPP2MPEndPointsObject<IPv4Address>(1, this.ipv4addr,
+ Arrays.asList(this.ipv4addr), true, false));
+ serDeserTestWithoutBin(new PCEPP2MPEndPointsObject<IPv6Address>(2, this.ipv6addr, Arrays.asList(
+ this.ipv6addr, this.ipv6addr, this.ipv6addr), true, false));
+ serDeserTestWithoutBin(new PCEPP2MPEndPointsObject<IPv6Address>(1, this.ipv6addr,
+ Arrays.asList(this.ipv6addr), true, false));
+ }
+
+ @Test
+ public void testUnreachedDestinationObjects() throws PCEPDeserializerException, PCEPDocumentedException {
+ serDeserTestWithoutBin(new PCEPUnreachedDestinationObject<IPv4Address>(Arrays.asList(this.ipv4addr,
+ this.ipv4addr, this.ipv4addr), true, false));
+ serDeserTestWithoutBin(new PCEPUnreachedDestinationObject<IPv4Address>(Arrays.asList(this.ipv4addr),
+ true, false));
+ serDeserTestWithoutBin(new PCEPUnreachedDestinationObject<IPv6Address>(Arrays.asList(this.ipv6addr,
+ this.ipv6addr, this.ipv6addr), true, false));
+ serDeserTestWithoutBin(new PCEPUnreachedDestinationObject<IPv6Address>(Arrays.asList(this.ipv6addr),
+ true, false));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.impl.subobject.EROAsNumberSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROIPv4PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROIPv6PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.EROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROExplicitExclusionRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType1Subobject;
+import org.opendaylight.protocol.pcep.subobject.EROProtectionType2Subobject;
+import org.opendaylight.protocol.pcep.subobject.EROType1LabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROAttributesSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROGeneralizedLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith128PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith32PCEIDSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType1Subobject;
+import org.opendaylight.protocol.pcep.subobject.RROProtectionType2Subobject;
+import org.opendaylight.protocol.pcep.subobject.RROType1LabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROWavebandSwitchingLabelSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+
+/**
+ * Tests for subobjects
+ */
+public class PCEPSubobjectParserTest {
+ final byte[] ipv6bytes1 = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ final byte[] ipv6bytes2 = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9A, (byte) 0xBC, (byte) 0xDE, (byte) 0x12, (byte) 0x34,
+ (byte) 0x54, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+
+ final byte[] ipv4bytes1 = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ final byte[] ipv4bytes2 = { (byte) 0x12, (byte) 0x34, (byte) 0x50, (byte) 0x00 };
+
+ @Test
+ public void testSerDeser() throws PCEPDeserializerException, IOException {
+ final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/PackOfSubobjects.bin");
+ final List<ExplicitRouteSubobject> objsToTest = PCEPEROSubobjectParser.parse(bytesFromFile);
+
+ assertEquals(8, objsToTest.size());
+
+ assertEquals(objsToTest.get(0), new EROAsNumberSubobject(new ASNumber(0xFFFFL), true));
+ assertEquals(objsToTest.get(1), new EROAsNumberSubobject(new ASNumber(0x0010L), false));
+ assertEquals(objsToTest.get(2),
+ new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(this.ipv4bytes1), 0x20),
+ true));
+
+ assertEquals(objsToTest.get(3),
+ new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(this.ipv4bytes2), 0x15),
+ false));
+ assertEquals(objsToTest.get(4),
+ new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(this.ipv6bytes1), 0x80),
+ true));
+
+ assertEquals(objsToTest.get(5),
+ new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(this.ipv6bytes2), 0x16),
+ false));
+ final byte[] addr1 = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ assertEquals(objsToTest.get(6), new EROUnnumberedInterfaceSubobject(new IPv4Address(addr1),
+ new UnnumberedInterfaceIdentifier(0xFFFFFFFFL), true));
+
+ final byte[] addr2 = { (byte) 0x01, (byte) 0x24, (byte) 0x56, (byte) 0x78 };
+ assertEquals(objsToTest.get(7), new EROUnnumberedInterfaceSubobject(new IPv4Address(addr2),
+ new UnnumberedInterfaceIdentifier(0x9ABCDEF0L), false));
+
+ assertArrayEquals(bytesFromFile, PCEPEROSubobjectParser.put(objsToTest));
+
+ }
+
+ @Test
+ public void testEROSubojectsSerDeserWithoutBin() throws PCEPDeserializerException {
+ final List<ExplicitRouteSubobject> objsToTest = new ArrayList<ExplicitRouteSubobject>();
+ objsToTest.add(new EROType1LabelSubobject(0xFFFF51F2L, true, false));
+ objsToTest.add(new EROType1LabelSubobject(0x12345648L, false, true));
+ objsToTest.add(new EROGeneralizedLabelSubobject(new byte[] { (byte) 0x12, (byte) 0x00, (byte) 0x25, (byte) 0xFF }, true, true));
+ objsToTest.add(new EROWavebandSwitchingLabelSubobject(0x12345678L, 0x87654321L, 0xFFFFFFFFL, false, false));
+ objsToTest.add(new EROProtectionType1Subobject(true, (byte) 0x05, true));
+ objsToTest.add(new EROProtectionType2Subobject(true, false, true, true, (byte) 0x06, (byte) 0x3f, true, false, (byte) 0x00, false));
+ objsToTest.add(new EROPathKeyWith32PCEIDSubobject(0x1235, new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }, true));
+ objsToTest.add(new EROPathKeyWith128PCEIDSubobject(0x5432, new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55,
+ (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }, true));
+ objsToTest.add(new EROExplicitExclusionRouteSubobject(Arrays.asList((ExcludeRouteSubobject) new XROAsNumberSubobject(new ASNumber(2588), true))));
+
+ assertEquals(objsToTest, PCEPEROSubobjectParser.parse(PCEPEROSubobjectParser.put(objsToTest)));
+ }
+
+ @Test
+ public void testRROSubojectsSerDeserWithoutBin() throws PCEPDeserializerException {
+ final List<ReportedRouteSubobject> objsToTest = new ArrayList<ReportedRouteSubobject>();
+ objsToTest.add(new RROIPAddressSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(this.ipv6bytes2),
+ 0x16), true, false));
+ objsToTest.add(new RROIPAddressSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(this.ipv4bytes1),
+ 0x16), true, false));
+ objsToTest.add(new RROType1LabelSubobject(0xFFFF51F2L, true));
+ objsToTest.add(new RROType1LabelSubobject(0x12345648L, false));
+ objsToTest.add(new RROGeneralizedLabelSubobject(new byte[] { (byte) 0x12, (byte) 0x00, (byte) 0x25, (byte) 0xFF }, true));
+ objsToTest.add(new RROWavebandSwitchingLabelSubobject(0x12345678L, 0x87654321L, 0xFFFFFFFFL, false));
+ objsToTest.add(new RROProtectionType1Subobject(true, (byte) 0x05));
+ objsToTest.add(new RROProtectionType2Subobject(true, false, true, true, (byte) 0x06, (byte) 0x3f, true, false, (byte) 0x00));
+ objsToTest.add(new RROPathKeyWith32PCEIDSubobject(0x1235, new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }));
+ objsToTest.add(new RROPathKeyWith128PCEIDSubobject(0x5432, new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55,
+ (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }));
+ objsToTest.add(new RROAttributesSubobject(new byte[] { (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF,
+ (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1, (byte) 0x00, (byte) 0x55, (byte) 0xFF, (byte) 0xF1 }));
+
+ assertEquals(objsToTest, PCEPRROSubobjectParser.parse(PCEPRROSubobjectParser.put(objsToTest)));
+ }
+
+ @Test
+ public void testXROSubojectsSerDeserWithoutBin() throws PCEPDeserializerException {
+ final List<ExcludeRouteSubobject> objsToTest = new ArrayList<ExcludeRouteSubobject>();
+ objsToTest.add(new XROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(this.ipv6bytes2),
+ 0x16), true, XROSubobjectAttribute.INTERFACE));
+ objsToTest.add(new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(this.ipv4bytes1),
+ 0x16), false, XROSubobjectAttribute.INTERFACE));
+ objsToTest.add(new XROAsNumberSubobject(new ASNumber(0x1234), true));
+ objsToTest.add(new XROUnnumberedInterfaceSubobject(new IPv4Address(this.ipv4bytes1),
+ new UnnumberedInterfaceIdentifier(0xFFFFFFFFL), true, XROSubobjectAttribute.SRLG));
+ objsToTest.add(new XROSRLGSubobject(new SharedRiskLinkGroup(0x12345678L), false));
+
+ assertEquals(objsToTest, PCEPXROSubobjectParser.parse(PCEPXROSubobjectParser.put(objsToTest)));
+ }
+
+ @Test
+ public void testDifferentLengthExceptions() {
+ final byte[] bytes = { (byte) 0x00 }; // not empty but not enought data
+ // for parsing subobjects
+
+ try {
+ EROAsNumberSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ EROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ EROIPv4PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ EROIPv6PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+ }
+
+ @Test
+ public void testNullExceptions() throws PCEPDeserializerException {
+ final byte[] bytes = null; // not empty but not enought data for parsing
+ // subobjects
+
+ try {
+ EROAsNumberSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ EROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ EROIPv4PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ EROIPv6PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testUnknownInstanceExceptions() {
+
+ final ExplicitRouteSubobject instance = new ExplicitRouteSubobject() {
+ };
+
+ try {
+ EROAsNumberSubobjectParser.put(instance);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ EROUnnumberedInterfaceSubobjectParser.put(instance);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ EROIPv4PrefixSubobjectParser.put(instance);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ final byte[] ipv6addr = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+ EROIPv4PrefixSubobjectParser.put(new EROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(ipv6addr), 1), false));
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ EROIPv6PrefixSubobjectParser.put(instance);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ final byte[] ipv4addr = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+ EROIPv6PrefixSubobjectParser.put(new EROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(ipv4addr), 1), false));
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ }
+
+ @Test
+ public void testEmptyExceptions() throws PCEPDeserializerException {
+ final byte[] bytes = {}; // not empty but not enought data for parsing
+ // subobjects
+
+ try {
+ EROAsNumberSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ EROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ EROIPv4PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ EROIPv6PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.IPv4ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.IPv6ExtendedTunnelIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPIdentifier;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.concepts.TunnelIdentifier;
+import org.opendaylight.protocol.pcep.impl.tlv.LSPIdentifierIPv4TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.LSPIdentifierIPv6TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.OFListTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.PCEStatefulCapabilityTlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.RSVPErrorSpecIPv4TlvParser;
+import org.opendaylight.protocol.pcep.impl.tlv.RSVPErrorSpecIPv6TlvParser;
+import org.opendaylight.protocol.pcep.tlv.IPv4LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.IPv6LSPIdentifiersTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPSymbolicNameTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPUpdateErrorTlv;
+import org.opendaylight.protocol.pcep.tlv.NoPathVectorTlv;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import org.opendaylight.protocol.pcep.tlv.OFListTlv;
+import org.opendaylight.protocol.pcep.tlv.OrderTlv;
+import org.opendaylight.protocol.pcep.tlv.OverloadedDurationTlv;
+import org.opendaylight.protocol.pcep.tlv.P2MPCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.pcep.tlv.RSVPErrorSpecTlv;
+import org.opendaylight.protocol.pcep.tlv.ReqMissingTlv;
+
+/**
+ * Tests of PCEPTlvParser
+ */
+public class PCEPTlvParserTest {
+
+ @Test
+ public void testDeserialization() throws PCEPDeserializerException, IOException {
+ final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/PackOfTlvs.bin");
+ final List<PCEPTlv> tlvsToTest = PCEPTlvParser.parse(bytesFromFile);
+
+ assertEquals(17, tlvsToTest.size());
+ assertEquals(tlvsToTest.get(0), new PCEStatefulCapabilityTlv(false, false, true));
+ assertEquals(tlvsToTest.get(1), new LSPStateDBVersionTlv(0xFF00FFAAB2F5F2CFL));
+ assertEquals(tlvsToTest.get(2), new PCEStatefulCapabilityTlv(false, true, true));
+ assertEquals(tlvsToTest.get(3), new LSPStateDBVersionTlv(0xFFFFFFFFFFFFFFFFL));
+ assertEquals(tlvsToTest.get(4), new NoPathVectorTlv(true, true, true, false, true, true));
+ assertEquals(tlvsToTest.get(5), new OverloadedDurationTlv(0x7FFFFFFF));
+ assertEquals(tlvsToTest.get(6), new LSPSymbolicNameTlv(new LSPSymbolicName(new String("Med test of symbolic name").getBytes())));
+ final byte[] errorCode = { (byte) 0x25, (byte) 0x68, (byte) 0x95, (byte) 0x03 };
+ assertEquals(tlvsToTest.get(7), new LSPUpdateErrorTlv(errorCode));
+ final byte[] ipv4Address = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78 };
+ final byte[] tunnelId1 = { (byte) 0x12, (byte) 0x34 };
+ final byte[] extendedTunnelID1 = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78 };
+ final byte[] lspId1 = { (byte) 0xFF, (byte) 0xFF };
+ assertEquals(tlvsToTest.get(8), new IPv4LSPIdentifiersTlv(new IPv4Address(ipv4Address),
+ new LSPIdentifier(lspId1), new TunnelIdentifier(tunnelId1), new IPv4ExtendedTunnelIdentifier(new IPv4Address(extendedTunnelID1))));
+ final byte[] ipv6Address = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9A, (byte) 0xBC, (byte) 0xDE, (byte) 0xF0, (byte) 0x12,
+ (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9A, (byte) 0xBC, (byte) 0xDE, (byte) 0xF0 };
+ final byte[] tunnelId2 = { (byte) 0xFF, (byte) 0xFF };
+ final byte[] extendedTunnelID2 = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x01,
+ (byte) 0x23, (byte) 0x45, (byte) 0x67, (byte) 0x01, (byte) 0x23, (byte) 0x45, (byte) 0x67 };
+ final byte[] lspId2 = { (byte) 0x12, (byte) 0x34 };
+ assertEquals(tlvsToTest.get(9), new IPv6LSPIdentifiersTlv(new IPv6Address(ipv6Address),
+ new LSPIdentifier(lspId2), new TunnelIdentifier(tunnelId2), new IPv6ExtendedTunnelIdentifier(new IPv6Address(extendedTunnelID2))));
+ assertEquals(tlvsToTest.get(10), new RSVPErrorSpecTlv<IPv4Address>(new IPv4Address(ipv4Address), false, true, 0x92, 0x1602));
+ assertEquals(tlvsToTest.get(11), new RSVPErrorSpecTlv<IPv6Address>(new IPv6Address(ipv6Address), true, false, 0xD5, 0xC5D9));
+ assertEquals(tlvsToTest.get(12), new ReqMissingTlv(0xF7823517L));
+ final byte[] valueBytes = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ assertEquals(tlvsToTest.get(13), new NodeIdentifierTlv(valueBytes));
+ assertEquals(tlvsToTest.get(14), new OrderTlv(0xFFFFFFFFL, 0x00000001L));
+ assertEquals(tlvsToTest.get(15), new OFListTlv(new ArrayList<PCEPOFCodes>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(PCEPOFCodes.MCC);
+ this.add(PCEPOFCodes.MCP);
+ this.add(PCEPOFCodes.MLL);
+ }
+ }));
+ assertEquals(tlvsToTest.get(16), new P2MPCapabilityTlv(2));
+
+ assertArrayEquals(bytesFromFile, PCEPTlvParser.put(tlvsToTest));
+ }
+
+ @Test
+ public void testDifferentLengthExceptions() {
+ final byte[] bytes = { (byte) 0x00 }; // not empty but not enought data
+ // for parsing subobjects
+
+ try {
+ LSPIdentifierIPv4TlvParser.parse(bytes);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ LSPIdentifierIPv6TlvParser.parse(bytes);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ PCEStatefulCapabilityTlvParser.deserializeValueField(bytes);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ RSVPErrorSpecIPv4TlvParser.parse(bytes);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ RSVPErrorSpecIPv6TlvParser.parse(bytes);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ OFListTlvParser.parse(bytes);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+ }
+
+ @Test
+ public void testUnknownInstanceExceptions() {
+ try {
+ LSPIdentifierIPv4TlvParser.put(null);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ LSPIdentifierIPv6TlvParser.put(null);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ PCEStatefulCapabilityTlvParser.serializeValueField(null);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ RSVPErrorSpecIPv4TlvParser.put(null);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ RSVPErrorSpecIPv6TlvParser.put(null);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ OFListTlvParser.put(null);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ }
+
+ @Test
+ public void testEmptyExceptions() throws PCEPDeserializerException {
+ final byte[] bytes = {}; // empty
+
+ try {
+ LSPIdentifierIPv4TlvParser.parse(bytes);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ LSPIdentifierIPv6TlvParser.parse(bytes);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ PCEStatefulCapabilityTlvParser.deserializeValueField(bytes);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ RSVPErrorSpecIPv4TlvParser.parse(bytes);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ RSVPErrorSpecIPv6TlvParser.parse(bytes);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ OFListTlvParser.parse(bytes);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.framework.DeserializerException;
+import org.opendaylight.protocol.framework.DocumentedException;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.Bandwidth;
+import org.opendaylight.protocol.concepts.IGPMetric;
+import org.opendaylight.protocol.concepts.IPv4;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.TEMetric;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.PCEPDocumentedException;
+import org.opendaylight.protocol.pcep.PCEPErrors;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPOFCodes;
+import org.opendaylight.protocol.pcep.PCEPObject;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.concepts.LSPSymbolicName;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.impl.PCEPMessageFactory.PCEPMessageType;
+import org.opendaylight.protocol.pcep.impl.message.PCEPRawMessage;
+import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
+import org.opendaylight.protocol.pcep.message.PCCreateMessage;
+import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
+import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
+import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
+import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
+import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+import org.opendaylight.protocol.pcep.message.PCEPXRDeleteTunnelMessage;
+import org.opendaylight.protocol.pcep.object.CompositeErrorObject;
+import org.opendaylight.protocol.pcep.object.CompositeInstantiationObject;
+import org.opendaylight.protocol.pcep.object.CompositeNotifyObject;
+import org.opendaylight.protocol.pcep.object.CompositePathObject;
+import org.opendaylight.protocol.pcep.object.CompositeReplySvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestObject;
+import org.opendaylight.protocol.pcep.object.CompositeRequestSvecObject;
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject;
+import org.opendaylight.protocol.pcep.object.CompositeRptPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeStateReportObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdPathObject;
+import org.opendaylight.protocol.pcep.object.CompositeUpdateRequestObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
+import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
+import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
+import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
+import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
+import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
+import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
+import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
+import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
+import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject;
+import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.pcep.tlv.LSPSymbolicNameTlv;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+
+public class PCEPValidatorTest {
+
+ private static final PCEPLspaObject lspa = new PCEPLspaObject(0L, 0L, 0L, (short) 0, (short) 0, false, false, false, false);
+
+ private final List<ExplicitRouteSubobject> eroSubobjects = asList(
+ new EROAsNumberSubobject(new ASNumber(0xFFFFL), false),
+ new EROUnnumberedInterfaceSubobject(new IPv4Address(
+ new byte[] { (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33 }), new UnnumberedInterfaceIdentifier(0x00FF00FF), false));
+
+ private final List<ReportedRouteSubobject> rroSubobjects = asList((ReportedRouteSubobject) new RROUnnumberedInterfaceSubobject(new IPv4Address(new byte[] { (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33 }),
+ new UnnumberedInterfaceIdentifier(0x00FF00FF)));
+
+ private final List<Long> requestIds = asList(0x000001L);
+
+ private final IPv4Address ip4addr = new IPv4Address(new byte[] { (byte) 0xFF, 0x00, 0x00, 0x01 });
+
+ private final PCEPSvecObject svecObj = new PCEPSvecObject(true, true, true, false, false, PCEPValidatorTest.this.requestIds, true);
+
+ private final PCEPRequestParameterObject requestParameter = new PCEPRequestParameterObject(true, false, false, false, false, false, false, false,
+ (short) 3, 1, true, false);
+
+ // private final PCEPEndPointsObject<IPv4Address> endPoints = new
+ // PCEPEndPointsObject<IPv4Address>(this.ip4addr, this.ip4addr);
+
+ private final PCEPEndPointsObject<IPv4Address> endPoints = new PCEPEndPointsObject<IPv4Address>(this.ip4addr, this.ip4addr);
+
+ private final PCEPMessageFactory msgFactory = new PCEPMessageFactory();
+
+ // private final PCEPClassTypeObject classType = new
+ // PCEPClassTypeObject((short) 7);
+ // private final PCEPClassTypeObjectProvider classTypeProvider = new
+ // PCEPClassTypeObjectProvider((short) 7, true);
+
+ private static List<PCEPMessage> deserMsg(final String srcFile) throws IOException, DeserializerException, DocumentedException, PCEPDeserializerException {
+ final byte[] bytesFromFile = ByteArray.fileToBytes(srcFile);
+ final PCEPRawMessage rawMessage = (PCEPRawMessage) new PCEPMessageFactory().parse(ByteArray.cutBytes(bytesFromFile, PCEPMessageHeader.COMMON_HEADER_LENGTH),
+ new PCEPMessageHeader().fromBytes(Arrays.copyOf(bytesFromFile, PCEPMessageHeader.COMMON_HEADER_LENGTH)));
+
+ return PCEPMessageValidator.getValidator(rawMessage.getMsgType()).validate(rawMessage.getAllObjects());
+ }
+
+ @Test
+ public void testOpenMessageValidationFromBin() throws IOException, DeserializerException, DocumentedException, PCEPDeserializerException {
+ assertEquals(
+ deserMsg("src/test/resources/PCEPOpenMessage1.bin"),
+ asList(new PCEPOpenMessage(new PCEPOpenObject(30, 120, 1, asList(new PCEStatefulCapabilityTlv(false, true, true), new LSPStateDBVersionTlv(
+ 0x80))))));
+
+ assertEquals(deserMsg("src/test/resources/Open.1.bin"), asList(new PCEPOpenMessage(new PCEPOpenObject(1, 4, 1))));
+
+ assertEquals(
+ deserMsg("src/test/resources/Open.3.bin"),
+ asList(new PCEPOpenMessage(new PCEPOpenObject(1, 4, 1, asList(new PCEStatefulCapabilityTlv(false, true, true), new LSPStateDBVersionTlv(53))))));
+ }
+
+ @Test
+ public void testKeepAliveMessageValidationFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+ assertEquals(deserMsg("src/test/resources/PCEPKeepAliveMessage1.bin"), asList(new PCEPKeepAliveMessage()));
+ assertEquals(deserMsg("src/test/resources/Keepalive.1.bin"), asList(new PCEPKeepAliveMessage()));
+ }
+
+ @Test
+ public void testCloseMsg() throws PCEPDeserializerException, IOException, PCEPDocumentedException, DeserializerException, DocumentedException {
+ assertEquals(deserMsg("src/test/resources/PCEPCloseMessage1.bin"), asList(new PCEPCloseMessage(new PCEPCloseObject(Reason.TOO_MANY_UNKNOWN_MSG))));
+ assertEquals(deserMsg("src/test/resources/Close.1.bin"), asList(new PCEPCloseMessage(new PCEPCloseObject(Reason.UNKNOWN))));
+ }
+
+ @Test
+ public void testRequestMessageValidationFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+ List<CompositeRequestObject> requests = new ArrayList<CompositeRequestObject>();
+ final byte[] ipAdress = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ requests.add(new CompositeRequestObject(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 5, 0xDEADBEEFL,
+ true, false), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress), new IPv4Address(ipAdress))));
+ PCEPRequestMessage specMessage = new PCEPRequestMessage(requests);
+ List<PCEPMessage> deserMsgs = deserMsg("src/test/resources/PCEPRequestMessage1.bin");
+ final List<PCEPMessage> specMessages = new ArrayList<PCEPMessage>();
+ specMessages.add(specMessage);
+
+ assertEquals(deserMsgs, specMessages);
+
+ requests = new ArrayList<CompositeRequestObject>();
+ final byte[] ipAdress2 = { (byte) 0x7F, (byte) 0x00, (byte) 0x00, (byte) 0x01 };
+ requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2))));
+ specMessage = new PCEPRequestMessage(requests);
+ deserMsgs = deserMsg("src/test/resources/PCReq.1.bin");
+ specMessages.clear();
+ specMessages.add(specMessage);
+ assertEquals(deserMsgs, specMessages);
+
+ requests = new ArrayList<CompositeRequestObject>();
+ requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2)), null, null, null, null,
+ null, null, null, null, new PCEPLoadBalancingObject(3, new Bandwidth(1024.75f), false)));
+ specMessage = new PCEPRequestMessage(requests);
+ deserMsgs = deserMsg("src/test/resources/PCReq.2.bin");
+ specMessages.clear();
+ specMessages.add(specMessage);
+ assertEquals(deserMsgs, specMessages);
+
+ requests = new ArrayList<CompositeRequestObject>();
+ requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2)), null, new PCEPLspObject(1,
+ false, false, true, false), PCEPValidatorTest.lspa, new PCEPRequestedPathBandwidthObject(new Bandwidth(1000), false, false),
+ new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(53L), false, false));
+ }
+ }, new PCEPReportedRouteObject(this.rroSubobjects, false), new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false),
+ new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new PCEPLoadBalancingObject(5, new Bandwidth(3f), false)));
+
+ List<CompositeRequestSvecObject> svecList = new ArrayList<CompositeRequestSvecObject>();
+ svecList.add(new CompositeRequestSvecObject(new PCEPSvecObject(true, false, false, false, false, this.requestIds, false)));
+
+ specMessage = new PCEPRequestMessage(svecList, requests);
+ deserMsgs = deserMsg("src/test/resources/PCReq.3.bin");
+ specMessages.clear();
+ specMessages.add(specMessage);
+ assertEquals(deserMsgs, specMessages);
+
+ specMessages.clear();
+ requests = new ArrayList<CompositeRequestObject>();
+ requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2)), null, null, null, null,
+ null, null, null, null, null));
+ specMessages.add(new PCEPRequestMessage(requests));
+
+ final byte[] ipAdress3 = { (byte) 0x7F, (byte) 0x00, (byte) 0x30, (byte) 0x01 };
+ requests = new ArrayList<CompositeRequestObject>();
+ requests.add(new CompositeRequestObject(new PCEPRequestParameterObject(false, false, false, false, false, false, false, false, (short) 4, 1, true,
+ false), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress3), new IPv4Address(ipAdress2)), null, null, null, null, null, null, null, null, null));
+ specMessages.add(new PCEPRequestMessage(requests));
+
+ final byte[] ipAdress4 = { (byte) 0x7F, (byte) 0x30, (byte) 0x00, (byte) 0x01 };
+ requests = new ArrayList<CompositeRequestObject>();
+ requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress4)), null, null, null, null,
+ null, null, null, null, null));
+ specMessages.add(new PCEPRequestMessage(requests));
+
+ final byte[] ipAdress5 = { (byte) 0x7F, (byte) 0xd0, (byte) 0x00, (byte) 0x01 };
+ requests = new ArrayList<CompositeRequestObject>();
+ requests.add(new CompositeRequestObject(
+ new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 1, true, false),
+ new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress5), new IPv4Address(ipAdress5)), null, null, null, null, null, null, null, null, null));
+
+ specMessages.add(new PCEPRequestMessage(requests));
+ deserMsgs = deserMsg("src/test/resources/PCReq.4.bin");
+ assertEquals(deserMsgs, specMessages);
+
+ specMessages.clear();
+ svecList = new ArrayList<CompositeRequestSvecObject>();
+ svecList.add(new CompositeRequestSvecObject(new PCEPSvecObject(true, false, false, false, false, this.requestIds, false)));
+ svecList.add(new CompositeRequestSvecObject(new PCEPSvecObject(false, true, true, false, false, this.requestIds, false),
+ new PCEPObjectiveFunctionObject(PCEPOFCodes.MCC, true, false), new PCEPGlobalConstraintsObject((short) 0x55, (short) 1, (short) 100,
+ (short) 0x26, true, false), new PCEPExcludeRouteObject(new ArrayList<ExcludeRouteSubobject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new XROAsNumberSubobject(new ASNumber(0x12), true));
+ }
+ }, true, true, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new TEMetric(123456L), true, false));
+ }
+ }));
+
+ requests = new ArrayList<CompositeRequestObject>();
+ requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress2), new IPv4Address(ipAdress2)), null, null,
+ PCEPValidatorTest.lspa, new PCEPRequestedPathBandwidthObject(new Bandwidth(1000), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(53L), false, false));
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(5335L), false, false));
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(128256), false, false));
+ }
+ }, new PCEPReportedRouteObject(this.rroSubobjects, false), new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false),
+ new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new PCEPLoadBalancingObject(5, new Bandwidth(3f), false)));
+
+ final byte[] ipAdress6 = { (byte) 0x7F, (byte) 0xF0, (byte) 0x00, (byte) 0x01 };
+ specMessages.add(new PCEPRequestMessage(svecList, requests));
+
+ requests = new ArrayList<CompositeRequestObject>();
+ requests.add(new CompositeRequestObject(this.requestParameter, new PCEPEndPointsObject<IPv4Address>(new IPv4Address(ipAdress6), new IPv4Address(ipAdress6)), null, null,
+ PCEPValidatorTest.lspa, new PCEPRequestedPathBandwidthObject(new Bandwidth(1000), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(53L), false, false));
+ }
+ }, new PCEPReportedRouteObject(this.rroSubobjects, false), new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false),
+ new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new PCEPLoadBalancingObject(5, new Bandwidth(3f), false)));
+ deserMsgs = deserMsg("src/test/resources/PCReq.5.bin");
+ specMessages.add(new PCEPRequestMessage(svecList, requests));
+ assertEquals(deserMsgs, specMessages);
+
+ // FIXME: need construct with invalid processed parameter
+ // assertEquals(deserMsg("src/test/resources/PCReq.6.invalid.bin"),
+ // asList(
+ // new PCEPErrorMessage(new CompositeErrorObject(new
+ // PCEPRequestParameterObject(true, false, false, false, false, false,
+ // false, false, (short) 3,
+ // 1L, false, false), new PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))),
+ // new PCEPRequestMessage(asList(new
+ // CompositeRequestObject(this.requestParameter, new
+ // PCEPEndPointsObject<IPv4Address>(IPv4Address
+ // .getNetworkAddressFactory().getNetworkAddressForBytes(new byte[] {
+ // 127, 0, 0, 1 }), IPv4Address.getNetworkAddressFactory()
+ // .getNetworkAddressForBytes(new byte[] { 127, 0, 0, 1 })), null, null,
+ // null, null, null, null, null, null, new PCEPLoadBalancingObject(
+ // 3, new Bandwidth(1024.75), false))))));
+
+ }
+
+ @Test
+ public void testRequestMessageValidationFromRawMsg() throws PCEPDeserializerException {
+ List<PCEPObject> objs = new ArrayList<PCEPObject>();
+ List<PCEPMessage> msgs;
+ PCEPRequestParameterObject tmpRP;
+
+ // test unrecognized object in svec list
+ objs.add(this.svecObj);
+ objs.add(new UnknownObject(true, false, PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+ objs.add(new PCEPSvecObject(true, true, true, false, false, PCEPValidatorTest.this.requestIds, true));
+
+ msgs = PCEPMessageValidator.getValidator(PCEPMessageType.REQUEST).validate(objs);
+
+ assertEquals(msgs.get(0), new PCEPErrorMessage(new ArrayList<PCEPErrorObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+ }
+ }));
+
+ // test with request p flag not set and ignoracion of more than one
+ // end-points objects
+ objs = new ArrayList<PCEPObject>();
+ objs.add(this.svecObj);
+ objs.add(this.svecObj);
+ tmpRP = new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 3, 1, false, false);
+ objs.add(tmpRP);
+ objs.add(this.endPoints);
+
+ objs.add(this.requestParameter);
+ objs.add(this.endPoints);
+ objs.add(this.endPoints);
+ // FIXME:mv use object constructor with set processed flag
+ // objs.add(this.classTypeProvider);
+ // objs.add(this.requestParameter);
+ // objs.add(this.endPointsProvider);
+ // objs.add(new PCEPClassTypeObjectProvider((short) 7, false));
+
+ msgs = PCEPMessageValidator.getValidator(PCEPMessageType.REQUEST).validate(objs);
+ // FIXME:mv use object constructor with set processed flag
+ // assertEquals(msgs.get(0), new PCEPErrorMessage(new
+ // CompositeErrorObject(tmpRP, new
+ // PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+ // assertEquals(
+ // msgs.get(1),
+ // new PCEPRequestMessage(asList(new
+ // CompositeRequestSvecObject(this.svecObj), new
+ // CompositeRequestSvecObject(this.svecObj)), Util
+ // .asList(new CompositeRequestObject(this.requestParameter,
+ // this.endPoints, this.classType, null, null, null, null, null, null,
+ // null,
+ // null))));
+ // assertEquals(msgs.get(2), new PCEPErrorMessage(new
+ // CompositeErrorObject(tmpRP, new
+ // PCEPErrorObject(PCEPErrors.P_FLAG_NOT_SET))));
+ }
+
+ @Test
+ public void testReplyMessageValidatorFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+
+ List<PCEPReplyMessage> specMessages = new ArrayList<PCEPReplyMessage>();
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+ false, false, (short) 5, 0xDEADBEEFL, true, true)))));
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, true, true, false, false, false,
+ false, false, (short) 7, 0x12345678L, false, false)))));
+ assertEquals(deserMsg("src/test/resources/PCEPReplyMessage1.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPReplyMessage>();
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+ false, false, (short) 3, 1, false, false)))));
+ assertEquals(deserMsg("src/test/resources/PCRep.1.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPReplyMessage>();
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+ false, false, (short) 3, 1, false, false)))));
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(false, false, false, false, false, false,
+ false, false, (short) 5, 2, false, false), new PCEPNoPathObject((short) 0, false, false), null, null, null, null, null, null))));
+ assertEquals(deserMsg("src/test/resources/PCRep.2.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPReplyMessage>();
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+ false, false, (short) 3, 1, false, false), new PCEPNoPathObject((short) 1, true, false), new PCEPLspObject(1, true, true, false, true),
+ PCEPValidatorTest.lspa, new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(234), false, false));
+ }
+ }, new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new ArrayList<CompositePathObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositePathObject(new PCEPExplicitRouteObject(PCEPValidatorTest.this.eroSubobjects, false), lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(234L), false, false));
+ }
+ }, new PCEPIncludeRouteObject(PCEPValidatorTest.this.eroSubobjects, false, false)));
+ }
+ }))));
+ assertEquals(deserMsg("src/test/resources/PCRep.3.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPReplyMessage>();
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+ false, false, (short) 7, 1, false, false)))));
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+ false, false, (short) 1, 2, false, false)))));
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+ false, false, (short) 2, 4, false, false)))));
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(false, false, false, false, false, false,
+ false, false, (short) 3, 4, false, false)))));
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(false, false, false, false, false, false,
+ false, false, (short) 6, 5, false, false)))));
+ assertEquals(deserMsg("src/test/resources/PCRep.4.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPReplyMessage>();
+ final List<Long> requestIDs = new ArrayList<Long>();
+ requestIDs.add(0x25069045L);
+
+ final List<PCEPMetricObject> metrics = new ArrayList<PCEPMetricObject>();
+ metrics.add(new PCEPMetricObject(true, true, new IGPMetric(234L), true, false));
+
+ final List<CompositeReplySvecObject> svecList = new ArrayList<CompositeReplySvecObject>();
+ svecList.add(new CompositeReplySvecObject(new PCEPSvecObject(true, true, true, false, false, requestIDs, true), new PCEPObjectiveFunctionObject(
+ PCEPOFCodes.MCC, true, false), metrics));
+
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+ false, false, (short) 3, 1, false, false), new PCEPNoPathObject((short) 1, true, false), null, PCEPValidatorTest.lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(234), false, false));
+ }
+ }, new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new ArrayList<CompositePathObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositePathObject(new PCEPExplicitRouteObject(PCEPValidatorTest.this.eroSubobjects, false), lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(234L), false, false));
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(5355L), false, false));
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(5353L), false, false));
+ }
+ }, new PCEPIncludeRouteObject(PCEPValidatorTest.this.eroSubobjects, false, false)));
+ }
+ })), svecList));
+ specMessages.add(new PCEPReplyMessage(asList(new CompositeResponseObject(new PCEPRequestParameterObject(true, false, false, false, false, false,
+ false, false, (short) 3, 1, false, false), new PCEPNoPathObject((short) 1, true, false), null, PCEPValidatorTest.lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(234), false, false));
+ }
+ }, new PCEPIncludeRouteObject(this.eroSubobjects, false, false), new ArrayList<CompositePathObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new CompositePathObject(new PCEPExplicitRouteObject(PCEPValidatorTest.this.eroSubobjects, false), lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(234L), false, false));
+ }
+ }, new PCEPIncludeRouteObject(PCEPValidatorTest.this.eroSubobjects, false, false)));
+ this.add(new CompositePathObject(new PCEPExplicitRouteObject(PCEPValidatorTest.this.eroSubobjects, false), lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(500f), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, true, new IGPMetric(234L), false, false));
+ }
+ }, new PCEPIncludeRouteObject(PCEPValidatorTest.this.eroSubobjects, false, false)));
+ }
+ })), svecList));
+ assertEquals(deserMsg("src/test/resources/PCRep.5.bin"), specMessages);
+ }
+
+ @Test
+ public void testUpdMessageValidatorFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+ List<PCEPMessage> specMessages = new ArrayList<PCEPMessage>();
+
+ List<CompositeUpdateRequestObject> requests = new ArrayList<CompositeUpdateRequestObject>();
+ requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true)));
+
+ specMessages.add(new PCEPUpdateRequestMessage(requests));
+ assertEquals(deserMsg("src/test/resources/PCUpd.1.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPMessage>();
+ List<CompositeUpdPathObject> paths = new ArrayList<CompositeUpdPathObject>();
+ paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa, null, null));
+ requests = new ArrayList<CompositeUpdateRequestObject>();
+ requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true), paths));
+ specMessages.add(new PCEPUpdateRequestMessage(requests));
+ assertEquals(deserMsg("src/test/resources/PCUpd.2.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPMessage>();
+ paths = new ArrayList<CompositeUpdPathObject>();
+ paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+ requests = new ArrayList<CompositeUpdateRequestObject>();
+ requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true), paths));
+ specMessages.add(new PCEPUpdateRequestMessage(requests));
+ assertEquals(deserMsg("src/test/resources/PCUpd.3.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPMessage>();
+ requests = new ArrayList<CompositeUpdateRequestObject>();
+ requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true)));
+ requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true)));
+ specMessages.add(new PCEPUpdateRequestMessage(requests));
+ assertEquals(deserMsg("src/test/resources/PCUpd.4.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPMessage>();
+ requests = new ArrayList<CompositeUpdateRequestObject>();
+ requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true)));
+ paths = new ArrayList<CompositeUpdPathObject>();
+ paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+ requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true), paths));
+ paths = new ArrayList<CompositeUpdPathObject>();
+ paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+ paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+ paths.add(new CompositeUpdPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+ new PCEPRequestedPathBandwidthObject(new Bandwidth(5353), false, false), new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+ requests.add(new CompositeUpdateRequestObject(new PCEPLspObject(1, true, false, true, true), paths));
+ specMessages.add(new PCEPUpdateRequestMessage(requests));
+ assertEquals(deserMsg("src/test/resources/PCUpd.5.bin"), specMessages);
+ }
+
+ @Test
+ public void testRptMessageValidatorFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+ List<PCEPMessage> specMessages = new ArrayList<PCEPMessage>();
+ List<CompositeStateReportObject> reports = new ArrayList<CompositeStateReportObject>();
+ reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true)));
+ specMessages.add(new PCEPReportMessage(reports));
+ assertEquals(deserMsg("src/test/resources/PCRpt.1.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPMessage>();
+ List<CompositeRptPathObject> paths = new ArrayList<CompositeRptPathObject>();
+ paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa, null, null, null));
+ reports = new ArrayList<CompositeStateReportObject>();
+ reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true), paths));
+ specMessages.add(new PCEPReportMessage(reports));
+ assertEquals(deserMsg("src/test/resources/PCRpt.2.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPMessage>();
+ paths = new ArrayList<CompositeRptPathObject>();
+ paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+ new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false), new PCEPReportedRouteObject(this.rroSubobjects, false),
+ new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+
+ reports = new ArrayList<CompositeStateReportObject>();
+ reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true), paths));
+ specMessages.add(new PCEPReportMessage(reports));
+ //FIXME:
+ //assertEquals(deserMsg("src/test/resources/PCRpt.3.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPMessage>();
+ reports = new ArrayList<CompositeStateReportObject>();
+ reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true)));
+ reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true)));
+ reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true)));
+ specMessages.add(new PCEPReportMessage(reports));
+ assertEquals(deserMsg("src/test/resources/PCRpt.4.bin"), specMessages);
+
+ specMessages = new ArrayList<PCEPMessage>();
+ reports = new ArrayList<CompositeStateReportObject>();
+ paths = new ArrayList<CompositeRptPathObject>();
+ paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+ new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false), new PCEPReportedRouteObject(this.rroSubobjects, false),
+ new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+ reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true), paths));
+ paths = new ArrayList<CompositeRptPathObject>();
+ paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+ new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false), new PCEPReportedRouteObject(this.rroSubobjects, false),
+ new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+ paths.add(new CompositeRptPathObject(new PCEPExplicitRouteObject(this.eroSubobjects, false), PCEPValidatorTest.lspa,
+ new PCEPExistingPathBandwidthObject(new Bandwidth(5353), false, false), new PCEPReportedRouteObject(this.rroSubobjects, false),
+ new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+ reports.add(new CompositeStateReportObject(new PCEPLspObject(1, true, false, true, true), paths));
+ specMessages.add(new PCEPReportMessage(reports));
+ //FIXME
+ //assertEquals(deserMsg("src/test/resources/PCRpt.5.bin"), specMessages);
+ }
+
+ @Test
+ public void testXRDeleteTunnelMessage() throws DeserializerException, DocumentedException, PCEPDeserializerException {
+ final PCEPXRDeleteTunnelMessage dTunnel = new PCEPXRDeleteTunnelMessage(new PCEPLspObject(1, false, true, false, true));
+ final byte[] bytes = this.msgFactory.put(dTunnel);
+
+ final PCEPRawMessage rawMessage = (PCEPRawMessage) this.msgFactory.parse(ByteArray.cutBytes(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH),
+ new PCEPMessageHeader().fromBytes(Arrays.copyOf(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH)));
+
+ assertEquals(PCEPMessageValidator.getValidator(rawMessage.getMsgType()).validate(rawMessage.getAllObjects()), asList((PCEPMessage) dTunnel));
+ }
+
+ @Test
+ public void testXRAddTunnelMessage() throws DeserializerException, DocumentedException, PCEPDeserializerException {
+ final List<ExplicitRouteSubobject> subs = new ArrayList<ExplicitRouteSubobject>();
+ subs.add(new EROAsNumberSubobject(new ASNumber(10), false));
+ final PCEPXRAddTunnelMessage addTunnel = new PCEPXRAddTunnelMessage(new PCEPLspObject(1, false, false, false, false),
+ new PCEPEndPointsObject<IPv4Address>(IPv4.FAMILY.addressForString("127.0.0.2"), IPv4.FAMILY.addressForString("127.0.0.1")),
+ new PCEPExplicitRouteObject(subs, true));
+ final byte[] bytes = this.msgFactory.put(addTunnel);
+
+ final PCEPRawMessage rawMessage = (PCEPRawMessage) this.msgFactory.parse(ByteArray.cutBytes(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH),
+ new PCEPMessageHeader().fromBytes(Arrays.copyOf(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH)));
+ assertEquals(PCEPMessageValidator.getValidator(rawMessage.getMsgType()).validate(rawMessage.getAllObjects()), asList((PCEPMessage) addTunnel));
+ }
+
+ @Test
+ public void testPCCreateMessage() throws DeserializerException, DocumentedException, PCEPDeserializerException {
+ final List<CompositeInstantiationObject> insts = new ArrayList<CompositeInstantiationObject>();
+ final List<ExplicitRouteSubobject> subs = new ArrayList<ExplicitRouteSubobject>();
+ subs.add(new EROAsNumberSubobject(new ASNumber(10), false));
+ final List<PCEPTlv> tlvs = new ArrayList<PCEPTlv>();
+ final LSPSymbolicNameTlv tlv = new LSPSymbolicNameTlv(new LSPSymbolicName(new byte[] { 5, 4 }));
+ tlvs.add(tlv);
+ insts.add(new CompositeInstantiationObject(new PCEPEndPointsObject<IPv4Address>(IPv4.FAMILY.addressForString("127.0.0.2"),
+ IPv4.FAMILY.addressForString("127.0.0.1")), PCEPValidatorTest.lspa, new PCEPExplicitRouteObject(subs, true), null, new ArrayList<PCEPMetricObject>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ this.add(new PCEPMetricObject(true, false, new IGPMetric(4L), false, false));
+ }
+ }));
+ final PCCreateMessage msg = new PCCreateMessage(insts);
+
+ final byte[] bytes = this.msgFactory.put(msg);
+
+ // FIXME: need construct with invalid processed parameter
+ final PCEPRawMessage rawMessage = (PCEPRawMessage) this.msgFactory.parse(ByteArray.cutBytes(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH),
+ new PCEPMessageHeader().fromBytes(Arrays.copyOf(bytes, PCEPMessageHeader.COMMON_HEADER_LENGTH)));
+
+ assertEquals(PCEPMessageValidator.getValidator(rawMessage.getMsgType()).validate(rawMessage.getAllObjects()), asList((PCEPMessage) msg));
+ }
+
+ @Test
+ public void testNotificationValidatorFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+ List<CompositeNotifyObject> notifications = new ArrayList<CompositeNotifyObject>();
+ List<PCEPNotificationObject> notificationsList = new ArrayList<PCEPNotificationObject>();
+ notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+ notifications.add(new CompositeNotifyObject(notificationsList));
+ PCEPNotificationMessage specMessage = new PCEPNotificationMessage(notifications);
+ assertEquals(deserMsg("src/test/resources/PCNtf.1.bin"), asList((PCEPMessage) specMessage));
+
+ notifications = new ArrayList<CompositeNotifyObject>();
+ notificationsList = new ArrayList<PCEPNotificationObject>();
+ notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+ List<PCEPRequestParameterObject> requestsList = new ArrayList<PCEPRequestParameterObject>();
+ requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 3, 1, false, false));
+ notifications.add(new CompositeNotifyObject(requestsList, notificationsList));
+ specMessage = new PCEPNotificationMessage(notifications);
+ assertEquals(deserMsg("src/test/resources/PCNtf.2.bin"), asList((PCEPMessage) specMessage));
+
+ notifications = new ArrayList<CompositeNotifyObject>();
+ notificationsList = new ArrayList<PCEPNotificationObject>();
+ notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+ requestsList = new ArrayList<PCEPRequestParameterObject>();
+ requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 10, false, false));
+ notifications.add(new CompositeNotifyObject(requestsList, notificationsList));
+ specMessage = new PCEPNotificationMessage(notifications);
+ assertEquals(deserMsg("src/test/resources/PCNtf.3.bin"), asList((PCEPMessage) specMessage));
+
+ notifications = new ArrayList<CompositeNotifyObject>();
+ notificationsList = new ArrayList<PCEPNotificationObject>();
+ notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+ notificationsList.add(new PCEPNotificationObject((short) 1, (short) 2));
+ notificationsList.add(new PCEPNotificationObject((short) 2, (short) 1));
+ notificationsList.add(new PCEPNotificationObject((short) 2, (short) 2));
+ notifications.add(new CompositeNotifyObject(notificationsList));
+ specMessage = new PCEPNotificationMessage(notifications);
+ assertEquals(deserMsg("src/test/resources/PCNtf.4.bin"), asList((PCEPMessage) specMessage));
+
+ notifications = new ArrayList<CompositeNotifyObject>();
+ notificationsList = new ArrayList<PCEPNotificationObject>();
+ notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+ requestsList = new ArrayList<PCEPRequestParameterObject>();
+ requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 10, false, false));
+ notifications.add(new CompositeNotifyObject(requestsList, notificationsList));
+ notificationsList = new ArrayList<PCEPNotificationObject>();
+ notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+ notificationsList.add(new PCEPNotificationObject((short) 1, (short) 1));
+ requestsList = new ArrayList<PCEPRequestParameterObject>();
+ requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 10, false, false));
+ requestsList.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 10, false, false));
+ notifications.add(new CompositeNotifyObject(requestsList, notificationsList));
+ specMessage = new PCEPNotificationMessage(notifications);
+ assertEquals(deserMsg("src/test/resources/PCNtf.5.bin"), asList((PCEPMessage) specMessage));
+ }
+
+ @Test
+ public void testErrorMessageValidatoinFromBin() throws IOException, PCEPDeserializerException, PCEPDocumentedException, DeserializerException, DocumentedException {
+ List<PCEPErrorObject> errorsList = new ArrayList<PCEPErrorObject>();
+ errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+
+ PCEPErrorMessage specMessage = new PCEPErrorMessage(errorsList);
+ assertEquals(deserMsg("src/test/resources/PCErr.1.bin"), asList((PCEPMessage) specMessage));
+
+ List<PCEPRequestParameterObject> requests = new ArrayList<PCEPRequestParameterObject>();
+ requests.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 3, 1, false, false));
+
+ List<CompositeErrorObject> errors = new ArrayList<CompositeErrorObject>();
+ errors.add(new CompositeErrorObject(requests, errorsList));
+
+ specMessage = new PCEPErrorMessage(errors);
+ assertEquals(deserMsg("src/test/resources/PCErr.2.bin"), asList((PCEPMessage) specMessage));
+
+ specMessage = new PCEPErrorMessage(new PCEPOpenObject(0, 0, 0), errorsList, null);
+ assertEquals(deserMsg("src/test/resources/PCErr.3.bin"), asList((PCEPMessage) specMessage));
+
+ requests = new ArrayList<PCEPRequestParameterObject>();
+ requests.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 53, false, false));
+
+ errors = new ArrayList<CompositeErrorObject>();
+ errors.add(new CompositeErrorObject(requests, errorsList));
+
+ specMessage = new PCEPErrorMessage(errors);
+ assertEquals(deserMsg("src/test/resources/PCErr.3b.bin"), asList((PCEPMessage) specMessage));
+
+ errorsList = new ArrayList<PCEPErrorObject>();
+ errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+ errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+ errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+
+ specMessage = new PCEPErrorMessage(null, errorsList, null);
+ assertEquals(deserMsg("src/test/resources/PCErr.4.bin"), asList((PCEPMessage) specMessage));
+
+ requests = new ArrayList<PCEPRequestParameterObject>();
+ requests.add(new PCEPRequestParameterObject(true, false, false, false, false, false, false, false, (short) 1, 53, false, false));
+
+ errorsList = new ArrayList<PCEPErrorObject>();
+ errorsList.add(new PCEPErrorObject(PCEPErrors.UNRECOGNIZED_OBJ_CLASS));
+
+ errors = new ArrayList<CompositeErrorObject>();
+ errors.add(new CompositeErrorObject(requests, errorsList));
+ errors.add(new CompositeErrorObject(requests, errorsList));
+
+ specMessage = new PCEPErrorMessage(errors);
+ assertEquals(deserMsg("src/test/resources/PCErr.5.bin"), asList((PCEPMessage) specMessage));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.concepts.ASNumber;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.IPv6Address;
+import org.opendaylight.protocol.concepts.IPv6Prefix;
+import org.opendaylight.protocol.concepts.SharedRiskLinkGroup;
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.concepts.UnnumberedInterfaceIdentifier;
+import org.opendaylight.protocol.pcep.impl.subobject.XROAsNumberSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROIPv4PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROIPv6PrefixSubobjectParser;
+import org.opendaylight.protocol.pcep.impl.subobject.XROUnnumberedInterfaceSubobjectParser;
+import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
+import org.opendaylight.protocol.pcep.subobject.XROSubobjectAttribute;
+import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
+
+public class PCEPXROSubobjectParserTest {
+
+ @Test
+ public void testSerDeser() throws PCEPDeserializerException, IOException {
+ final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/PackOfXROSubobjects.bin");
+ final List<ExcludeRouteSubobject> objsToTest = PCEPXROSubobjectParser.parse(bytesFromFile);
+
+ assertEquals(5, objsToTest.size());
+
+ assertEquals(
+ objsToTest.get(0),
+ new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(
+ new byte[] { (byte) 192, (byte) 168, (byte) 0, (byte) 0 }), 16), true, XROSubobjectAttribute.NODE));
+ assertEquals(
+ objsToTest.get(1),
+ new XROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(
+ new byte[] { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x90, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78,
+ (byte) 0x90, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0, (byte) 0 }), 112), true,
+ XROSubobjectAttribute.INTERFACE));
+ assertEquals(
+ objsToTest.get(2),
+ new XROUnnumberedInterfaceSubobject(new IPv4Address(
+ new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0x20 }), new UnnumberedInterfaceIdentifier(0x1234L), false,
+ XROSubobjectAttribute.SRLG));
+ assertEquals(objsToTest.get(3), new XROAsNumberSubobject(new ASNumber(0x1234), false));
+ assertEquals(objsToTest.get(4), new XROSRLGSubobject(new SharedRiskLinkGroup(0x12345678L), false));
+
+ assertArrayEquals(bytesFromFile, PCEPXROSubobjectParser.put(objsToTest));
+
+ }
+
+ @Test
+ public void testDifferentLengthExceptions() {
+ final byte[] bytes = { (byte) 0x00 }; //not empty but not enought data for parsing subobjects
+
+ try {
+ XROAsNumberSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ XROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ XROIPv4PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+
+ try {
+ XROIPv6PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final PCEPDeserializerException e) {
+ }
+ }
+
+ @Test
+ public void testNullExceptions() throws PCEPDeserializerException {
+ final byte[] bytes = null; //not empty but not enought data for parsing subobjects
+
+ try {
+ XROAsNumberSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ XROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ XROIPv4PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ XROIPv6PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testUnknownInstanceExceptions() {
+
+ final ExcludeRouteSubobject instance = new ExcludeRouteSubobject(true) {
+ };
+
+ try {
+ XROAsNumberSubobjectParser.put(instance);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ XROUnnumberedInterfaceSubobjectParser.put(instance);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ XROIPv4PrefixSubobjectParser.put(instance);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ final byte[] ipv6addr = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+ XROIPv4PrefixSubobjectParser.put(new XROIPPrefixSubobject<IPv6Prefix>(new IPv6Prefix(new IPv6Address(ipv6addr), 1), false, XROSubobjectAttribute.INTERFACE));
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ XROIPv6PrefixSubobjectParser.put(instance);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ final byte[] ipv4addr = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+ XROIPv6PrefixSubobjectParser.put(new XROIPPrefixSubobject<IPv4Prefix>(new IPv4Prefix(new IPv4Address(ipv4addr), 1), false, XROSubobjectAttribute.INTERFACE));
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ }
+
+ @Test
+ public void testEmptyExceptions() throws PCEPDeserializerException {
+ final byte[] bytes = {}; //not empty but not enought data for parsing subobjects
+
+ try {
+ XROAsNumberSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ XROUnnumberedInterfaceSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ XROIPv4PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+
+ try {
+ XROIPv6PrefixSubobjectParser.parse(bytes, true);
+ fail("");
+ } catch (final IllegalArgumentException e) {
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import org.opendaylight.protocol.pcep.PCEPCloseTermination;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject.Reason;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.Timer;
+
+public class ServerSessionMock extends PCEPSessionImpl {
+
+ private final MockPCE client;
+
+ public ServerSessionMock(final PCEPSessionListener listener, final PCEPSessionListener client) {
+ super(new MockDispatcher(), new Timer(), new PCEPConnection() {
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ try {
+ return new InetSocketAddress(InetAddress.getByName("localhost"), 4189);
+ } catch (final UnknownHostException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public PCEPSessionListener getListener() {
+ return listener;
+ }
+
+ @Override
+ public PCEPSessionPreferences getProposal() {
+ return new PCEPSessionPreferences(new PCEPOpenObject(4, 9, 2));
+ }
+
+ @Override
+ public PCEPSessionProposalChecker getProposalChecker() {
+ return new SimpleSessionProposalChecker();
+ }
+ }, new PCEPMessageFactory(), 5, 30);
+ this.client = (MockPCE) client;
+ }
+
+ @Override
+ public void sendMessage(final PCEPMessage msg) {
+ this.lastMessageSentAt = System.nanoTime();
+ this.client.onMessage(this, msg);
+ }
+
+ @Override
+ public void close() {
+ this.client.onSessionTerminated(this, new PCEPCloseTermination(Reason.UNKNOWN));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Simple Session Listener that is notified about messages and changes in the session.
+ */
+public class SimpleSessionListener extends PCEPSessionListener {
+
+ public List<PCEPMessage> messages = new ArrayList<PCEPMessage>();
+
+ public boolean up = false;
+
+ private static final Logger logger = LoggerFactory.getLogger(SimpleSessionListener.class);
+
+ public SimpleSessionListener() {
+ }
+
+ @Override
+ public void onMessage(PCEPSession session, PCEPMessage message) {
+ logger.debug("Received message: " + message.getClass() + " " + message);
+ this.messages.add(message);
+ }
+
+ @Override
+ public synchronized void onSessionUp(PCEPSession session, PCEPOpenObject local,
+ PCEPOpenObject remote) {
+ logger.debug("Session up.");
+ this.up = true;
+ this.notifyAll();
+ }
+
+ @Override
+ public void onSessionDown(PCEPSession session, PCEPCloseObject reason, Exception e) {
+ logger.debug("Session down.");
+ this.up = false;
+ //this.notifyAll();
+ }
+
+ @Override
+ public void onSessionTerminated(PCEPSession session,
+ TerminationReason cause) {
+ logger.debug("Session terminated. Cause : " + cause.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl;
+
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ *
+ */
+public class SimpleSessionProposalChecker extends PCEPSessionProposalChecker {
+
+ @Override
+ public Boolean checkSessionCharacteristics(SessionPreferences openObj) {
+ return true;
+ }
+
+ @Override
+ public PCEPSessionPreferences getNewProposal(SessionPreferences open) {
+ return new PCEPSessionPreferences(new PCEPOpenObject(1, 1, 0, null));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.tlv;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.tlv.LSPStateDBVersionTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class LSPStateDBVersionTlvParserTest {
+ @Test
+ public void testEquality() throws IOException, PCEPDeserializerException {
+ final LSPStateDBVersionTlv objToTest1a = (LSPStateDBVersionTlv) PCEPTlvParser.parse(
+ ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv1.bin")).get(0);
+ final LSPStateDBVersionTlv objToTest1b = (LSPStateDBVersionTlv) PCEPTlvParser.parse(
+ ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv1.bin")).get(0);
+ final LSPStateDBVersionTlv objToTest2 = (LSPStateDBVersionTlv) PCEPTlvParser.parse(
+ ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv2.bin")).get(0);
+
+ assertTrue(objToTest1a.equals(objToTest1a));
+ assertFalse(objToTest1a.equals(objToTest2));
+ assertFalse(objToTest1a == objToTest1b);
+ assertTrue(objToTest1a.equals(objToTest1b));
+ }
+
+ @Test
+ public void testSerialization() throws PCEPDeserializerException, IOException {
+ final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv1.bin");
+
+ final LSPStateDBVersionTlv objToTest = (LSPStateDBVersionTlv) PCEPTlvParser.parse(bytesFromFile).get(0);
+ assertEquals(objToTest.getDbVersion(), 128L);
+
+ final byte[] bytesActual = PCEPTlvParser.put(objToTest);
+
+ assertArrayEquals(bytesFromFile, bytesActual);
+ }
+
+ @Test
+ public void testConstruction() throws PCEPDeserializerException, IOException {
+ final LSPStateDBVersionTlv expected = (LSPStateDBVersionTlv) PCEPTlvParser.parse(
+ ByteArray.fileToBytes("src/test/resources/LSPStateDBVersionTlv1.bin")).get(0);
+ final LSPStateDBVersionTlv actual = new LSPStateDBVersionTlv(128L);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test(expected = PCEPDeserializerException.class)
+ public void testValidityControl() throws Exception {
+ /*
+ * Should throw exception
+ */
+ PCEPTlvParser.parse(ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlvInvalid1.bin"));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.impl.tlv;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.pcep.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
+import org.opendaylight.protocol.pcep.tlv.PCEStatefulCapabilityTlv;
+import org.opendaylight.protocol.util.ByteArray;
+
+public class PCEStatefulCapabilityTlvParserTest {
+ @Test
+ public void testEquality() throws IOException, PCEPDeserializerException {
+ final PCEStatefulCapabilityTlv objToTest1a = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(
+ ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv1.bin")).get(0);
+ final PCEStatefulCapabilityTlv objToTest1b = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(
+ ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv1.bin")).get(0);
+ final PCEStatefulCapabilityTlv objToTest2 = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(
+ ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv2.bin")).get(0);
+
+ assertTrue(objToTest1a.equals(objToTest1a));
+ assertFalse(objToTest1a.equals(objToTest2));
+ assertFalse(objToTest1a == objToTest1b);
+ assertTrue(objToTest1a.equals(objToTest1b));
+ }
+
+ @Test
+ public void testSerialization() throws PCEPDeserializerException, IOException {
+ final byte[] bytesFromFile = ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv1.bin");
+
+ final PCEStatefulCapabilityTlv objToTest = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(bytesFromFile).get(0);
+ assertTrue(objToTest.isUpdate());
+ assertTrue(objToTest.isVersioned());
+
+ final byte[] bytesActual = PCEPTlvParser.put(objToTest);
+
+ assertArrayEquals(bytesFromFile, bytesActual);
+ }
+
+ @Test
+ public void testConstruction() throws PCEPDeserializerException, IOException {
+ final PCEStatefulCapabilityTlv expected = (PCEStatefulCapabilityTlv) PCEPTlvParser.parse(
+ ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlv1.bin")).get(0);
+
+ final PCEStatefulCapabilityTlv actual = new PCEStatefulCapabilityTlv(false, true, true);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test(expected = PCEPDeserializerException.class)
+ public void testValidityControl() throws Exception {
+ /*
+ * Should throw exception
+ */
+ PCEPTlvParser.parse(ByteArray.fileToBytes("src/test/resources/PCEStatefulCapabilityTlvInvalid1.bin"));
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>protocol-parent</artifactId>
+ <version>0.1</version>
+ </parent>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>pcep-parent</artifactId>
+ <description>PCEP protocol parent</description>
+ <packaging>pom</packaging>
+ <version>1.0</version>
+ <name>${project.artifactId}</name>
+
+ <modules>
+ <module>api</module>
+ <module>impl</module>
+ <module>testtool</module>
+ </modules>
+</project>
--- /dev/null
+target
+.settings
+.classpath
+.project
--- /dev/null
+import java.util.Queue
+
+import org.opendaylight.protocol.pcep.PCEPMessage
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject
+import org.opendaylight.protocol.pcep.tool.MessageGeneratorService
+
+class GroovyReplyMessageGenerator implements MessageGeneratorService {
+
+ public GroovyReplyMessageGenerator() {
+ }
+
+ @Override
+ public Queue<PCEPMessage> generateMessages() {
+ def queue = new LinkedList<PCEPMessage>()
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ return queue
+ }
+}
\ No newline at end of file
--- /dev/null
+import java.util.Queue
+
+import org.opendaylight.protocol.pcep.PCEPMessage
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject
+import org.opendaylight.protocol.pcep.tool.MessageGeneratorService
+
+class GroovyReplyMessageGenerator implements MessageGeneratorService {
+
+ public GroovyReplyMessageGenerator() {
+ }
+
+ @Override
+ public Queue<PCEPMessage> generateMessages() {
+ def queue = new LinkedList<PCEPMessage>()
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ return queue
+ }
+}
\ No newline at end of file
--- /dev/null
+import java.util.Queue
+
+import org.opendaylight.protocol.pcep.PCEPMessage
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject
+import org.opendaylight.protocol.pcep.tool.MessageGeneratorService
+
+class GroovyReplyMessageGenerator implements MessageGeneratorService {
+
+ public GroovyReplyMessageGenerator() {
+ }
+
+ @Override
+ public Queue<PCEPMessage> generateMessages() {
+ def queue = new LinkedList<PCEPMessage>()
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ return queue
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>pcep-parent</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>pcep-testtool</artifactId>
+ <description>PCEP Interop Testing Tool</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>${logback.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-impl</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-impl</artifactId>
+ <version>1.0</version>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-all</artifactId>
+ <version>2.0.2</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.protocol.pcep.testtool
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>1.7.1</version>
+ <configuration>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <transformers>
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>org.opendaylight.protocol.pcep.testtool.Main</mainClass>
+ </transformer>
+ </transformers>
+ <shadedArtifactAttached>true</shadedArtifactAttached>
+ <shadedClassifierName>executable</shadedClassifierName>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.testtool;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPConnectionFactory;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
+import org.opendaylight.protocol.pcep.PCEPSessionProposal;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalCheckerFactory;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
+import org.opendaylight.protocol.pcep.impl.PCEPConnectionImpl;
+import org.opendaylight.protocol.pcep.impl.PCEPDispatcherImpl;
+import org.opendaylight.protocol.pcep.impl.PCEPSessionProposalCheckerFactoryImpl;
+import org.opendaylight.protocol.pcep.impl.PCEPSessionProposalFactoryImpl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+public class Main {
+
+ public static String usage = "DESCRIPTION:\n" + "\tCreates a server with given parameters. As long as it runs, it accepts connections "
+ + "from PCCs.\n" + "USAGE:\n" + "\t-a, --address\n" + "\t\tthe ip address to which is this server bound.\n"
+ + "\t\tFormat: x.x.x.x:y where y is port number.\n\n" +
+
+ "\t-d, --deadtimer\n" + "\t\tin seconds, value of the desired deadtimer\n"
+ + "\t\tAccording to RFC5440, recommended value for deadtimer is 4 times the value\n"
+ + "\t\tof KeepAlive timer. If it's not, a warning is printed.\n"
+ + "\t\tIf not set, it's value will be derived from KeepAlive timer value.\n\n" +
+
+ "\t-ka, --keepalive\n" + "\t\tin seconds, value of the desired KeepAlive timer.\n"
+ + "\t\tIf not present, KeepAlive timer will be set to recommended value (30s).\n\n" +
+
+ "\t--stateful\n" + "\t\tpassive stateful\n\n" +
+
+ "\t--active\n" + "\t\tactive stateful (implies --stateful)\n\n" +
+
+ "\t--versioned\n" + "\t\tversioned stateful (implies --stateful)\n\n" +
+
+ "\t--instant\n"
+ + "\t\tinstantiated stateful, <seconds> cleanup timeout (default value, if not included = 0) (implies --stateful)\n\n" +
+
+ "\t-arm, --autoResponseMessages <path to file>\n"
+ + "\t\t <path to file> with groovy script which implements MessageGeneratorService.\n"
+ + "\t\t Messages are used as auto response for every message received. Purely for testing puposes! \n\n" +
+
+ "\t-psm, --periodicallySendMessages <path to file> <period>\n"
+ + "\t\t <path to file> with groovy script which implements MessageGeneratorService followed by <period> in seconds.\n"
+ + "\t\t Messages which are sent periodically. Purely for testing puposes! \n\n" +
+
+ "\t-snm, --sendNowMessage <path to file>\n"
+ + "\t\t <path to file> with groovy script which implements MessageGeneratorService.\n"
+ + "\t\t Messages are sent in defined states defined by programmer. Purely for testing puposes! \n\n" +
+
+ "\t--help\n" + "\t\tdisplay this help and exits\n\n" +
+
+ "With no parameters, this help is printed.";
+
+ public static void main(final String[] args) throws IOException {
+ if (args.length == 0 || (args.length == 1 && args[0].equalsIgnoreCase("--help"))) {
+ System.out.println(Main.usage);
+ return;
+ }
+
+ InetSocketAddress address = null;
+ int keepAliveValue = 30;
+ int deadTimerValue = 0;
+ boolean stateful = false;
+ boolean active = false;
+ boolean versioned = false;
+ boolean instant = false;
+ String autoResponseMessagesSrc = null;
+ String sendNowMessageSrc = null;
+ String periodicallySendMessagesSrc = null;
+ int period = 0;
+ int timeout = 0;
+
+ int i = 0;
+ while (i < args.length) {
+ if (args[i].equalsIgnoreCase("-a") || args[i].equalsIgnoreCase("--address")) {
+ final String[] ip = args[i + 1].split(":");
+ address = new InetSocketAddress(InetAddress.getByName(ip[0]), Integer.valueOf(ip[1]));
+ i++;
+ } else if (args[i].equalsIgnoreCase("-d") || args[i].equalsIgnoreCase("--deadtimer")) {
+ deadTimerValue = Integer.valueOf(args[i + 1]);
+ i++;
+ } else if (args[i].equalsIgnoreCase("-ka") || args[i].equalsIgnoreCase("--keepalive")) {
+ keepAliveValue = Integer.valueOf(args[i + 1]);
+ i++;
+ } else if (args[i].equalsIgnoreCase("--stateful")) {
+ stateful = true;
+ } else if (args[i].equalsIgnoreCase("--active")) {
+ stateful = true;
+ active = true;
+ } else if (args[i].equalsIgnoreCase("--versioned")) {
+ stateful = true;
+ versioned = true;
+ } else if (args[i].equalsIgnoreCase("--instant")) {
+ stateful = true;
+ instant = true;
+ if (Integer.valueOf(args[i + 1]) > 0 && Integer.valueOf(args[i + 1]) < Integer.MAX_VALUE) {
+ timeout = Integer.valueOf(args[i + 1]);
+ i++;
+ }
+ } else if (args[i].equalsIgnoreCase("--autoResponseMessages") || args[i].equalsIgnoreCase("-arm")) {
+ autoResponseMessagesSrc = args[i + 1];
+ i++;
+ } else if (args[i].equalsIgnoreCase("--periodicallySendMessages") || args[i].equalsIgnoreCase("-psm")) {
+ periodicallySendMessagesSrc = args[i + 1];
+ i++;
+ period = Integer.valueOf(args[i + 1]);
+ i++;
+ } else if (args[i].equalsIgnoreCase("--sendNowMessage") || args[i].equalsIgnoreCase("-snm")) {
+ sendNowMessageSrc = args[i + 1];
+ i++;
+ } else {
+ System.out.println("WARNING: Unrecognized argument: " + args[i]);
+ }
+ i++;
+ }
+ if (deadTimerValue != 0 && deadTimerValue != keepAliveValue * 4) {
+ System.out.println("WARNING: The value of DeadTimer should be 4 times the value of KeepAlive.");
+ }
+ if (deadTimerValue == 0) {
+ deadTimerValue = keepAliveValue * 4;
+ }
+
+ final PCEPSessionListenerFactory slf = new TestingSessionListenerFactory(autoResponseMessagesSrc, periodicallySendMessagesSrc, period, sendNowMessageSrc);
+ final PCEPSessionProposalFactory spf = new PCEPSessionProposalFactoryImpl(deadTimerValue, keepAliveValue, stateful, active, versioned, instant, timeout);
+ final PCEPSessionProposalCheckerFactory spcf = new PCEPSessionProposalCheckerFactoryImpl();
+
+ final PCEPSessionProposal prefs = spf.getSessionProposal(address, 0);
+
+ final DispatcherImpl d = new DispatcherImpl(Executors.defaultThreadFactory());
+ final PCEPDispatcherImpl dispatcher = new PCEPDispatcherImpl(d, spf);
+
+ try {
+ dispatcher.createServer(address, new PCEPConnectionFactory() {
+ @Override
+ public PCEPConnection createProtocolConnection(final InetSocketAddress address) {
+ final PCEPSessionProposalChecker checker = spcf.getPreferencesChecker(address);
+ final PCEPSessionListener lsnr = slf.getSessionListener(address.getAddress());
+
+ return new PCEPConnectionImpl(address, lsnr, prefs.getProposal(), checker);
+ }
+
+ @Override
+ public void setProposal(final PCEPSessionProposalFactory proposals, final InetSocketAddress address, final int sessionId) {
+ }
+ });
+ // final ProtocolServer s = dispatcher.createServer(address, slf, spf, spcf);
+
+ // try {
+ // Thread.sleep(10000);
+ // } catch (final InterruptedException e) {
+ // e.printStackTrace();
+ // }
+ //
+ // s.close();
+
+ } finally {
+ ((PCEPSessionProposalCheckerFactoryImpl) spcf).close();
+ d.stop();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.testtool;
+
+import java.util.Queue;
+
+import org.opendaylight.protocol.pcep.PCEPMessage;
+
+public interface MessageGeneratorService {
+ public Queue<PCEPMessage> generateMessages();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.testtool;
+
+import java.net.InetAddress;
+
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
+
+/**
+ *
+ */
+public class SessionListenerFactory extends PCEPSessionListenerFactory {
+
+ @Override
+ public PCEPSessionListener getSessionListener(InetAddress address) {
+ return new SimpleSessionListener();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.testtool;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+
+/**
+ * Simple Session Listener that is notified about messages and changes in the session.
+ */
+public class SimpleSessionListener extends PCEPSessionListener {
+
+ public List<PCEPMessage> messages = new ArrayList<PCEPMessage>();
+
+ public boolean up = false;
+
+ private static final Logger logger = LoggerFactory.getLogger(SimpleSessionListener.class);
+
+ public SimpleSessionListener() {
+ }
+
+ @Override
+ public void onMessage(PCEPSession session, PCEPMessage message) {
+ logger.debug("Received message: " + message);
+ this.messages.add(message);
+ }
+
+ @Override
+ public void onSessionUp(PCEPSession session, PCEPOpenObject local,
+ PCEPOpenObject remote) {
+ logger.debug("Session up.");
+ this.up = true;
+ //this.notifyAll();
+ }
+
+ @Override
+ public void onSessionDown(PCEPSession session, PCEPCloseObject reason, Exception e) {
+ logger.debug("Session down.");
+ this.up = false;
+ //this.notifyAll();
+ }
+
+ @Override
+ public void onSessionTerminated(PCEPSession session,
+ TerminationReason cause) {
+ logger.debug("Session terminated. Cause : " + cause.toString());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.testtool;
+
+import groovy.lang.GroovyClassLoader;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.protocol.framework.TerminationReason;
+import org.opendaylight.protocol.concepts.IPv4Address;
+import org.opendaylight.protocol.concepts.IPv4Prefix;
+import org.opendaylight.protocol.concepts.Prefix;
+import org.opendaylight.protocol.pcep.PCEPMessage;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.message.PCEPXRAddTunnelMessage;
+import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
+import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
+import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
+import org.opendaylight.protocol.pcep.object.PCEPLspObject;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
+import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
+
+public class TestingSessionListener extends PCEPSessionListener {
+
+ public List<PCEPMessage> messages = new ArrayList<PCEPMessage>();
+
+ private static final Logger logger = LoggerFactory.getLogger(TestingSessionListener.class);
+
+ public final Queue<PCEPMessage> replyMessages;
+ public final Queue<PCEPMessage> sendNowMessages;
+ public final Queue<PCEPMessage> periodicalMessages;
+ public final int period;
+
+ private class MessageTimer extends TimerTask {
+ private final PCEPMessage message;
+ private final PCEPSession session;
+
+ MessageTimer(final PCEPMessage message, final PCEPSession session) {
+ this.message = message;
+ this.session = session;
+ }
+
+ @Override
+ public void run() {
+ this.session.sendMessage(this.message);
+ }
+ }
+
+ public TestingSessionListener() {
+ /**
+ * default messages are set to null
+ */
+ this.period = 0;
+ this.replyMessages = new LinkedList<PCEPMessage>();
+ this.sendNowMessages = new LinkedList<PCEPMessage>();
+ this.periodicalMessages = new LinkedList<PCEPMessage>();
+ }
+
+ public TestingSessionListener(final String autoResponseMessagesSrc, final String periodicallySendMessagesSrc, final int period,
+ final String sendNowMessageSrc) {
+ this.period = period;
+ this.replyMessages = this.loadMessageGeneratorFromFile(autoResponseMessagesSrc).generateMessages();
+ this.sendNowMessages = this.loadMessageGeneratorFromFile(sendNowMessageSrc).generateMessages();
+ this.periodicalMessages = this.loadMessageGeneratorFromFile(periodicallySendMessagesSrc).generateMessages();
+ }
+
+ /**
+ * Periodically send messages from loaded queue.
+ *
+ * @param session the session used to send message
+ * @param period the time between two sent messages
+ */
+ public void sendPeriodically(final PCEPSession session, final int seconds) {
+ if (!this.periodicalMessages.isEmpty()) {
+ this.sendPeriodically(session, this.periodicalMessages.poll(), seconds);
+ } else
+ logger.debug("DON'T starting PERIODICAL sender. Messages queue is empty.");
+ }
+
+ /**
+ * Periodically send specified message.
+ *
+ * @param session the session used to send message
+ * @param message the message to send
+ * @param period the time between two sent messages
+ */
+ public void sendPeriodically(final PCEPSession session, final PCEPMessage message, final int seconds) {
+ final Timer timer = new Timer();
+
+ logger.debug("Starting periodical sending of messages with {} seconds delay.", seconds);
+ timer.schedule(new MessageTimer(message, session), seconds * 1000);
+ }
+
+ public void sendNow(final PCEPSession session) {
+ if (!this.sendNowMessages.isEmpty()) {
+ final PCEPMessage msg = this.sendNowMessages.poll();
+ this.sendNow(session, msg);
+ } else
+ logger.debug("DON'T sending NOW. Messages queue is empty.");
+ }
+
+ public void sendNow(final PCEPSession session, final PCEPMessage message) {
+ logger.debug("Sending NOW.");
+ session.sendMessage(message);
+ }
+
+ @Override
+ public void onMessage(final PCEPSession session, final PCEPMessage message) {
+ logger.debug("Received message: " + message);
+ this.messages.add(message);
+
+ // if (!this.replyMessages.isEmpty()) {
+ // this.logger.debug("Remaining messages in queue: {}", this.replyMessages.size());
+ // session.sendMessage(this.replyMessages.poll());
+ // } else
+ // this.logger.debug("Reply messages queue is empty.");
+ }
+
+ @Override
+ public void onSessionUp(final PCEPSession session, final PCEPOpenObject local, final PCEPOpenObject remote) {
+ logger.debug("Session up.");
+ final List<ExplicitRouteSubobject> subs = new ArrayList<ExplicitRouteSubobject>();
+ subs.add(new EROIPPrefixSubobject<Prefix<?>>(new IPv4Prefix(new IPv4Address(new byte[] { 10, 1, 1, 2 }), 32), false));
+ subs.add(new EROIPPrefixSubobject<Prefix<?>>(new IPv4Prefix(new IPv4Address(new byte[] { 2, 2, 2, 2 }), 32), false));
+ session.sendMessage(new PCEPXRAddTunnelMessage(new PCEPLspObject(23, false, false, false, false), new PCEPEndPointsObject<IPv4Address>(new IPv4Address(new byte[] {
+ 1, 1, 1, 1 }), new IPv4Address(new byte[] { 2, 2, 2, 2 })), new PCEPExplicitRouteObject(subs, false)));
+ this.sendNow(session);
+ this.sendPeriodically(session, this.period);
+ }
+
+ @Override
+ public void onSessionDown(final PCEPSession session, final PCEPCloseObject reason, final Exception e) {
+ logger.debug("Session down because: " + reason);
+ try {
+ session.close();
+ } catch (final IOException ex) {
+ logger.warn("Session could not be closed.", e);
+ }
+ }
+
+ @Override
+ public void onSessionTerminated(final PCEPSession session, final TerminationReason cause) {
+ logger.debug("Session terminated. Cause : " + cause.toString());
+ }
+
+ private MessageGeneratorService loadMessageGeneratorFromFile(final String path) {
+ try {
+ final GroovyClassLoader l = new GroovyClassLoader();
+ final Class<?> scriptClass = l.parseClass(new File(path));
+ l.close();
+ logger.debug("Loaded '{}'", path);
+ final MessageGeneratorService generator = (MessageGeneratorService) scriptClass.newInstance();
+ logger.debug("Instantiated '{}'", path);
+ return generator;
+ } catch (final Exception e) {
+ logger.error("Failed to load '{}'. Using empty queue.", path);
+ return new MessageGeneratorService() {
+
+ @Override
+ public Queue<PCEPMessage> generateMessages() {
+ return new LinkedList<PCEPMessage>();
+ }
+ };
+ }
+
+ }
+
+ @SuppressWarnings("unused")
+ private MessageGeneratorService loadMessageGeneratorFormSysResource(final String path) {
+ try {
+ final InputStream is = this.getClass().getResourceAsStream(path);
+ final BufferedReader buffReader = new BufferedReader(new InputStreamReader(is));
+ final StringBuilder script = new StringBuilder();
+ String scriptLine;
+ while ((scriptLine = buffReader.readLine()) != null) {
+ script.append(scriptLine + "\n");
+ }
+ final GroovyClassLoader l = new GroovyClassLoader();
+ final Class<?> scriptClass = l.parseClass(script.toString());
+ l.close();
+ logger.debug("Loaded '{}'", path);
+ final MessageGeneratorService generator = (MessageGeneratorService) scriptClass.newInstance();
+ logger.debug("Instantiated '{}'", path);
+ return generator;
+
+ } catch (final Exception e) {
+ logger.error("Failed to load '{}' from system resources. Using empty queue.", path);
+ return new MessageGeneratorService() {
+
+ @Override
+ public Queue<PCEPMessage> generateMessages() {
+ return new LinkedList<PCEPMessage>();
+ }
+ };
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.testtool;
+
+import java.net.InetAddress;
+
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
+
+/**
+ *
+ */
+public class TestingSessionListenerFactory extends PCEPSessionListenerFactory {
+
+ private final String autoResponseMessagesSrc;
+ private final String periodicallySendMessagesSrc;
+ private final String sendNowMessageSrc;
+ private final int period;
+
+ public TestingSessionListenerFactory(String autoResponseMessagesSrc, String periodicallySendMessagesSrc, int period, String sendNowMessageSrc) {
+ this.autoResponseMessagesSrc = autoResponseMessagesSrc;
+ this.periodicallySendMessagesSrc = periodicallySendMessagesSrc;
+ this.period = period;
+ this.sendNowMessageSrc = sendNowMessageSrc;
+ }
+
+ @Override
+ public PCEPSessionListener getSessionListener(InetAddress address) {
+ return new TestingSessionListener(this.autoResponseMessagesSrc, this.periodicallySendMessagesSrc, this.period, this.sendNowMessageSrc);
+ }
+
+}
--- /dev/null
+import java.util.Queue
+
+import org.opendaylight.protocol.pcep.PCEPMessage
+import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject
+import org.opendaylight.protocol.pcep.message.PCEPReplyMessage
+import org.opendaylight.protocol.pcep.object.CompositeResponseObject
+import org.opendaylight.protocol.pcep.tool.MessageGeneratorService
+
+class GroovyReplyMessageGenerator implements MessageGeneratorService {
+
+ public GroovyReplyMessageGenerator() {
+ }
+
+ @Override
+ public Queue<PCEPMessage> generateMessages() {
+ def queue = new LinkedList<PCEPMessage>()
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 7 as Short, 6565 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ queue.push(
+ new PCEPReplyMessage(
+ [
+ new CompositeResponseObject(
+ new PCEPRequestParameterObject(true, false, true, false, true, 5 as Short, 235568 as Long, true, false)
+ )
+ ]
+ )
+ )
+
+ return queue
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.testtool;
+
+import org.opendaylight.protocol.framework.DispatcherImpl;
+import org.opendaylight.protocol.framework.SessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPConnection;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPSessionPreferences;
+import org.opendaylight.protocol.pcep.PCEPSessionProposal;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalChecker;
+import org.opendaylight.protocol.pcep.PCEPSessionProposalFactory;
+import org.opendaylight.protocol.pcep.PCEPTlv;
+import org.opendaylight.protocol.pcep.impl.PCEPDispatcherImpl;
+import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
+import org.opendaylight.protocol.pcep.tlv.NodeIdentifierTlv;
+import com.google.common.collect.Lists;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.concurrent.Executors;
+
+public class PCCMock {
+
+ public static void main(final String[] args) throws IOException, InterruptedException {
+ final List<PCEPTlv> tlvs = Lists.newArrayList();
+ tlvs.add(new NodeIdentifierTlv(new byte[] { (byte) 127, (byte) 2, (byte) 3, (byte) 7 }));
+ final PCEPSessionPreferences prop = new PCEPSessionPreferences(new PCEPOpenObject(30, 120, 0, tlvs));
+ final DispatcherImpl di = new DispatcherImpl(Executors.defaultThreadFactory());
+ final PCEPDispatcherImpl d = new PCEPDispatcherImpl(di, new PCEPSessionProposalFactory() {
+
+ @Override
+ public PCEPSessionProposal getSessionProposal(final InetSocketAddress address, final int sessionId) {
+ return new PCEPSessionProposal() {
+
+ @Override
+ public PCEPSessionPreferences getProposal() {
+ return prop;
+ }
+ };
+ }
+ });
+
+ try {
+
+ final PCEPSessionProposalChecker check = new PCEPSessionProposalChecker() {
+ @Override
+ public Boolean checkSessionCharacteristics(final SessionPreferences openObj) {
+ return true;
+ }
+
+ @Override
+ public PCEPSessionPreferences getNewProposal(final SessionPreferences open) {
+ return new PCEPSessionPreferences(new PCEPOpenObject(30, 120, 0, null));
+ }
+ };
+
+ d.createClient(new PCEPConnection() {
+ @Override
+ public InetSocketAddress getPeerAddress() {
+ return new InetSocketAddress("127.0.0.1", 4189);
+ }
+
+ @Override
+ public PCEPSessionProposalChecker getProposalChecker() {
+ return check;
+ }
+
+ @Override
+ public PCEPSessionPreferences getProposal() {
+ return prop;
+ }
+
+ @Override
+ public PCEPSessionListener getListener() {
+ return new SimpleSessionListener();
+ }
+ });
+ // Thread.sleep(5000);
+ // final List<CompositeRequestObject> cro = new ArrayList<CompositeRequestObject>();
+ // cro.add(new CompositeRequestObject(new PCEPRequestParameterObject(false, true, true, true, true, (short)
+ // 4, 123, false, false),
+ // new PCEPEndPointsObject<IPv4Address>(new IPv4Address(InetAddress.getByName("10.0.0.3")), new
+ // IPv4Address(InetAddress.getByName("10.0.0.5")))));
+ // for (int i = 0; i < 3; i++) {
+ // Thread.sleep(1000);
+ // session.sendMessage(new PCEPRequestMessage(cro));
+ // }
+ // Thread.sleep(5000);
+ // Thread.sleep(1000);
+
+ } finally {
+ di.stop();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.pcep.testtool;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
+
+public class PCEPTestingToolTest {
+
+ @Test
+ public void testSimpleSessionListener() {
+ final SimpleSessionListener ssl = new SimpleSessionListener();
+ assertEquals(0, ssl.messages.size());
+ ssl.onMessage(null, new PCEPKeepAliveMessage());
+ assertEquals(1, ssl.messages.size());
+ assertTrue(ssl.messages.get(0) instanceof PCEPKeepAliveMessage);
+ assertFalse(ssl.up);
+ ssl.onSessionUp(null, null, null);
+ assertTrue(ssl.up);
+ ssl.onSessionDown(null, null, null);
+ assertFalse(ssl.up);
+ }
+
+ @Test
+ public void testSessionListenerFactory() {
+ assertTrue(new SessionListenerFactory().getSessionListener(null) instanceof SimpleSessionListener);
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <name>OpenDaylight protocols</name>
+ <url>index.html</url>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>protocol-parent</artifactId>
+ <description>OpenDaylight BGP+PCEP protocol parent</description>
+ <version>0.1</version>
+ <packaging>pom</packaging>
+ <properties>
+ <java.version.source>1.7</java.version.source>
+ <java.version.target>1.7</java.version.target>
+ <jacoco.version>0.6.2.201302030002</jacoco.version>
+ <commons.io.version>2.4</commons.io.version>
+ <checkstyle.version>2.9.1</checkstyle.version>
+ <pmd.version>2.7.1</pmd.version>
+ <dependency.version>2.8</dependency.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <cxf.version>2.6.5</cxf.version>
+ <slf4j.version>1.7.2</slf4j.version>
+ <logback.version>1.0.7</logback.version>
+ <junit.version>4.10</junit.version>
+ <maven.compiler.version>2.5.1</maven.compiler.version>
+ <maven.bundle.version>2.3.7</maven.bundle.version>
+ <jgrapht.version>0.8.3-SNAPSHOT</jgrapht.version>
+ <surefire.version>2.14.1</surefire.version>
+ <commonscodec.version>1.7</commonscodec.version>
+ <guava.version>13.0.1</guava.version>
+ <osgi.version>5.0.0</osgi.version>
+ <osgi.compendium.version>4.0.0</osgi.compendium.version>
+ </properties>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <modules>
+ <module>bgp</module>
+ <module>concepts</module>
+ <module>framework</module>
+ <module>mockito-configuration</module>
+ <module>pcep</module>
+ <module>util</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>${logback.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.8.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>${jacoco.version}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>2.9.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>${pmd.version}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>${maven.antrun.version}</version>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>NPS-APPLICATION Project site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ <!-- mock repository to allow deploy phase without real deployment -->
+ <repository>
+ <id>targetRepo</id>
+ <name>Target folder as mock repository</name>
+ <url>file://${basedir}/target/deploy</url>
+ </repository>
+ </distributionManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven.compiler.version}</version>
+ <configuration>
+ <source>${java.version.source}</source>
+ <target>${java.version.target}</target>
+ <testSource>${java.version.source}</testSource>
+ <testTarget>${java.version.target}</testTarget>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>${jacoco.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>report</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>check</goal>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${basedir}/target/jacoco</outputDirectory>
+ <haltOnFailure>false</haltOnFailure>
+ <check>
+ <classRatio>80</classRatio>
+ </check>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>2.9.1</version>
+ <configuration>
+ <configLocation>build/checkstyle/checkstyle-checker.xml</configLocation>
+ <outputDirectory>${basedir}/target/checkstyle/report</outputDirectory>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <redirectTestOutputToFile>true</redirectTestOutputToFile>
+ <parallel>classes</parallel>
+ <forkCount>1C</forkCount>
+ <reuseForks>false</reuseForks>
+ <perCoreThreadCount>true</perCoreThreadCount>
+ <threadCount>2</threadCount>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>${pmd.version}</version>
+ <configuration>
+ <targetJdk>${java.version.target}</targetJdk>
+ <rulesets>
+ <ruleset>rulesets/basic.xml</ruleset>
+ <ruleset>rulesets/finalizers.xml</ruleset>
+ <ruleset>rulesets/imports.xml</ruleset>
+ <ruleset>rulesets/junit.xml</ruleset>
+ <!--ruleset>rulesets/optimizations.xml</ruleset -->
+ <ruleset>rulesets/strings.xml</ruleset>
+ <ruleset>rulesets/unusedcode.xml</ruleset>
+ </rulesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>${dependency.version}</version>
+ <configuration>
+ <!--failOnWarning>true</failOnWarning -->
+ <ignoreNonCompile>true</ignoreNonCompile>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.fusesource.mvnplugins</groupId>
+ <artifactId>maven-graph-plugin</artifactId>
+ <version>1.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.8</version>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.jacoco</groupId>
+ <artifactId>
+ jacoco-maven-plugin
+ </artifactId>
+ <versionRange>
+ [0.6.2.201302030002,)
+ </versionRange>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ <versionRange>
+ [2.1.4,)
+ </versionRange>
+ <goals>
+ <goal>revision</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>mvnplugins.fusesource.org</id>
+ <url>http://mvnplugins.fusesource.org/repo/release</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ </pluginRepository>
+ </pluginRepositories>
+</project>
--- /dev/null
+
+About ${project.artifactId}
+
+---
+${project.description}
+Project main site.
+---
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+ <body>
+ <head>${project.artifactId}</head>
+ <links>
+ <item name="${project.artifactId}" href="index.html"/>
+ </links>
+
+ <menu ref="modules"/>
+
+ <menu ref="reports"/>
+
+
+ </body>
+</project>
+
--- /dev/null
+target
+.classpath
+.settings
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>nps-util</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.protocol</groupId>
+ <artifactId>protocol-parent</artifactId>
+ <version>0.1</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>util</artifactId>
+ <description>Protocol utilities</description>
+ <packaging>bundle</packaging>
+ <version>1.0</version>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>${commonscodec.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Import-Package>
+ com.google.common.*,
+ javax.net.ssl,
+ org.apache.commons.codec.binary,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.protocol.util
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>util</id>
+ <name>NPS-UTIL Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.apache.commons.codec.binary.Hex;
+
+/**
+ *
+ * Util class for methods working with byte array.
+ *
+ */
+public final class ByteArray {
+ private ByteArray() {
+ }
+
+ /**
+ * Returns a new byte array from given byte array, starting at start index
+ * with the size of the length parameter. Byte array given as parameter
+ * stays untouched.
+ *
+ * @param bytes
+ * original byte array
+ * @param startIndex
+ * beginning index, inclusive
+ * @param length
+ * how many bytes should be in the sub-array
+ * @return a new byte array that is a sub-array of the original
+ */
+ public static byte[] subByte(final byte[] bytes, int startIndex, int length) {
+ if (bytes.length == 0 || length < 0 || length > bytes.length || startIndex < 0 || startIndex > bytes.length || startIndex + length > bytes.length) {
+ throw new IllegalArgumentException("Cannot create subByte, invalid arguments: Length: " + length + " startIndex: " + startIndex);
+ }
+ final byte[] res = new byte[length];
+ System.arraycopy(bytes, startIndex, res, 0, length);
+ return res;
+ }
+
+ /**
+ * Converts byte array to Integer. If there are less bytes in the array as
+ * required (4), the method will push adequate number of zero bytes
+ * prepending given byte array.
+ *
+ * @param bytes
+ * array to be converted to int
+ * @return int
+ */
+ public static int bytesToInt(byte[] bytes) {
+ if (bytes.length > Integer.SIZE / 8) {
+ throw new IllegalArgumentException("Cannot convert bytes to integer. Byte array too big.");
+ }
+ byte[] res = new byte[Integer.SIZE / 8];
+ if (bytes.length != Integer.SIZE / 8) {
+ System.arraycopy(bytes, 0, res, Integer.SIZE / 8 - bytes.length, bytes.length);
+ } else {
+ res = bytes;
+ }
+ final ByteBuffer buff = ByteBuffer.wrap(res);
+ return buff.getInt();
+ }
+
+ /**
+ * Converts byte array to long. If there are less bytes in the array as
+ * required (Long.Size), the method will push adequate number of zero bytes
+ * prepending given byte array.
+ *
+ * @param bytes
+ * array to be converted to long
+ * @return long
+ */
+ public static long bytesToLong(byte[] bytes) {
+ if (bytes.length > Long.SIZE / 8) {
+ throw new IllegalArgumentException("Cannot convert bytes to long.Byte array too big.");
+ }
+ byte[] res = new byte[Long.SIZE / 8];
+ if (bytes.length != Long.SIZE / 8) {
+ System.arraycopy(bytes, 0, res, Long.SIZE / 8 - bytes.length, bytes.length);
+ } else {
+ res = bytes;
+ }
+ final ByteBuffer buff = ByteBuffer.wrap(res);
+ return buff.getLong();
+ }
+
+ /**
+ * Converts byte array to float IEEE 754 format. If there are less bytes in
+ * the array as required (Float.Size), the method will push adequate number
+ * of zero bytes prepending given byte array.
+ *
+ * @param bytes
+ * array to be converted to float
+ * @return float
+ */
+ public static float bytesToFloat(byte[] bytes) {
+ if (bytes.length > Float.SIZE / 8) {
+ throw new IllegalArgumentException("Cannot convert bytes to float.Byte array too big.");
+ }
+ byte[] res = new byte[Float.SIZE / 8];
+ if (bytes.length != Float.SIZE / 8) {
+ System.arraycopy(bytes, 0, res, Float.SIZE / 8 - bytes.length, bytes.length);
+ } else {
+ res = bytes;
+ }
+ final ByteBuffer buff = ByteBuffer.wrap(res);
+ return buff.getFloat();
+ }
+
+ /**
+ * Cuts 'count' number of bytes from the beginning of given byte array.
+ *
+ * @param bytes
+ * array to be cut, cannot be null
+ * @param count
+ * how many bytes needed to be cut, needs to be > 0
+ * @return bytes array without first 'count' bytes
+ */
+ public static byte[] cutBytes(byte[] bytes, int count) {
+ if (bytes.length == 0 || count > bytes.length || count <= 0) {
+ throw new IllegalArgumentException("Cannot cut bytes, invalid arguments: Count: " + count + " bytes.length: " + bytes.length);
+ }
+ return Arrays.copyOfRange(bytes, count, bytes.length);
+ }
+
+ /**
+ * Parse byte to bits, from the leftmost bit.
+ *
+ * @param b
+ * byte to be parsed
+ * @return array of booleans with size of 8
+ */
+ public static boolean[] parseBits(byte b) {
+ final boolean[] bits = new boolean[Byte.SIZE];
+ int j = 0;
+ for (int i = Byte.SIZE - 1; i >= 0; i--) {
+ bits[j] = ((b & (1 << i)) != 0);
+ j++;
+ }
+ return bits;
+ }
+
+ /**
+ * Parses array of bytes to BitSet, from left most bit.
+ *
+ * @param bytes
+ * array of bytes to be parsed
+ * @return BitSet with length = bytes.length * Byte.SIZE
+ */
+ public static BitSet bytesToBitSet(byte[] bytes) {
+ final BitSet bitSet = new BitSet(bytes.length * Byte.SIZE);
+ for (int bytes_iter = 0; bytes_iter < bytes.length; bytes_iter++) {
+ final int offset = bytes_iter * Byte.SIZE;
+ for (int byte_iter = Byte.SIZE - 1; byte_iter >= 0; byte_iter--) {
+ bitSet.set(offset + (Byte.SIZE - byte_iter - 1), (bytes[bytes_iter] & 1 << (byte_iter)) != 0);
+ }
+ }
+ return bitSet;
+ }
+
+ /**
+ * Parses BitSet to bytes, from most left bit.
+ *
+ * @param bitSet
+ * BitSet to be parsed
+ * @param returnedLength
+ * Length of returned array. Overlapping flags are truncated.
+ * @return parsed array of bytes with length of bitSet.length / Byte.SIZE
+ */
+ public static byte[] bitSetToBytes(BitSet bitSet, int returnedLength) {
+ final byte[] bytes = new byte[returnedLength];
+
+ for (int bytes_iter = 0; bytes_iter < bytes.length; bytes_iter++) {
+ final int offset = bytes_iter * Byte.SIZE;
+
+ for (int byte_iter = Byte.SIZE - 1; byte_iter >= 0; byte_iter--) {
+ bytes[bytes_iter] |= (bitSet.get(offset + (Byte.SIZE - byte_iter - 1)) ? 1 << byte_iter : 0);
+ }
+ }
+ return bytes;
+ }
+
+ /**
+ * Parses file to array of bytes
+ *
+ * @param name
+ * path to file to by parsed
+ * @return parsed array of bytes
+ */
+ public static byte[] fileToBytes(String name) throws IOException {
+ final File file = new File(name);
+ int offset = 0;
+ int numRead = 0;
+
+ if (file.length() > Integer.MAX_VALUE) {
+ throw new IOException("Too large file to load in byte array.");
+ }
+
+ final FileInputStream fin = new FileInputStream(file);
+ final byte[] byteArray = new byte[(int) file.length()];
+
+ while (offset < byteArray.length && (numRead = fin.read(byteArray, offset, byteArray.length - offset)) >= 0) {
+ offset += numRead;
+ }
+
+ if (fin != null) {
+ fin.close();
+ }
+
+ return byteArray;
+ }
+
+ /**
+ * Parses integer to array of bytes
+ *
+ * @param num
+ * integer to be parsed
+ * @return parsed array of bytes with length of Integer.SIZE/Byte.SIZE
+ */
+ public static byte[] intToBytes(int num) {
+ final ByteBuffer bytesBuffer = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE);
+ bytesBuffer.putInt(num);
+
+ return bytesBuffer.array();
+ }
+
+ /**
+ * Parses integer to array of bytes
+ *
+ * @param num
+ * integer to be parsed
+ * @return parsed array of bytes with length of Long.SIZE/Byte.SIZE
+ */
+ public static byte[] longToBytes(long num) {
+ final ByteBuffer bytesBuffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
+ bytesBuffer.putLong(num);
+
+ return bytesBuffer.array();
+ }
+
+ /**
+ * Copies range of bits from passed byte and align to right.<br/>
+ *
+ * @param src
+ * source byte to copy from
+ * @param fromBit
+ * bit from which will copy (inclusive) - numbered from 0
+ * @param length
+ * of bits to by copied - <1,8>
+ * @return copied value aligned to right
+ */
+ public static byte copyBitsRange(byte src, int fromBit, int length) {
+ if (fromBit < 0 | fromBit > Byte.SIZE - 1 | length < 1 | length > Byte.SIZE) {
+ throw new IllegalArgumentException("fromBit or toBit is out of range.");
+ }
+ if (fromBit + length > Byte.SIZE) {
+ throw new IllegalArgumentException("Out of range.");
+ }
+
+ byte retByte = 0;
+ int retI = 0;
+
+ for (int i = fromBit + length - 1; i >= fromBit; i--) {
+
+ if ((src & 1 << (Byte.SIZE - i - 1)) != 0) {
+ retByte |= 1 << retI;
+ }
+
+ retI++;
+ }
+
+ return retByte;
+ }
+
+ /**
+ * Copies whole source byte array to destination from offset.<br/>
+ * Length of src can't be bigger than dest length minus offset
+ *
+ * @param src
+ * byte[]
+ * @param dest
+ * byte[]
+ * @param offset
+ * int
+ */
+ public static void copyWhole(byte[] src, byte[] dest, int offset) {
+ if (dest.length - offset < src.length) {
+ throw new ArrayIndexOutOfBoundsException("Can't copy whole array.");
+ }
+
+ System.arraycopy(src, 0, dest, offset, src.length);
+ }
+
+ /**
+ * Convert array of bytes to java short.<br/>
+ * Size can't be bigger than size of short in bytes.
+ *
+ * @param bytes
+ * byte[]
+ * @return array of bytes
+ */
+ public static short bytesToShort(byte[] bytes) {
+ if (bytes.length > Short.SIZE / Byte.SIZE) {
+ throw new IllegalArgumentException("Cannot convert bytes to short. Byte array too big.");
+ }
+ byte[] res = new byte[Short.SIZE / Byte.SIZE];
+ if (bytes.length != Short.SIZE / Byte.SIZE) {
+ System.arraycopy(bytes, 0, res, Integer.SIZE / Byte.SIZE - bytes.length, bytes.length);
+ } else {
+ res = bytes;
+ }
+ final ByteBuffer buff = ByteBuffer.wrap(res);
+ return buff.getShort();
+ }
+
+ /**
+ * Convert short java representation to array of bytes.
+ *
+ * @param num
+ * short
+ * @return short represented as array of bytes
+ */
+ public static byte[] shortToBytes(short num) {
+ final ByteBuffer bytesBuffer = ByteBuffer.allocate(Short.SIZE / Byte.SIZE);
+ bytesBuffer.putShort(num);
+
+ return bytesBuffer.array();
+ }
+
+ /**
+ * Convert float java representation to array of bytes.
+ *
+ * @param num
+ * float
+ * @return float represented as array of bytes
+ */
+ public static byte[] floatToBytes(float num) {
+ final ByteBuffer bytesBuffer = ByteBuffer.allocate(Float.SIZE / Byte.SIZE);
+ bytesBuffer.putFloat(num);
+
+ return bytesBuffer.array();
+ }
+
+ /**
+ * Pretty print array of bytes as hex encoded string with 16 bytes per line.
+ * Each byte is separated by space, after first 8 bytes there are 2 spaces
+ * instead of one.
+ */
+ public static String bytesToHexString(byte[] array) {
+ return bytesToHexString(array, 16, " ", 8, " ");
+ }
+
+ /**
+ * Pretty-print an array of bytes as hex-encoded string. Separate them
+ * with specified separator.
+ */
+ public static String toHexString(final byte[] array, final String separator) {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < array.length; i++) {
+ sb.append(Hex.encodeHexString(new byte[] { array[i] }));
+ if (i + 1 != array.length)
+ sb.append(separator);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Convert array of bytes to hexadecimal String.
+ *
+ * @param array
+ * @param bytesOnLine
+ * number of bytes that should by displayed in one line
+ * @param byteSeparator
+ * string that will be placed after each byte
+ * @param wordCount
+ * number of bytes that make a 'word' (group of bytes)
+ * @param wordSeparator
+ * string that will be placed after each word
+ * @return Hexadecimal string representation of given byte array
+ */
+ public static String bytesToHexString(byte[] array, int bytesOnLine, String byteSeparator, int wordCount, String wordSeparator) {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < array.length; i++) {
+ sb.append(Hex.encodeHexString(new byte[] { array[i] }));
+ if ((i + 1) % bytesOnLine == 0) {
+ sb.append("\n");
+ } else {
+ sb.append(byteSeparator);
+ if ((i + 1) % wordCount == 0) {
+ sb.append(wordSeparator);
+ }
+ }
+
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Decodes bytes to human readable UTF-8 string. If bytes are not valid
+ * UTF-8, they are represented as raw binary.
+ *
+ * @param bytes
+ * bytes to be decoded to string
+ * @return String representation of passed bytes
+ */
+ public static String bytesToHRString(byte[] bytes) {
+ try {
+ return Charset.forName("UTF-8").newDecoder().decode(ByteBuffer.wrap(bytes)).toString();
+ } catch (final CharacterCodingException e) {
+ return Arrays.toString(bytes);
+ }
+ }
+
+ /**
+ * Searches for byte sequence in given array. Returns the index of first occurrence of
+ * this sequence (where it starts).
+ * @param bytes byte array where to search for sequence
+ * @param sequence to be searched in given byte array
+ * @return -1 if the sequence could not be found in given byte array
+ * int index of first occurrence of the sequence in bytes
+ */
+ public static int findByteSequence(byte[] bytes, byte[] sequence) {
+ if (bytes.length < sequence.length)
+ throw new IllegalArgumentException("Sequence to be found is longer than the given byte array.");
+ if (bytes.length == sequence.length)
+ if (Arrays.equals(bytes, sequence))
+ return 0;
+ else
+ return -1;
+ int j = 0;
+ for (int i = 0; i < bytes.length; i++) {
+ if (bytes[i] == sequence[j]) {
+ j++;
+ if (j == sequence.length)
+ return i - j + 1;
+ } else
+ j = 0;
+ }
+ return -1;
+ }
+
+ private static final byte maskBits[] = new byte[] { 0, -128, -64, -32, -16, -8, -4, -2 };
+ public static final byte[] maskBytes(final byte[] original,
+ final int bits) {
+ if (original.length * 8 < bits)
+ throw new IllegalArgumentException("Attempted to apply invalid mask (too long)");
+
+ final int needbytes = (bits +7) / 8;
+ // We need to have a new copy of the underlying byte array, so that
+ // the original bytes stay untouched
+ final byte[] bytes = Arrays.copyOf(original, original.length);
+
+ final int needmask = bits % 8;
+ if (needmask != 0)
+ bytes[needbytes-1] &= maskBits[needmask];
+
+ // zero-out the rest of the bytes
+ for (int i = needbytes ; i < bytes.length; i++) {
+ bytes[i] = 0;
+ }
+ return bytes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Extension of the TypesafeContainer which supports the notion of a default
+ * key.
+ *
+ * @param <S> Supertype of all objects stored in this container
+ */
+public class DefaultingTypesafeContainer<S> extends TypesafeContainer<S> {
+ private static final long serialVersionUID = 140170613440644179L;
+ private Class<? extends S> defaultKey = null;
+
+ /**
+ * Returns the default entry.
+ *
+ * @return Default entry, or null if no default was set
+ */
+ public S getDefaultEntry() {
+ if (defaultKey == null) {
+ return null;
+ }
+ return defaultKey.cast(getEntry(defaultKey));
+ }
+
+ /**
+ * Sets or resets the default entry.
+ *
+ * @param entry Default entry value. Use null to reset the container
+ * to no default entry.
+ */
+ public void setDefaultEntry(final S entry) {
+ if (defaultKey != null) {
+ removeEntry(defaultKey);
+ defaultKey = null;
+ }
+ if (entry != null) {
+ /*
+ * This is rather obvious: entry is required to be a subclass
+ * of T. This implies that its class conforms to
+ * Class<? extends T>. For some reason, the compiler is not
+ * smart enough to know this.
+ */
+ @SuppressWarnings("unchecked")
+ final Class<? extends S> c = (Class<? extends S>) entry.getClass();
+ defaultKey = c;
+
+ setEntry(defaultKey, entry);
+ }
+ }
+
+ @Override
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("defaultKey", this.defaultKey);
+ return super.addToStringAttributes(toStringHelper);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() * 7 + (defaultKey != null ? defaultKey.hashCode() : 0);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof DefaultingTypesafeContainer == false) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (super.equals(obj)==false) {
+ return false;
+ }
+ Object thatDefaultKey = ((DefaultingTypesafeContainer<?>)obj).defaultKey;
+ if (defaultKey == thatDefaultKey) {
+ return true;
+ }
+ if ((defaultKey == null) != (thatDefaultKey == null)) {
+ return false;
+ }
+ return thatDefaultKey.equals(thatDefaultKey);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+public class RemoveOnlySet<E> implements Set<E> {
+ private final Set<E> set;
+
+ public RemoveOnlySet(final Set<E> set) {
+ this.set = set;
+ }
+
+ public static <T> RemoveOnlySet<T> wrap(final Set<T> set) {
+ return new RemoveOnlySet<T>(set);
+ }
+
+ @Override
+ public boolean add(final E e) {
+ throw new UnsupportedOperationException("Set does not accept additions");
+ }
+
+ @Override
+ public boolean addAll(final Collection<? extends E> c) {
+ throw new UnsupportedOperationException("Set does not accept additions");
+ }
+
+ @Override
+ public void clear() {
+ set.clear();
+ }
+
+ @Override
+ public boolean contains(final Object o) {
+ return set.contains(o);
+ }
+
+ @Override
+ public boolean containsAll(final Collection<?> c) {
+ return set.containsAll(c);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return set.isEmpty();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return set.iterator();
+ }
+
+ @Override
+ public boolean remove(final Object o) {
+ return set.remove(o);
+ }
+
+ @Override
+ public boolean removeAll(final Collection<?> c) {
+ return set.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(final Collection<?> c) {
+ return set.retainAll(c);
+ }
+
+ @Override
+ public int size() {
+ return set.size();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return set.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(final T[] a) {
+ return set.toArray(a);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class SSLUtil {
+ public static SSLContext initializeSecureContext(
+ final String pass, final InputStream ksKeysFile,
+ final InputStream ksTrustFile, final String algorithm)
+ throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
+ FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException {
+
+ Preconditions.checkNotNull(ksTrustFile, "ksTrustFile cannot be null");
+ Preconditions.checkNotNull(ksKeysFile, "ksKeysFile cannot be null");
+
+ final char[] passphrase = pass.toCharArray();
+
+ // First initialize the key and trust material.
+ final KeyStore ksKeys = KeyStore.getInstance("JKS");
+ ksKeys.load(ksKeysFile, passphrase);
+ final KeyStore ksTrust = KeyStore.getInstance("JKS");
+ ksTrust.load(ksTrustFile, passphrase);
+
+ // KeyManager's decide which key material to use.
+ final KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
+ kmf.init(ksKeys, passphrase);
+
+ // TrustManager's decide whether to allow connections.
+ final TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
+ tmf.init(ksTrust);
+
+ final SSLContext sslContext = SSLContext.getInstance("TLS");
+
+ // Create/initialize the SSLContext with key material
+ sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ return sslContext;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Container to store different types of objects and retrieve them back in
+ * a type-safe manner. this is a direct application of Joshua Bloch's typesafe
+ * heterogeneous container pattern from Effective Java.
+ *
+ * @param <S> Supertype of all objects stored in this container
+ */
+public class TypesafeContainer<S> implements Serializable {
+ private static final long serialVersionUID = 4369804407106485605L;
+ private final Map<Class<? extends S>, Object> entries;
+
+ /**
+ * Create a new container with default initial capacity
+ */
+ public TypesafeContainer() {
+ entries = new HashMap<Class<? extends S>, Object>();
+ }
+
+ /**
+ * Create a new container with specified initial capacity
+ *
+ * @param initialCapacity Desired initial capacity
+ */
+ public TypesafeContainer(final int initialCapacity) {
+ entries = new HashMap<Class<? extends S>, Object>(initialCapacity);
+ }
+
+ /**
+ * Get entry types currently present in the container.
+ *
+ * @return Entry types currently present in the contaier
+ */
+ public Set<Class<? extends S>> getEntryTypes() {
+ return entries.keySet();
+ }
+
+ /**
+ * Returns entry of a particular type
+ *
+ * @param clazz Entry type
+ * @return T Entry value, null if entry of specified type is not present
+ */
+ public <T extends S> T getEntry(final Class<T> clazz) {
+ return clazz.cast(entries.get(clazz));
+ }
+
+ /**
+ * Remove the entry for a particular type
+ *
+ * @param clazz Entry type, may not be null
+ */
+ public void removeEntry(final Class<? extends S> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("Entry type may not be null");
+ }
+ entries.remove(clazz);
+ }
+
+ /**
+ * Sets an entry of particular type
+ *
+ * @param clazz Entry type
+ * @param entry Entry value, may not be null
+ */
+ public void setEntry(final Class<? extends S> clazz, final S entry) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("Entry type may not be null");
+ }
+ if (entry == null) {
+ throw new IllegalArgumentException("Entry value may not be null");
+ }
+
+ entries.put(clazz, entry);
+ }
+
+ @Override
+ public String toString(){
+ return addToStringAttributes(Objects.toStringHelper(this)).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+ toStringHelper.add("entries", this.entries);
+ return toStringHelper;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof TypesafeContainer == false) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ return entries.equals(((TypesafeContainer<?>)obj).entries);
+ }
+
+ @Override
+ public int hashCode() {
+ return entries.hashCode();
+ }
+
+}
+
--- /dev/null
+
+About ${project.artifactId}
+
+---
+${project.description}
+---
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="${project.artifactId}">
+
+ <body>
+ <head>${project.artifactId}</head>
+ <links>
+ <item name="${project.artifactId}" href="index.html"/>
+ </links>
+
+ <menu ref="parent"/>
+
+ <menu ref="reports"/>
+
+
+ </body>
+</project>
+
--- /dev/null
+/*
+ * Copyright (c) 2013 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.util;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.BitSet;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ByteArrayTest {
+
+ byte[] before = new byte[] { 15, 28, 4, 6, 9, 10 };
+
+ @Test
+ public void testBytesToFloat() {
+ final float expected = 8581;
+ final byte[] b = ByteArray.floatToBytes(expected);
+ assertEquals(expected, ByteArray.bytesToFloat(b), 50);
+ }
+
+ @Test
+ public void testSubByte() {
+ byte[] after = ByteArray.subByte(this.before, 0, 3);
+ byte[] expected = new byte[] { 15, 28, 4 };
+ assertArrayEquals(expected, after);
+ after = ByteArray.subByte(this.before, 5, 1);
+ expected = new byte[] { 10 };
+ assertArrayEquals(expected, after);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubByte2(){
+ ByteArray.subByte(new byte[0], 2, 2);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubByte3(){
+ ByteArray.subByte(this.before, 2, -1);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubByte4(){
+ ByteArray.subByte(this.before, -1, 2);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubByte5(){
+ ByteArray.subByte(this.before, 9, 2);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubByte6(){
+ ByteArray.subByte(this.before, 2, 19);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubByte7(){
+ ByteArray.subByte(this.before, 2, 7);
+ }
+
+ @Test
+ public void testCutBytes() {
+ byte[] after = ByteArray.cutBytes(this.before, 2);
+ byte[] expected = new byte[] { 4, 6, 9, 10 };
+ assertArrayEquals(expected, after);
+ after = ByteArray.cutBytes(this.before, 6);
+ expected = new byte[] {};
+ assertArrayEquals(expected, after);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCutBytes2(){
+ ByteArray.cutBytes(new byte[0], 5);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCutBytes3(){
+ ByteArray.cutBytes(this.before, 9);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCutBytes4(){
+ ByteArray.cutBytes(this.before, 0);
+ }
+
+ @Test
+ public void testParseBits() {
+ final byte b = (byte) -76; // 1011 0100
+ final boolean[] after = ByteArray.parseBits(b);
+ assertTrue(after[0]);
+ assertFalse(after[1]);
+ assertTrue(after[2]);
+ assertTrue(after[3]);
+ assertFalse(after[4]);
+ assertTrue(after[5]);
+ assertFalse(after[6]);
+ assertFalse(after[7]);
+ }
+
+ private final byte[] inBytes = { (byte) 0x03, (byte) 0xFF, (byte) 0x01, (byte) 0x80 };
+ BitSet inBitSet = new BitSet();
+
+ @Before
+ public void generateBitSet() {
+ // 0x03
+ this.inBitSet.set(6, 8);
+
+ // 0xFF
+ this.inBitSet.set(8, 16);
+
+ // 0x01
+ this.inBitSet.set(23);
+
+ // 0x80
+ this.inBitSet.set(24);
+ }
+
+ @Test
+ public void testBytesToBitSetFunction() {
+ final BitSet iputBitSet = ByteArray.bytesToBitSet(this.inBytes);
+
+ assertEquals(this.inBitSet, iputBitSet);
+ }
+
+ @Test
+ public void testBitSetToBytesFunction() {
+ byte[] resultBytes = ByteArray.bitSetToBytes(this.inBitSet, this.inBytes.length);
+ assertArrayEquals(this.inBytes, resultBytes);
+
+ resultBytes = ByteArray.bitSetToBytes(this.inBitSet, this.inBytes.length - 1);
+ assertArrayEquals(Arrays.copyOf(this.inBytes, this.inBytes.length - 1), resultBytes);
+
+ resultBytes = ByteArray.bitSetToBytes(this.inBitSet, this.inBytes.length + 1);
+ assertArrayEquals(Arrays.copyOf(this.inBytes, this.inBytes.length + 1), resultBytes);
+ }
+
+ @Test
+ public void testFileToBytes() throws IOException {
+ final String FILE_TO_TEST = "src/test/resources/PCEStatefulCapabilityTlv1.bin";
+
+ final File fileToCompareWith = new File(FILE_TO_TEST);
+ final InputStream bytesIStream = new FileInputStream(fileToCompareWith);
+
+ try {
+ final byte[] actualBytes = ByteArray.fileToBytes(FILE_TO_TEST);
+
+ if (fileToCompareWith.length() > Integer.MAX_VALUE) {
+ throw new IOException("Too large file to load in byte array.");
+ }
+
+ final byte[] expectedBytes = new byte[(int) fileToCompareWith.length()];
+
+ int offset = 0;
+ int numRead = 0;
+ while (offset < expectedBytes.length && (numRead = bytesIStream.read(expectedBytes, offset, actualBytes.length - offset)) >= 0) {
+ offset += numRead;
+ }
+
+ assertArrayEquals(expectedBytes, actualBytes);
+ } finally {
+ bytesIStream.close();
+ }
+ }
+
+ @Test
+ public void testIntToBytes() {
+ assertEquals(Integer.MAX_VALUE, ByteArray.bytesToInt(ByteArray.intToBytes(Integer.MAX_VALUE)));
+ assertEquals(Integer.MIN_VALUE, ByteArray.bytesToInt(ByteArray.intToBytes(Integer.MIN_VALUE)));
+ assertEquals(5, ByteArray.bytesToInt(ByteArray.intToBytes(5)));
+ }
+
+ @Test
+ public void testLongToBytes_bytesToLong() {
+ assertEquals(Long.MAX_VALUE, ByteArray.bytesToLong(ByteArray.longToBytes(Long.MAX_VALUE)));
+ assertEquals(Long.MIN_VALUE, ByteArray.bytesToLong(ByteArray.longToBytes(Long.MIN_VALUE)));
+ assertEquals(5, ByteArray.bytesToLong(ByteArray.longToBytes(5)));
+ }
+
+ /**
+ * if less than 4 bytes are converted, zero bytes should be appendet at the
+ * buffer's start
+ */
+ @Test
+ public void testBytesToLong_prependingZeros() {
+ assertEquals(1, ByteArray.bytesToLong(new byte[] { 0, 0, 1 }));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBytesToInt(){
+ final byte[] b = new byte[Integer.SIZE + 1];
+ ByteArray.bytesToInt(b);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBytesToShort2(){
+ final byte[] b = new byte[Short.SIZE + 1];
+ ByteArray.bytesToInt(b);
+ }
+
+ @Test
+ public void testBytes(){
+ assertTrue(ByteArray.bytesToInt(new byte[]{ 0, 0, 0, 15}) == 15);
+ assertEquals(Float.valueOf((float) 1.4E-45), Float.valueOf(ByteArray.bytesToFloat(new byte[]{ 0, 0, 0, 1})));
+ assertEquals(Long.valueOf(16613001005322L), Long.valueOf(ByteArray.bytesToLong(this.before)));
+ assertEquals(Short.valueOf((short) 1), Short.valueOf(ByteArray.bytesToShort(new byte[]{0, 1})));
+ }
+
+
+ @Test
+ public void testCopyBitRange() {
+ assertEquals((byte) 10, ByteArray.copyBitsRange((byte) 0x28, 2, 4));
+ assertEquals((byte) 3, ByteArray.copyBitsRange((byte) 0xFF, 2, 2));
+ assertEquals((byte) 7, ByteArray.copyBitsRange((byte) 0xFF, 5, 3));
+ assertEquals((byte) 15, ByteArray.copyBitsRange((byte) 0xFF, 0, 4));
+ assertEquals((byte) 31, ByteArray.copyBitsRange((byte) 0xF9, 0, 5));
+ assertEquals((byte) 0xA2, ByteArray.copyBitsRange((byte) 0xA2, 0, 8));
+ assertEquals((byte) 1, ByteArray.copyBitsRange((byte) 0xFF, 5, 1));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCopyBitsRange2(){
+ ByteArray.copyBitsRange((byte) 0x28, -1, 4);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCopyBitsRange3(){
+ ByteArray.copyBitsRange((byte) 0x28, 1, 187);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCopyBitsRange4(){
+ ByteArray.copyBitsRange((byte) 0x28, 1, 40);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCopyBitsRange5(){
+ ByteArray.copyBitsRange((byte) 0x28, 28, 2);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCopyBitsRange6(){
+ ByteArray.copyBitsRange((byte) 0x28, 2, -2);
+ }
+
+ @Test
+ public void testCopyWhole() {
+ final byte[] expecteds = { (byte) 0x04, (byte) 0x02, (byte) 0xD4, (byte) 0xf5, (byte) 0x32 };
+
+ final byte[] actuals = new byte[5];
+ actuals[0] = (byte) 0x04;
+ actuals[1] = (byte) 0x02;
+ actuals[2] = (byte) 0xD4;
+
+ final byte[] src = { (byte) 0xf5, (byte) 0x32 };
+
+ ByteArray.copyWhole(src, actuals, 3);
+
+ assertArrayEquals(expecteds, actuals);
+ }
+
+ @Test(expected = ArrayIndexOutOfBoundsException.class)
+ public void testCopyWhole2(){
+ ByteArray.copyWhole(new byte[0], new byte[1], 2);
+ }
+
+ @Test
+ public void testBytesToShort() {
+ final byte[] bytes1 = { (byte) 0x00, (byte) 0x01 };
+ final short expectedShort1 = 1;
+ assertEquals(expectedShort1, ByteArray.bytesToShort(bytes1));
+
+ final byte[] bytes2 = { (byte) 0xFF, (byte) 0xFF };
+ final short expectedShort2 = (short) 0xFFFF;
+ assertEquals(expectedShort2, ByteArray.bytesToShort(bytes2));
+
+ final byte[] bytes3 = { (byte) 0x25, (byte) 0x34 };
+ final short expectedShort3 = (short) 0x2534;
+ assertEquals(expectedShort3, ByteArray.bytesToShort(bytes3));
+ }
+
+ @Test
+ public void testShortToBytes() {
+ final byte[] expectedBytes1 = { (byte) 0x00, (byte) 0x01 };
+ assertArrayEquals(expectedBytes1, ByteArray.shortToBytes((short) 1));
+
+ final byte[] expectedBytes2 = { (byte) 0xFF, (byte) 0xFF };
+ assertArrayEquals(expectedBytes2, ByteArray.shortToBytes((short) 0xFFFF));
+
+ final byte[] expectedBytes3 = { (byte) 0x25, (byte) 0x34 };
+ assertArrayEquals(expectedBytes3, ByteArray.shortToBytes((short) 0x2534));
+ }
+
+ @Test
+ public void testFloatToBytes() {
+ final byte[] expectedBytes1 = { (byte) 0x35, (byte) 0x86, (byte) 0x37, (byte) 0xbd };
+ assertArrayEquals(expectedBytes1, ByteArray.floatToBytes((float) 0.000001));
+
+ final byte[] expectedBytes2 = { (byte) 0xEF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ assertArrayEquals(expectedBytes2, ByteArray.floatToBytes((float) -158456315583795709447797473280.0));
+
+ final byte[] expectedBytes3 = { (byte) 0x49, (byte) 0xbf, (byte) 0x1c, (byte) 0x92 };
+ assertArrayEquals(expectedBytes3, ByteArray.floatToBytes((float) 1565586.253637));
+ }
+
+ @Test
+ public void testBytesToHexString() {
+ final byte[] b = new byte[] { 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, };
+ final String expected = "01 16 01 16 01 16 01 16 01 16 01 16 01 16 01 16\n01 16 ";
+ assertEquals(expected, ByteArray.bytesToHexString(b));
+ }
+
+ @Test
+ public void testBytesToHRString() {
+ byte[] b;
+
+ // test valid US-ASCII string
+ b = new byte[] { (byte) 79, (byte) 102, (byte) 45, (byte) 57, (byte) 107, (byte) 45, (byte) 48, (byte) 50 };
+ final String expected = "Of-9k-02";
+ assertEquals(expected, ByteArray.bytesToHRString(b));
+
+ // test Utf-8 restricted bytes
+ b = new byte[] { (byte) 246, (byte) 248, (byte) 254 };
+ assertEquals(Arrays.toString(b), ByteArray.bytesToHRString(b));
+
+ // test unexpected continuation bytes
+ b = new byte[] { (byte) 128, (byte) 113, (byte) 98 };
+ assertEquals(Arrays.toString(b), ByteArray.bytesToHRString(b));
+ }
+
+ @Test
+ public void testFindByteSequence() {
+ final byte[] bytes = new byte[] { (byte)36, (byte)41, (byte)55, (byte)101, (byte)38 };
+ final byte[] sequence1 = new byte[] { (byte)36, (byte)41 };
+
+ assertEquals(0, ByteArray.findByteSequence(bytes, sequence1));
+
+ final byte[] sequence2 = new byte[] { (byte)55, (byte)38 };
+
+ assertEquals(-1, ByteArray.findByteSequence(bytes, sequence2));
+
+ final byte[] sequence3 = new byte[] { (byte)101, (byte)38 };
+
+ assertEquals(3, ByteArray.findByteSequence(bytes, sequence3));
+
+ try {
+ ByteArray.findByteSequence(bytes, new byte[] { (byte)36, (byte)41, (byte)55, (byte)101, (byte)38, (byte)66 });
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Sequence to be found is longer than the given byte array.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testMaskBytes() {
+ final byte[] bytes = new byte[] {(byte)0xAC, (byte)0xA8, (byte)0x1F, (byte)0x08 };
+ try {
+ ByteArray.maskBytes(bytes, 48);
+ } catch (final IllegalArgumentException e) {
+ assertEquals("Attempted to apply invalid mask (too long)", e.getMessage());
+ }
+
+ assertArrayEquals(bytes, ByteArray.maskBytes(bytes, 32));
+
+ assertArrayEquals(new byte[] { (byte)0xAC, (byte)0x80, 0, 0}, ByteArray.maskBytes(bytes, 10));
+ }
+
+}