import com.google.common.collect.Lists;
import com.google.common.net.HostAndPort;
import com.google.common.net.InetAddresses;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timer;
import io.netty.util.concurrent.GlobalEventExecutor;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import org.opendaylight.protocol.pcep.ietf.stateful07.StatefulActivator;
import org.opendaylight.protocol.pcep.impl.DefaultPCEPSessionNegotiatorFactory;
import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccTunnelManager;
import org.opendaylight.protocol.pcep.spi.PCEPExtensionProviderContext;
import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
import org.opendaylight.tcpmd5.api.KeyMapping;
short dt = DEFAULT_DEAD_TIMER;
String password = null;
int reconnectTime = -1;
+ int redelegationTimeout = 0;
+ int stateTimeout = -1;
+ final Timer timer = new HashedWheelTimer();
getRootLogger(lc).setLevel(ch.qos.logback.classic.Level.INFO);
int argIdx = 0;
password = args[++argIdx];
} else if (args[argIdx].equals("--reconnect")) {
reconnectTime = Integer.valueOf(args[++argIdx]).intValue() * 1000;
+ } else if (args[argIdx].equals("--redelegation-timeout")) {
+ redelegationTimeout = Integer.valueOf(args[++argIdx]);
+ } else if (args[argIdx].equals("--state-timeout")) {
+ stateTimeout = Integer.valueOf(args[++argIdx]);
} else {
LOG.warn("WARNING: Unrecognized argument: {}", args[argIdx]);
}
argIdx++;
}
- createPCCs(lsps, pcError, pccCount, localAddress, remoteAddress, ka, dt, password, reconnectTime);
+ createPCCs(lsps, pcError, pccCount, localAddress, remoteAddress, ka, dt, password, reconnectTime, redelegationTimeout, stateTimeout, timer);
}
public static void createPCCs(final int lspsPerPcc, final boolean pcerr, final int pccCount,
final InetSocketAddress localAddress, final List<InetSocketAddress> remoteAddress, final short keepalive, final short deadtimer,
- final String password, final int reconnectTime) throws InterruptedException, ExecutionException {
+ final String password, final int reconnectTime, final int redelegationTimeout, final int stateTimeout, final Timer timer) throws InterruptedException, ExecutionException {
startActivators();
InetAddress currentAddress = localAddress.getAddress();
final Open openMessage = getOpenMessage(keepalive, deadtimer);
final PCCDispatcher pccDispatcher = new PCCDispatcher(ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance().getMessageHandlerRegistry(),
getSessionNegotiatorFactory(openMessage));
for (int i = 0; i < pccCount; i++) {
- createPCC(lspsPerPcc, pcerr, new InetSocketAddress(currentAddress, localAddress.getPort()),
- remoteAddress, openMessage, pccDispatcher, password, reconnectTime);
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(lspsPerPcc, currentAddress,
+ redelegationTimeout, stateTimeout, timer);
+ createPCC(pcerr, new InetSocketAddress(currentAddress, localAddress.getPort()),
+ remoteAddress, openMessage, pccDispatcher, password, reconnectTime, tunnelManager);
currentAddress = InetAddresses.increment(currentAddress);
}
}
@SuppressWarnings("deprecation")
- private static void createPCC(final int lspsPerPcc, final boolean pcerr, final InetSocketAddress localAddress,
+ private static void createPCC(final boolean pcerr, final InetSocketAddress localAddress,
final List<InetSocketAddress> remoteAddress, final Open openMessage, final PCCDispatcher pccDispatcher,
- final String password, final int reconnectTime) throws InterruptedException, ExecutionException {
+ final String password, final int reconnectTime, final PccTunnelManager tunnelManager) throws InterruptedException, ExecutionException {
final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> snf = getSessionNegotiatorFactory(openMessage);
+
for (final InetSocketAddress pceAddress : remoteAddress) {
- pccDispatcher.createClient(localAddress, pceAddress, reconnectTime == -1 ? getNeverReconnectStrategyFactory() : getTimedReconnectStrategyFactory(reconnectTime), new SessionListenerFactory<PCEPSessionListener>() {
- @Override
- public PCEPSessionListener getSessionListener() {
- return new SimpleSessionListener(lspsPerPcc, pcerr, localAddress.getAddress());
- }
- }, snf, getKeyMapping(pceAddress.getAddress(), password));
+ pccDispatcher.createClient(localAddress, pceAddress, reconnectTime == -1 ? getNeverReconnectStrategyFactory() : getTimedReconnectStrategyFactory(reconnectTime),
+ new SessionListenerFactory<PCEPSessionListener>() {
+ @Override
+ public PCEPSessionListener getSessionListener() {
+ return new PccSessionListener(remoteAddress.indexOf(pceAddress), tunnelManager, pcerr);
+ }
+ } ,snf, getKeyMapping(pceAddress.getAddress(), password));
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.symbolic.path.name.tlv.SymbolicPathNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcerrBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObjectBuilder;
return rptBuilder.build();
}
- public static Lsp createLsp(final long plspId, final boolean sync, final Optional<Tlvs> tlvs) {
+ public static Lsp createLsp(final long plspId, final boolean sync, final Optional<Tlvs> tlvs, final boolean isDelegatedLsp, final boolean remove) {
final LspBuilder lspBuilder = new LspBuilder();
lspBuilder.setAdministrative(true);
- lspBuilder.setDelegate(true);
+ lspBuilder.setDelegate(isDelegatedLsp);
lspBuilder.setIgnore(false);
lspBuilder.setOperational(OperationalStatus.Up);
lspBuilder.setPlspId(new PlspId(plspId));
lspBuilder.setProcessingRule(false);
- lspBuilder.setRemove(false);
+ lspBuilder.setRemove(remove);
lspBuilder.setSync(sync);
lspBuilder.setTlvs(tlvs.orNull());
return lspBuilder.build();
}
+ public static Lsp createLsp(final long plspId, final boolean sync, final Optional<Tlvs> tlvs, final boolean isDelegatedLspe) {
+ return createLsp(plspId, sync, tlvs, isDelegatedLspe, false);
+ }
+
public static Path createPath(final List<Subobject> subobjects) {
final PathBuilder pathBuilder = new PathBuilder();
pathBuilder.setEro(new EroBuilder().setSubobject(subobjects).build());
}
public static Path updToRptPath(
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.Path path) {
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.Path path) {
final PathBuilder pathBuilder = new PathBuilder();
- pathBuilder.fieldsFrom(path);
+ if (path != null) {
+ pathBuilder.fieldsFrom(path);
+ }
return pathBuilder.build();
}
public static Path reqToRptPath(final Requests request) {
final PathBuilder pathBuilder = new PathBuilder();
- pathBuilder.fieldsFrom(request);
+ if (request != null) {
+ pathBuilder.fieldsFrom(request);
+ }
return pathBuilder.build();
}
new Ipv4ExtendedTunnelId(extendedTunnelAddress))
.build()).build()).setTunnelId(new TunnelId((int) lspId)).build());
if (symbolicPathName) {
- final byte[] pathName;
if (symbolicName.isPresent()) {
- pathName = symbolicName.get();
+ tlvs.setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(
+ new SymbolicPathName(symbolicName.get())).build());
} else {
- pathName = ("pcc_" + tunnelSender + "_tunnel_" + lspId).getBytes(Charsets.UTF_8);
+ tlvs.setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(
+ new SymbolicPathName(getDefaultPathName(tunnelSender, lspId))).build());
}
- tlvs.setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(
- new SymbolicPathName(pathName)).build());
}
return tlvs.build();
}
- public static Message createErrorMsg(final PCEPErrors e, final long srpId) {
+ public static Pcerr createErrorMsg(final PCEPErrors e, final long srpId) {
final PcerrMessageBuilder msgBuilder = new PcerrMessageBuilder();
return new PcerrBuilder().setPcerrMessage(
msgBuilder
.build()).build())).build()).build();
}
+ public static byte[] getDefaultPathName(final String address, final long lspId) {
+ return ("pcc_" + address + "_tunnel_" + lspId).getBytes(Charsets.UTF_8);
+ }
+
}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock;
+
+import java.util.Random;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPTerminationReason;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccTunnelManager;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Pcinitiate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PccSessionListener implements PCEPSessionListener, PccSession {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PccSessionListener.class);
+
+ private final boolean errorMode;
+ private final PccTunnelManager tunnelManager;
+ private final int sessionId;
+ private PCEPSession session;
+
+ public PccSessionListener(final int sessionId, final PccTunnelManager tunnelManager, final boolean errorMode) {
+ this.errorMode = errorMode;
+ this.tunnelManager = tunnelManager;
+ this.sessionId = sessionId;
+ }
+
+ @Override
+ public void onMessage(final PCEPSession session, final Message message) {
+ LOG.trace("Received message: {}", message);
+ if (this.errorMode) {
+ //random error message
+ session.sendMessage(createErrorMessage(message));
+ return;
+ }
+ if (message instanceof Pcupd) {
+ final Updates update = ((Pcupd) message).getPcupdMessage().getUpdates().get(0);
+ if (update.getLsp().isDelegate() != null && update.getLsp().isDelegate()) {
+ //regular LSP update
+ this.tunnelManager.reportToAll(update, this);
+ } else {
+ //returning LSP delegation
+ this.tunnelManager.returnDelegation(update, this);
+ }
+ } else if (message instanceof Pcinitiate) {
+ final Requests request = ((Pcinitiate) message).getPcinitiateMessage().getRequests().get(0);
+ if (request.getSrp().getAugmentation(Srp1.class) != null && request.getSrp().getAugmentation(Srp1.class).isRemove()) {
+ //remove LSP
+ this.tunnelManager.removeTunnel(request, this);
+ } else if (request.getLsp().isDelegate() != null && request.getLsp().isDelegate() && request.getEndpointsObj() == null) {
+ //take LSP delegation
+ this.tunnelManager.takeDelegation(request, this);
+ } else {
+ //create LSP
+ this.tunnelManager.addTunnel(request, this);
+ }
+ }
+ }
+
+ @Override
+ public void onSessionUp(final PCEPSession session) {
+ LOG.debug("Session up.");
+ this.session = session;
+ this.tunnelManager.onSessionUp(this);
+ }
+
+ @Override
+ public void onSessionDown(final PCEPSession session, final Exception e) {
+ LOG.info("Session down with cause : {} or exception: {}", e.getCause(), e, e);
+ this.tunnelManager.onSessionDown(this);
+ session.close();
+ }
+
+ @Override
+ public void onSessionTerminated(final PCEPSession session, final PCEPTerminationReason cause) {
+ LOG.info("Session terminated. Cause : {}", cause.toString());
+ }
+
+ @Override
+ public void sendReport(final Pcrpt reportMessage) {
+ this.session.sendMessage(reportMessage);
+ }
+
+ @Override
+ public void sendError(final Pcerr errorMessage) {
+ this.session.sendMessage(errorMessage);
+ }
+
+ @Override
+ public int getId() {
+ return this.sessionId;
+ }
+
+ private final Random rnd = new Random();
+
+ private PCEPErrors getRandomError() {
+ return PCEPErrors.values()[this.rnd.nextInt(PCEPErrors.values().length)];
+ }
+
+ private Pcerr createErrorMessage(final Message message) {
+ final Srp srp;
+ if (message instanceof Pcupd) {
+ srp = ((Pcupd) message).getPcupdMessage().getUpdates().get(0).getSrp();
+ } else {
+ srp = ((Pcinitiate) message).getPcinitiateMessage().getRequests().get(0).getSrp();
+ }
+ return MsgBuilderUtil.createErrorMsg(getRandomError(), srp.getOperationId().getValue());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock;
+
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLsp;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLspTlvs;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPath;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPcRtpMessage;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createSrp;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.reqToRptPath;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.updToRptPath;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.net.InetAddresses;
+import io.netty.util.Timeout;
+import io.netty.util.Timer;
+import io.netty.util.TimerTask;
+import java.net.InetAddress;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccTunnelManager;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.OperationalStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.Lsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.reports.Path;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.reports.PathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
+
+public class PccTunnelManagerImpl implements PccTunnelManager {
+
+ private static final Subobject DEFAULT_ENDPOINT_HOP = getDefaultEROEndpointHop();
+ private static final String ENDPOINT_ADDRESS = "1.1.1.1";
+ private static final String ENDPOINT_PREFIX = ENDPOINT_ADDRESS + "/32";
+ private static final Optional<Srp> NO_SRP = Optional.<Srp> absent();
+ private static final int PCC_DELEGATION = -1;
+
+ @GuardedBy("this")
+ private final Map<Integer, PccSession> sessions = new HashMap<>();
+
+ @GuardedBy("this")
+ private final Map<PlspId, Tunnel> tunnels = new HashMap<>();
+
+ private final AtomicLong plspIDsCounter;
+ private final String address;
+ private final Timer timer;
+ private final int redelegationTimeout;
+ private final int stateTimeout;
+
+ public PccTunnelManagerImpl(final int lspsCount, final InetAddress address, final int redelegationTimeout,
+ final int stateTimeout, final Timer timer) {
+ Preconditions.checkArgument(lspsCount >= 0);
+ Preconditions.checkNotNull(address);
+ this.redelegationTimeout = redelegationTimeout;
+ this.stateTimeout = stateTimeout;
+ this.plspIDsCounter = new AtomicLong(lspsCount);
+ this.address = InetAddresses.toAddrString(Preconditions.checkNotNull(address));
+ this.timer = Preconditions.checkNotNull(timer);
+ for (int i = 1; i <= lspsCount; i++) {
+ final Tunnel tunnel = new Tunnel(MsgBuilderUtil.getDefaultPathName(this.address, i), PCC_DELEGATION, LspType.PCC_LSP,
+ createPath(Lists.newArrayList(DEFAULT_ENDPOINT_HOP)));
+ tunnels.put(new PlspId((long) i), tunnel);
+ }
+ }
+
+ @Override
+ public void reportToAll(final Updates update, final PccSession session) {
+ final PlspId plspId = update.getLsp().getPlspId();
+ final Tunnel tunnel = tunnels.get(plspId);
+ final long srpId = update.getSrp().getOperationId().getValue();
+ if (tunnel != null) {
+ if (hasDelegation(tunnel, session)) {
+ final Srp srp = createSrp(update.getSrp().getOperationId().getValue());
+ final Path path = updToRptPath(update.getPath());
+ final List<Subobject> subobjects = update.getPath().getEro().getSubobject();
+ final Lsp lsp = update.getLsp();
+ sendToAll(tunnel, plspId, subobjects, srp, path, lsp);
+ //update tunnel state
+ tunnel.setLspState(path);
+ } else {
+ session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
+ }
+ } else {
+ session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
+ }
+ }
+
+ @Override
+ public void returnDelegation(final Updates update, final PccSession session) {
+ final PlspId plspId = update.getLsp().getPlspId();
+ final Tunnel tunnel = tunnels.get(plspId);
+ final long srpId = update.getSrp().getOperationId().getValue();
+ if (tunnel != null) {
+ //check if session really has a delegation
+ if (hasDelegation(tunnel, session)) {
+ //send report D=0
+ final Tlvs tlvs = createLspTlvs(plspId.getValue(), true,
+ getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), this.address), this.address,
+ this.address, Optional.of(tunnel.getPathName()));
+ session.sendReport(createPcRtpMessage(
+ new LspBuilder(update.getLsp()).setSync(true).setOperational(OperationalStatus.Up).setDelegate(false).setTlvs(tlvs).build(),
+ Optional.of(createSrp(srpId)), tunnel.getLspState()));
+ //start state timer
+ startStateTimeout(tunnel, plspId);
+ //if PCC's LSP, start re-delegation timer
+ if (tunnel.getType() == LspType.PCC_LSP) {
+ startRedelegationTimer(tunnel, plspId, session);
+ } else {
+ //if PCE-initiated LSP, revoke delegation instantly
+ setDelegation(plspId, null);
+ }
+ } else {
+ session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
+ }
+ } else {
+ session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
+ }
+ }
+
+ @Override
+ public synchronized void onSessionUp(final PccSession session) {
+ //first session - delegate all PCC's LSPs
+ //only when reporting at startup
+ if (! sessions.containsKey(session.getId()) && session.getId() == 0) {
+ for (final PlspId plspId : tunnels.keySet()) {
+ setDelegation(plspId, session);
+ }
+ }
+ sessions.put(session.getId(), session);
+ if (!tunnels.isEmpty()) {
+ //report all known LSPs
+ for (final Entry<PlspId, Tunnel> entry : tunnels.entrySet()) {
+ final Tunnel tunnel = entry.getValue();
+ final boolean delegation = hasDelegation(tunnel, session);
+ if (delegation) {
+ tunnel.cancelTimeouts();
+ }
+ final long plspId = entry.getKey().getValue();
+ final Tlvs tlvs = MsgBuilderUtil.createLspTlvs(plspId, true,
+ getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), PccTunnelManagerImpl.this.address), this.address,
+ this.address, Optional.of(tunnel.getPathName()));
+ session.sendReport(createPcRtpMessage(
+ createLsp(plspId, true, Optional.<Tlvs> fromNullable(tlvs), delegation, false), NO_SRP,
+ tunnel.getLspState()));
+ }
+ //end-of-sync marker
+ session.sendReport(createPcRtpMessage(createLsp(0, false, Optional.<Tlvs> absent(), true, false), NO_SRP,
+ createPath(Collections.<Subobject> emptyList())));
+ }
+ }
+
+ @Override
+ public void takeDelegation(final Requests request, final PccSession session) {
+ final PlspId plspId = request.getLsp().getPlspId();
+ final Tunnel tunnel = tunnels.get(plspId);
+ final long srpId = request.getSrp().getOperationId().getValue();
+ if (tunnel != null) {
+ //check if tunnel has no delegation
+ if (tunnel.type == LspType.PCE_LSP && (tunnel.getDelegationHolder() == -1 || tunnel.getDelegationHolder() == session.getId())) {
+ //set delegation
+ tunnel.cancelTimeouts();
+ setDelegation(plspId, session);
+ //send report
+ final Tlvs tlvs = createLspTlvs(plspId.getValue(), true,
+ getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), this.address), this.address,
+ this.address, Optional.of(tunnel.getPathName()));
+ session.sendReport(createPcRtpMessage(
+ new LspBuilder(request.getLsp()).setSync(true).setOperational(OperationalStatus.Up).setDelegate(true).setTlvs(tlvs).build(),
+ Optional.of(createSrp(srpId)), tunnel.getLspState()));
+ } else {
+ session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.LSP_NOT_PCE_INITIATED, srpId));
+ }
+ } else {
+ session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
+ }
+ }
+
+ @Override
+ public synchronized void onSessionDown(final PccSession session) {
+ for (final Entry<PlspId, Tunnel> entry : tunnels.entrySet()) {
+ final Tunnel tunnel = entry.getValue();
+ final PlspId plspId = entry.getKey();
+ //deal with delegations
+ if (hasDelegation(tunnel, session)) {
+ startStateTimeout(tunnel, entry.getKey());
+ startRedelegationTimer(tunnel, plspId, session);
+ }
+ }
+ }
+
+ @Override
+ public void addTunnel(final Requests request, final PccSession session) {
+ final PlspId plspId = new PlspId(this.plspIDsCounter.incrementAndGet());
+ final Tunnel tunnel = new Tunnel(request.getLsp().getTlvs().getSymbolicPathName().getPathName().getValue(),
+ session.getId(), LspType.PCE_LSP, reqToRptPath(request));
+ sendToAll(tunnel, plspId, request.getEro().getSubobject(), createSrp(request.getSrp().getOperationId().getValue()),
+ tunnel.getLspState(), new LspBuilder(request.getLsp()).addAugmentation(Lsp1.class, new Lsp1Builder().setCreate(true).build()).build());
+ tunnels.put(plspId, tunnel);
+ }
+
+ @Override
+ public void removeTunnel(final Requests request, final PccSession session) {
+ final PlspId plspId = request.getLsp().getPlspId();
+ final Tunnel tunnel = tunnels.get(plspId);
+ final long srpId = request.getSrp().getOperationId().getValue();
+ if (tunnel != null) {
+ if (tunnel.getType() == LspType.PCE_LSP) {
+ if (hasDelegation(tunnel, session)) {
+ tunnels.remove(plspId);
+ sendToAll(tunnel, plspId, tunnel.getLspState().getEro().getSubobject(),
+ new SrpBuilder(request.getSrp()).addAugmentation(Srp1.class, new Srp1Builder().setRemove(true).build()).build(),
+ reqToRptPath(request), request.getLsp());
+ } else {
+ session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
+ }
+ } else {
+ session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.LSP_NOT_PCE_INITIATED, srpId));
+ }
+ } else {
+ session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
+ }
+ }
+
+ private void sendToAll(final Tunnel tunnel, final PlspId plspId, final List<Subobject> subobjects, final Srp srp, final Path path, final Lsp lsp) {
+ for (final PccSession session : sessions.values()) {
+ final boolean isDelegated = hasDelegation(tunnel, session);
+ final Tlvs tlvs = createLspTlvs(plspId.getValue(), true,
+ getDestinationAddress(subobjects, this.address), this.address,
+ this.address, Optional.of(tunnel.getPathName()));
+ final Pcrpt pcRpt = createPcRtpMessage(
+ new LspBuilder(lsp).setPlspId(plspId).setOperational(OperationalStatus.Up).setDelegate(isDelegated).setTlvs(tlvs).build(),
+ Optional.fromNullable(srp), path);
+ session.sendReport(pcRpt);
+ }
+ }
+
+ private void startStateTimeout(final Tunnel tunnel, final PlspId plspId) {
+ if (this.stateTimeout > -1) {
+ final Timeout stateTimeout = this.timer.newTimeout(new TimerTask() {
+ @Override
+ public void run(final Timeout timeout) throws Exception {
+ if (tunnel.getType() == LspType.PCE_LSP) {
+ PccTunnelManagerImpl.this.tunnels.remove(plspId);
+ //report tunnel removal to all
+ sendToAll(tunnel, plspId, Collections.<Subobject>emptyList(), createSrp(0), new PathBuilder().build(),
+ createLsp(plspId.getValue(), false, Optional.<Tlvs>absent(), false, true));
+ }
+ }
+ }, this.stateTimeout, TimeUnit.SECONDS);
+ tunnel.setStateTimeout(stateTimeout);
+ }
+ }
+
+ private void startRedelegationTimer(final Tunnel tunnel, final PlspId plspId, final PccSession session) {
+ final Timeout redelegationTimeout = this.timer.newTimeout(new TimerTask() {
+ @Override
+ public void run(final Timeout timeout) throws Exception {
+ //remove delegation
+ PccTunnelManagerImpl.this.setDelegation(plspId, null);
+ //delegate to another PCE
+ int index = session.getId();
+ for (int i = 1; i < sessions.size(); i++) {
+ index++;
+ if (index == sessions.size()) {
+ index = 0;
+ }
+ final PccSession nextSession = sessions.get(index);
+ if (nextSession != null) {
+ tunnel.cancelTimeouts();
+ final Tlvs tlvs = createLspTlvs(plspId.getValue(), true,
+ getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), PccTunnelManagerImpl.this.address),
+ PccTunnelManagerImpl.this.address, PccTunnelManagerImpl.this.address, Optional.of(tunnel.getPathName()));
+ nextSession.sendReport(createPcRtpMessage(
+ createLsp(plspId.getValue(), true, Optional.<Tlvs> fromNullable(tlvs), true, false), NO_SRP,
+ tunnel.getLspState()));
+ tunnel.setDelegationHolder(nextSession.getId());
+ break;
+ }
+ }
+ }
+ }, this.redelegationTimeout, TimeUnit.SECONDS);
+ tunnel.setRedelegationTimeout(redelegationTimeout);
+ }
+
+ private void setDelegation(final PlspId plspId, final PccSession session) {
+ final Tunnel tunnel = tunnels.get(plspId);
+ final int sessionId;
+ if (session != null) {
+ sessionId = session.getId();
+ } else {
+ sessionId = PCC_DELEGATION;
+ }
+ tunnel.setDelegationHolder(sessionId);
+ }
+
+ private static boolean hasDelegation(final Tunnel tunnel, final PccSession session) {
+ return tunnel.getDelegationHolder() == session.getId();
+ }
+
+ private static final class Tunnel {
+ private final byte[] pathName;
+ private int delegationHolder;
+ private final LspType type;
+ private Path lspState;
+ private Timeout redelegationTimeout;
+ private Timeout stateTimeout;
+
+ public Tunnel(final byte[] pathName, final int delegationHolder, final LspType type, final Path lspState) {
+ this.pathName = pathName;
+ this.delegationHolder = delegationHolder;
+ this.type = type;
+ this.lspState = lspState;
+ }
+
+ public byte[] getPathName() {
+ return pathName;
+ }
+
+ public int getDelegationHolder() {
+ return delegationHolder;
+ }
+
+ public LspType getType() {
+ return type;
+ }
+
+ public Path getLspState() {
+ return lspState;
+ }
+
+ public void setRedelegationTimeout(final Timeout redelegationTimeout) {
+ this.redelegationTimeout = redelegationTimeout;
+ }
+
+ public void setStateTimeout(final Timeout stateTimeout) {
+ this.stateTimeout = stateTimeout;
+ }
+
+ public void cancelTimeouts() {
+ if (this.redelegationTimeout != null) {
+ this.redelegationTimeout.cancel();
+ }
+ if (this.stateTimeout != null) {
+ this.stateTimeout.cancel();
+ }
+ }
+
+ public void setDelegationHolder(final int delegationHolder) {
+ this.delegationHolder = delegationHolder;
+ }
+
+ public void setLspState(final Path lspState) {
+ this.lspState = lspState;
+ }
+
+ }
+
+ enum LspType {
+ PCE_LSP, PCC_LSP
+ }
+
+ private static String getDestinationAddress(final List<Subobject> subobjects, final String defaultAddress) {
+ if (subobjects != null && !subobjects.isEmpty()) {
+ final String prefix = ((IpPrefixCase) subobjects.get(subobjects.size() - 1).getSubobjectType())
+ .getIpPrefix().getIpPrefix().getIpv4Prefix().getValue();
+ return prefix.substring(0, prefix.indexOf('/'));
+ }
+ return defaultAddress;
+ }
+
+ private static Subobject getDefaultEROEndpointHop() {
+ final SubobjectBuilder builder = new SubobjectBuilder();
+ builder.setLoose(false);
+ builder.setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(new IpPrefixBuilder().setIpPrefix(
+ new IpPrefix(new Ipv4Prefix(ENDPOINT_PREFIX))).build()).build());
+ return builder.build();
+ }
+
+}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.protocol.pcep.pcc.mock;
-
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLsp;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLspTlvs;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPath;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPcRtpMessage;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createSrp;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.reqToRptPath;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.updToRptPath;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import java.net.InetAddress;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicLong;
-import javax.annotation.concurrent.GuardedBy;
-import org.opendaylight.protocol.pcep.PCEPSession;
-import org.opendaylight.protocol.pcep.PCEPSessionListener;
-import org.opendaylight.protocol.pcep.PCEPTerminationReason;
-import org.opendaylight.protocol.pcep.spi.PCEPErrors;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Pcinitiate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv4Case;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SimpleSessionListener implements PCEPSessionListener {
-
- private static final Logger LOG = LoggerFactory.getLogger(SimpleSessionListener.class);
-
- private static final String ENDPOINT_ADDRESS = "1.1.1.1";
- private static final String ENDPOINT_PREFIX = ENDPOINT_ADDRESS + "/32";
-
- private static final Subobject DEFAULT_ENDPOINT_HOP = getDefaultEROEndpointHop();
-
- private final int lspsCount;
- private final boolean pcError;
- private final String address;
- private final AtomicLong plspIDs;
- @GuardedBy("this")
- private final Map<Long, byte[]> pathNames = new HashMap<>();
-
- public SimpleSessionListener(final int lspsCount, final boolean pcError, final InetAddress address) {
- Preconditions.checkArgument(lspsCount >= 0);
- this.lspsCount = lspsCount;
- this.pcError = pcError;
- this.address = address.getHostAddress();
- this.plspIDs = new AtomicLong(lspsCount);
- }
-
- @Override
- public void onMessage(final PCEPSession session, final Message message) {
- LOG.trace("Received message: {}", message);
- if (message instanceof Pcupd) {
- final Pcupd updMsg = (Pcupd) message;
- final Updates updates = updMsg.getPcupdMessage().getUpdates().get(0);
- final long srpId = updates.getSrp().getOperationId().getValue();
- if (this.pcError) {
- session.sendMessage(MsgBuilderUtil.createErrorMsg(getRandomError(), srpId));
- } else {
- final Tlvs tlvs = createLspTlvs(updates.getLsp().getPlspId().getValue(), true,
- getDestinationAddress(updates.getPath().getEro().getSubobject()), this.address, this.address,
- Optional.fromNullable(pathNames.get(updates.getLsp().getPlspId().getValue())));
- final Pcrpt pcRpt = createPcRtpMessage(new LspBuilder(updates.getLsp()).setTlvs(tlvs).build(),
- Optional.fromNullable(createSrp(srpId)), updToRptPath(updates.getPath()));
- session.sendMessage(pcRpt);
- }
- } else if (message instanceof Pcinitiate) {
- final Pcinitiate initMsg = (Pcinitiate) message;
- final Requests request = initMsg.getPcinitiateMessage().getRequests().get(0);
- if (this.pcError) {
- session.sendMessage(MsgBuilderUtil.createErrorMsg(getRandomError(), request.getSrp().getOperationId().getValue()));
- } else {
- final Pcrpt pcRpt;
- if (request.getSrp().getAugmentation(Srp1.class) != null && request.getSrp().getAugmentation(Srp1.class).isRemove()) {
- pcRpt = createPcRtpMessage(request.getLsp(), Optional.fromNullable(request.getSrp()), reqToRptPath(request));
- this.pathNames.remove(request.getLsp().getPlspId().getValue());
- } else {
- final LspBuilder lspBuilder = new LspBuilder(request.getLsp());
- lspBuilder.setPlspId(new PlspId(this.plspIDs.incrementAndGet()));
- lspBuilder.addAugmentation(Lsp1.class, new Lsp1Builder().setCreate(true).build());
- final Tlvs tlvs = createLspTlvs(lspBuilder.getPlspId().getValue(), true,
- ((Ipv4Case) request.getEndpointsObj().getAddressFamily()).getIpv4().getDestinationIpv4Address().getValue(), this.address, this.address,
- Optional.of(request.getLsp().getTlvs().getSymbolicPathName().getPathName().getValue()));
- lspBuilder.setTlvs(tlvs);
- pcRpt = createPcRtpMessage(lspBuilder.build(), Optional.fromNullable(request.getSrp()), reqToRptPath(request));
- this.pathNames.put(lspBuilder.getPlspId().getValue(), tlvs.getSymbolicPathName().getPathName().getValue());
- }
- session.sendMessage(pcRpt);
- }
- }
- }
-
- @Override
- public void onSessionUp(final PCEPSession session) {
- LOG.debug("Session up.");
- for (int i = 1; i <= this.lspsCount; i++) {
- final Tlvs tlvs = MsgBuilderUtil.createLspTlvs(i, true, ENDPOINT_ADDRESS, this.address,
- this.address, Optional.<byte[]>absent());
- session.sendMessage(createPcRtpMessage(
- createLsp(i, true, Optional.<Tlvs> fromNullable(tlvs)), Optional.<Srp> absent(),
- createPath(Lists.newArrayList(DEFAULT_ENDPOINT_HOP))));
- }
- // end-of-sync marker
- session.sendMessage(createPcRtpMessage(createLsp(0, false, Optional.<Tlvs> absent()), Optional.<Srp> absent(),
- createPath(Collections.<Subobject> emptyList())));
- }
-
- @Override
- public void onSessionDown(final PCEPSession session, final Exception e) {
- LOG.info("Session down with cause : {} or exception: {}", e.getCause(), e, e);
- session.close();
- }
-
- @Override
- public void onSessionTerminated(final PCEPSession session, final PCEPTerminationReason cause) {
- LOG.info("Session terminated. Cause : {}", cause.toString());
- }
-
- private String getDestinationAddress(final List<Subobject> subobjects) {
- if (subobjects != null && !subobjects.isEmpty()) {
- final String prefix = ((IpPrefixCase) subobjects.get(subobjects.size() - 1).getSubobjectType())
- .getIpPrefix().getIpPrefix().getIpv4Prefix().getValue();
- return prefix.substring(0, prefix.indexOf('/'));
- }
- return this.address;
- }
-
- private static Subobject getDefaultEROEndpointHop() {
- final SubobjectBuilder builder = new SubobjectBuilder();
- builder.setLoose(false);
- builder.setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(new IpPrefixBuilder().setIpPrefix(
- new IpPrefix(new Ipv4Prefix(ENDPOINT_PREFIX))).build()).build());
- return builder.build();
- }
-
- private Random rnd = new Random();
-
- private PCEPErrors getRandomError() {
- return PCEPErrors.values()[this.rnd.nextInt(PCEPErrors.values().length)];
- }
-
-}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock.api;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
+
+public interface PccSession {
+
+ void sendReport(Pcrpt reportMessage);
+
+ void sendError(Pcerr errorMessage);
+
+ int getId();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock.api;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+
+public interface PccTunnelManager {
+
+ void reportToAll(Updates updates, PccSession session);
+
+ void returnDelegation(Updates updates, PccSession session);
+
+ void takeDelegation(Requests request, PccSession session);
+
+ void onSessionUp(PccSession session);
+
+ void onSessionDown(PccSession session);
+
+ void addTunnel(Requests request, PccSession session);
+
+ void removeTunnel(Requests request, PccSession session);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock;
+
+import com.google.common.collect.Lists;
+import java.util.List;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccTunnelManager;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.PcinitiateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.PcinitiateMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.PcinitiateMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.RequestsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.OperationalStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PcupdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SrpIdNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.PcupdMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.UpdatesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.PathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.EndpointsObjBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
+
+public class PccSessionListenerTest {
+
+ @Mock
+ private PCEPSession mockedSession;
+
+ @Mock
+ private PccTunnelManager tunnelManager;
+
+ private final List<Message> sendMessages = Lists.newArrayList();
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(final InvocationOnMock invocation) throws Throwable {
+ PccSessionListenerTest.this.sendMessages.add((Message) invocation.getArguments()[0]);
+ return null;
+ }
+ }).when(mockedSession).sendMessage(Mockito.any(Message.class));
+ }
+
+ @After
+ public void cleanup() {
+ this.sendMessages.clear();
+ }
+
+ @Test
+ public void testOnMessage() {
+ final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+ listener.onMessage(mockedSession, createUpdMsg(true));
+ Mockito.verify(tunnelManager).reportToAll(Mockito.any(Updates.class), Mockito.any(PccSession.class));
+ listener.onMessage(mockedSession, createUpdMsg(false));
+ Mockito.verify(tunnelManager).returnDelegation(Mockito.any(Updates.class), Mockito.any(PccSession.class));
+ listener.onMessage(mockedSession, createInitMsg(false, true));
+ Mockito.verify(tunnelManager).addTunnel(Mockito.any(Requests.class), Mockito.any(PccSession.class));
+ listener.onMessage(mockedSession, createInitMsg(true, false));
+ Mockito.verify(tunnelManager).removeTunnel(Mockito.any(Requests.class), Mockito.any(PccSession.class));
+ listener.onMessage(mockedSession, createInitMsg(false, false));
+ Mockito.verify(tunnelManager).takeDelegation(Mockito.any(Requests.class), Mockito.any(PccSession.class));
+ }
+
+ @Test
+ public void testOnMessageErrorMode() {
+ final PccSessionListener listener = new PccSessionListener(1, tunnelManager, true);
+ listener.onMessage(mockedSession, createUpdMsg(true));
+ Mockito.verify(mockedSession).sendMessage(Mockito.any(Message.class));
+ }
+
+ @Test
+ public void testOnSessionUp() {
+ final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+ listener.onSessionUp(mockedSession);
+ Mockito.verify(tunnelManager).onSessionUp(Mockito.any(PccSession.class));
+ }
+
+ @Test
+ public void testOnSessionDown() {
+ final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+ listener.onSessionDown(mockedSession, new Exception());
+ Mockito.verify(tunnelManager).onSessionDown(Mockito.any(PccSession.class));
+ }
+
+ @Test
+ public void testSendError() {
+ final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+ listener.onSessionUp(mockedSession);
+ listener.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.ATTEMPT_2ND_SESSION, 0));
+ Mockito.verify(mockedSession).sendMessage(Mockito.<Message>any());
+ }
+
+ @Test
+ public void testSendReport() {
+ final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+ listener.onSessionUp(mockedSession);
+ listener.sendReport(null);
+ Mockito.verify(mockedSession).sendMessage(Mockito.<Message>any());
+ }
+
+ @Test
+ public void testGetId() {
+ final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+ Assert.assertEquals(1, listener.getId());
+ }
+
+ private static PcinitiateMessage createInitMsg(final boolean remove, final boolean endpoint) {
+ // lsp with "unknown" plsp-id
+ final LspBuilder lspBuilder = new LspBuilder()
+ .setAdministrative(true)
+ .setDelegate(true)
+ .setIgnore(false)
+ .setOperational(OperationalStatus.Up)
+ .setPlspId(new PlspId(999L))
+ .setProcessingRule(false)
+ .setRemove(remove)
+ .setSync(true);
+
+ final List<Requests> requests = Lists.newArrayList();
+ final RequestsBuilder reqBuilder = new RequestsBuilder()
+ .setLsp(lspBuilder.build())
+ .setSrp(new SrpBuilder(MsgBuilderUtil.createSrp(123)).addAugmentation(Srp1.class, new Srp1Builder().setRemove(remove).build()).build());
+ if (endpoint) {
+ reqBuilder.setEndpointsObj(new EndpointsObjBuilder().build());
+ }
+ requests.add(reqBuilder.build());
+
+ final PcinitiateMessageBuilder initBuilder = new PcinitiateMessageBuilder()
+ .setRequests(requests);
+ return new PcinitiateBuilder().setPcinitiateMessage(initBuilder.build()).build();
+ }
+
+ private static Pcupd createUpdMsg(final boolean delegation) {
+ final PcupdMessageBuilder msgBuilder = new PcupdMessageBuilder();
+ final UpdatesBuilder updsBuilder = new UpdatesBuilder();
+ updsBuilder.setLsp(new LspBuilder().setDelegate(delegation).setPlspId(new PlspId(1L)).build());
+ final PathBuilder pathBuilder = new PathBuilder();
+ pathBuilder.setEro(
+ new EroBuilder()
+ .setSubobject(Lists.newArrayList(new SubobjectBuilder().setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(
+ new IpPrefixBuilder().setIpPrefix(new IpPrefix(new Ipv4Prefix("127.0.0.2/32"))).build()).build()).build())).build());
+ updsBuilder.setPath(pathBuilder.build());
+ updsBuilder.setSrp(new SrpBuilder().setOperationId(new SrpIdNumber(0L)).build());
+ msgBuilder.setUpdates(Lists.newArrayList(updsBuilder.build()));
+ return new PcupdBuilder().setPcupdMessage(msgBuilder.build()).build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.Lists;
+import com.google.common.net.InetAddresses;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timer;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccTunnelManager;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.RequestsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SrpIdNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SymbolicPathName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.UpdatesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.PathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.symbolic.path.name.tlv.SymbolicPathNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
+
+public class PccTunnelManagerImplTest {
+
+ private static final InetAddress ADDRESS = InetAddresses.forString("1.2.4.5");
+ private static final Timer TIMER = new HashedWheelTimer();
+ private static final byte[] SYMBOLIC_NAME = "tets".getBytes(Charsets.UTF_8);
+ private static final Ero ERO = new EroBuilder()
+ .setSubobject(Lists.newArrayList(new SubobjectBuilder().setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(
+ new IpPrefixBuilder().setIpPrefix(new IpPrefix(new Ipv4Prefix("127.0.0.2/32"))).build()).build()).build())).build();
+
+ @Mock
+ private PccSession session1;
+ @Mock
+ private PccSession session2;
+
+ private final List<PCEPErrors> errorsSession1 = new ArrayList<>();
+
+ private final List<PCEPErrors> errorsSession2 = new ArrayList<>();
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Mockito.doNothing().when(session1).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(final InvocationOnMock invocation) throws Throwable {
+ errorsSession1.add(getError((Pcerr) invocation.getArguments()[0]));
+ return null;
+ }
+ }).when(session1).sendError(Mockito.any(Pcerr.class));
+ Mockito.doReturn(0).when(session1).getId();
+ Mockito.doNothing().when(session2).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(final InvocationOnMock invocation) throws Throwable {
+ errorsSession2.add(getError((Pcerr) invocation.getArguments()[0]));
+ return null;
+ }
+ }).when(session2).sendError(Mockito.any(Pcerr.class));
+ Mockito.doReturn(1).when(session2).getId();
+ }
+
+ @After
+ public void tearDown() {
+ this.errorsSession1.clear();
+ this.errorsSession2.clear();
+ }
+
+ @Test
+ public void testOnSessionUp() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ //1 reported LSP + 1 end-of-sync marker
+ Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ //1 reported LSP + 1 end-of-sync marker
+ Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ }
+
+ @Test
+ public void testOnSessionDownAndDelegateBack() throws InterruptedException {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 1, 10, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ tunnelManager.onSessionDown(session1);
+ Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ tunnelManager.onSessionUp(session1);
+ Mockito.verify(session1, Mockito.times(4)).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ }
+
+ @Test
+ public void testOnSessionDownAndDelegateToOther() throws InterruptedException {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, -1, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ tunnelManager.onSessionDown(session1);
+ Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ //wait for re-delegation timeout expires
+ Thread.sleep(500);
+ Mockito.verify(session2, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+ tunnelManager.onSessionUp(session1);
+ Mockito.verify(session1, Mockito.times(4)).sendReport(Mockito.any(Pcrpt.class));
+ }
+
+ @Test
+ public void testReportToAll() throws InterruptedException {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ tunnelManager.reportToAll(createUpdate(1), session1);
+ Mockito.verify(session1, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.verify(session2, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+ }
+
+ @Test
+ public void testReportToAllUnknownLsp() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.reportToAll(createUpdate(2), session1);
+ Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+ assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, errorsSession1.get(0));
+ }
+
+ @Test
+ public void testReportToAllNonDelegatedLsp() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ tunnelManager.reportToAll(createUpdate(1), session2);
+ Mockito.verify(session2, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+ assertEquals(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, errorsSession2.get(0));
+ }
+
+ @Test
+ public void testReturnDelegationPccLsp() throws InterruptedException {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 1, -1, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ tunnelManager.returnDelegation(createUpdate(1), session1);
+ Mockito.verify(session1, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ //wait for re-delegation timer expires
+ Thread.sleep(1200);
+ Mockito.verify(session2, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+ }
+
+ @Test
+ public void testReturnDelegationUnknownLsp() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.returnDelegation(createUpdate(2), session1);
+ Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+ assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, errorsSession1.get(0));
+ }
+
+ @Test
+ public void testReturnDelegationNonDelegatedLsp() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ tunnelManager.returnDelegation(createUpdate(1), session2);
+ Mockito.verify(session2, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+ assertEquals(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, errorsSession2.get(0));
+ }
+
+ @Test
+ public void testAddTunnel() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ tunnelManager.addTunnel(createRequests(1), session1);
+ Mockito.verify(session1, Mockito.times(1)).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.verify(session2, Mockito.times(1)).sendReport(Mockito.any(Pcrpt.class));
+ }
+
+ @Test
+ public void testRemoveTunnel() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ tunnelManager.addTunnel(createRequests(1), session1);
+ tunnelManager.removeTunnel(createRequests(1), session1);
+ Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ }
+
+ @Test
+ public void testRemoveTunnelUnknownLsp() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.removeTunnel(createRequests(1), session1);
+ Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+ assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, errorsSession1.get(0));
+ }
+
+ @Test
+ public void testRemoveTunnelNotPceInitiatedLsp() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.removeTunnel(createRequests(1), session1);
+ Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+ assertEquals(PCEPErrors.LSP_NOT_PCE_INITIATED, errorsSession1.get(0));
+ }
+
+ @Test
+ public void testRemoveTunnelNotDelegated() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ tunnelManager.addTunnel(createRequests(1), session1);
+ tunnelManager.removeTunnel(createRequests(1), session2);
+ Mockito.verify(session2, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+ assertEquals(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, errorsSession2.get(0));
+ }
+
+ @Test
+ public void testTakeDelegation() throws InterruptedException {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, -1, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ tunnelManager.addTunnel(createRequests(1), session1);
+ tunnelManager.returnDelegation(createUpdate(1), session1);
+ Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.verify(session2, Mockito.times(1)).sendReport(Mockito.any(Pcrpt.class));
+ Thread.sleep(500);
+ tunnelManager.takeDelegation(createRequests(1), session2);
+ Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ }
+
+ @Test
+ public void testTakeDelegationUnknownLsp() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.takeDelegation(createRequests(1), session1);
+ Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+ assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, errorsSession1.get(0));
+ }
+
+ @Test
+ public void testTakeDelegationNotPceInitiatedLsp() {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.takeDelegation(createRequests(1), session1);
+ Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+ assertEquals(PCEPErrors.LSP_NOT_PCE_INITIATED, errorsSession1.get(0));
+ }
+
+ @Test
+ public void testReturnDelegationNoRetake() throws InterruptedException {
+ final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+ tunnelManager.onSessionUp(session1);
+ tunnelManager.onSessionUp(session2);
+ tunnelManager.addTunnel(createRequests(1), session1);
+ tunnelManager.returnDelegation(createUpdate(1), session1);
+ //wait for state timeout expires
+ Thread.sleep(500);
+ Mockito.verify(session1, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+ Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+ }
+
+ private static Updates createUpdate(final long plspId) {
+ final UpdatesBuilder updsBuilder = new UpdatesBuilder();
+ updsBuilder.setLsp(new LspBuilder().setPlspId(new PlspId(plspId)).build());
+ final PathBuilder pathBuilder = new PathBuilder();
+ pathBuilder.setEro(ERO);
+ updsBuilder.setPath(pathBuilder.build());
+ updsBuilder.setSrp(new SrpBuilder().setOperationId(new SrpIdNumber(0L)).build());
+ return updsBuilder.build();
+ }
+
+ private static Requests createRequests(final long plspId) {
+ final RequestsBuilder reqBuilder = new RequestsBuilder();
+ reqBuilder.setEro(ERO);
+ reqBuilder.setLsp(new LspBuilder()
+ .setTlvs(new TlvsBuilder().setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(SYMBOLIC_NAME)).build()).build())
+ .setPlspId(new PlspId(plspId)).build());
+ reqBuilder.setSrp(new SrpBuilder().setOperationId(new SrpIdNumber(0L)).build());
+ return reqBuilder.build();
+ }
+
+ private static PCEPErrors getError(final Pcerr errorMessage) {
+ final ErrorObject errorObject = errorMessage.getPcerrMessage().getErrors().get(0).getErrorObject();
+ return PCEPErrors.forValue(errorObject.getType(), errorObject.getValue());
+ }
+
+}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.protocol.pcep.pcc.mock;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import com.google.common.collect.Lists;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.List;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.opendaylight.protocol.pcep.PCEPSession;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PcupdBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SrpIdNumber;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.PcupdMessageBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.UpdatesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.PathBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
-
-public class SimpleSessionListenerTest {
-
- private static final String IP_ADDRESS = "127.0.0.1";
-
- @Mock
- private PCEPSession mockedSession;
-
- private final List<Message> sendMessages = Lists.newArrayList();
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- Mockito.doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- SimpleSessionListenerTest.this.sendMessages.add((Message) invocation.getArguments()[0]);
- return null;
- }
- }).when(mockedSession).sendMessage(Mockito.any(Message.class));
- }
-
- @After
- public void cleanup() {
- this.sendMessages.clear();
- }
-
- @Test
- public void testSessionListenerPcRpt() throws UnknownHostException {
- final SimpleSessionListener sessionListser = new SimpleSessionListener(1, false, InetAddress.getByName(IP_ADDRESS));
-
- sessionListser.onSessionUp(this.mockedSession);
- // one lsp + end-of-sync marker
- Mockito.verify(this.mockedSession, Mockito.times(2)).sendMessage(Mockito.any(Message.class));
- assertEquals(2, this.sendMessages.size());
- assertTrue(this.sendMessages.get(0) instanceof Pcrpt);
- assertTrue(this.sendMessages.get(1) instanceof Pcrpt);
-
- sessionListser.onMessage(this.mockedSession, createUpdMsg());
- // send PcRpt as a response to PcUpd
- Mockito.verify(this.mockedSession, Mockito.times(3)).sendMessage(Mockito.any(Message.class));
- assertEquals(3, this.sendMessages.size());
- assertTrue(this.sendMessages.get(2) instanceof Pcrpt);
-
- sessionListser.onSessionDown(mockedSession, new Exception());
- Mockito.verify(this.mockedSession, Mockito.times(1)).close();
- }
-
- @Test
- public void testSessionListenerPcErr() throws UnknownHostException {
- final SimpleSessionListener sessionListser = new SimpleSessionListener(1, true, InetAddress.getByName(IP_ADDRESS));
-
- sessionListser.onMessage(this.mockedSession, createUpdMsg());
- // send PcErr as a response to PcUpd
- Mockito.verify(this.mockedSession, Mockito.times(1)).sendMessage(Mockito.any(Message.class));
- assertEquals(1, this.sendMessages.size());
- assertTrue(this.sendMessages.get(0) instanceof Pcerr);
- }
-
- private Pcupd createUpdMsg() {
- final PcupdMessageBuilder msgBuilder = new PcupdMessageBuilder();
- final UpdatesBuilder updsBuilder = new UpdatesBuilder();
- updsBuilder.setLsp(new LspBuilder().setPlspId(new PlspId(1L)).build());
- final PathBuilder pathBuilder = new PathBuilder();
- pathBuilder.setEro(
- new EroBuilder()
- .setSubobject(Lists.newArrayList(new SubobjectBuilder().setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(
- new IpPrefixBuilder().setIpPrefix(new IpPrefix(new Ipv4Prefix("127.0.0.2/32"))).build()).build()).build())).build());
- updsBuilder.setPath(pathBuilder.build());
- updsBuilder.setSrp(new SrpBuilder().setOperationId(new SrpIdNumber(0L)).build());
- msgBuilder.setUpdates(Lists.newArrayList(updsBuilder.build()));
- return new PcupdBuilder().setPcupdMessage(msgBuilder.build()).build();
- }
-}
* No StartTLS message before StartTLSWait timer expired
* TODO: error code to be assigned by IANA
*/
- STARTTLS_TIMER_EXP(30, 5);
+ STARTTLS_TIMER_EXP(30, 5),
+ /**
+ * LSP is not PCE-initiated
+ */
+ LSP_NOT_PCE_INITIATED(19, 9);
private PCEPErrorIdentifier errorId;
private static final Map<PCEPErrorIdentifier, PCEPErrors> VALUE_MAP;