Marc De Leenheer
Committed by Gerrit Code Review

Add OCh signal type to optical path intent.

Revert changes to LINC-OE specialized flowmod handling.

Change-Id: Ic4f333a44b7cd8a3111bfcba87ea909943eec56d
......@@ -21,9 +21,9 @@ package org.onosproject.net;
*/
public enum OchSignalType {
/**
* Represents fix grid.
* Represents fixed grid.
*/
FIX_GRID,
FIXED_GRID,
/**
* Represents flex grid.
......
......@@ -389,6 +389,7 @@ public final class Criteria {
* @param sigType optical signal type (8 bits unsigned integer)
* @return match criterion
*/
@Deprecated
public static Criterion matchOpticalSignalType(short sigType) {
return new OpticalSignalTypeCriterion(sigType, Type.OCH_SIGTYPE);
}
......
......@@ -23,6 +23,7 @@ import static com.google.common.base.MoreObjects.toStringHelper;
* Implementation of optical signal type criterion (8 bits unsigned
* integer).
*/
@Deprecated
public final class OpticalSignalTypeCriterion implements Criterion {
private static final short MASK = 0xff;
private final short signalType; // Signal type value: 8 bits
......
......@@ -18,6 +18,7 @@ package org.onosproject.net.intent;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.Path;
import com.google.common.base.MoreObjects;
......@@ -31,6 +32,7 @@ public final class OpticalPathIntent extends Intent {
private final ConnectPoint dst;
private final Path path;
private final OchSignal lambda;
private final OchSignalType signalType;
private OpticalPathIntent(ApplicationId appId,
Key key,
......@@ -38,12 +40,14 @@ public final class OpticalPathIntent extends Intent {
ConnectPoint dst,
Path path,
OchSignal lambda,
OchSignalType signalType,
int priority) {
super(appId, key, ImmutableSet.copyOf(path.links()), priority);
this.src = checkNotNull(src);
this.dst = checkNotNull(dst);
this.path = checkNotNull(path);
this.lambda = checkNotNull(lambda);
this.signalType = checkNotNull(signalType);
}
protected OpticalPathIntent() {
......@@ -51,6 +55,7 @@ public final class OpticalPathIntent extends Intent {
this.dst = null;
this.path = null;
this.lambda = null;
this.signalType = null;
}
/**
......@@ -71,6 +76,7 @@ public final class OpticalPathIntent extends Intent {
private ConnectPoint dst;
private Path path;
private OchSignal lambda;
private OchSignalType signalType;
Key key;
@Override
......@@ -133,6 +139,17 @@ public final class OpticalPathIntent extends Intent {
}
/**
* Sets the optical signal type for the intent that will be built.
*
* @param signalType the optical signal type
* @return this builder
*/
public Builder signalType(OchSignalType signalType) {
this.signalType = signalType;
return this;
}
/**
* Builds an optical path intent from the accumulated parameters.
*
* @return optical path intent
......@@ -146,6 +163,7 @@ public final class OpticalPathIntent extends Intent {
dst,
path,
lambda,
signalType,
priority
);
}
......@@ -168,6 +186,10 @@ public final class OpticalPathIntent extends Intent {
return lambda;
}
public OchSignalType signalType() {
return signalType;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
......@@ -179,6 +201,7 @@ public final class OpticalPathIntent extends Intent {
.add("egressPort", dst)
.add("path", path)
.add("lambda", lambda)
.add("signalType", signalType)
.toString();
}
}
......
......@@ -221,8 +221,8 @@ public class CriteriaTest {
Criterion sameAsMatchLambda1 = Criteria.matchLambda(lambda1);
Criterion matchLambda2 = Criteria.matchLambda(lambda2);
Criterion matchOchSignalType1 = Criteria.matchOchSignalType(OchSignalType.FIX_GRID);
Criterion sameAsMatchOchSignalType1 = Criteria.matchOchSignalType(OchSignalType.FIX_GRID);
Criterion matchOchSignalType1 = Criteria.matchOchSignalType(OchSignalType.FIXED_GRID);
Criterion sameAsMatchOchSignalType1 = Criteria.matchOchSignalType(OchSignalType.FIXED_GRID);
Criterion matchOchSignalType2 = Criteria.matchOchSignalType(OchSignalType.FLEX_GRID);
Criterion matchIndexedLambda1 = Criteria.matchLambda(Lambda.indexedLambda(1));
......
......@@ -18,7 +18,7 @@ package org.onosproject.net.intent;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.Path;
import com.google.common.testing.EqualsTester;
......@@ -39,7 +39,6 @@ public class OpticalPathIntentTest extends AbstractIntentTest {
OpticalPathIntent intent1;
OpticalPathIntent intent2;
Path defaultPath;
OchSignal lambda;
@Before
public void opticalPathIntentTestSetUp() {
......@@ -50,6 +49,7 @@ public class OpticalPathIntentTest extends AbstractIntentTest {
.dst(connectPoint("two", 2))
.path(defaultPath)
.lambda(createLambda())
.signalType(OchSignalType.FIXED_GRID)
.priority(PRIORITY)
.build();
......@@ -59,6 +59,7 @@ public class OpticalPathIntentTest extends AbstractIntentTest {
.dst(connectPoint("one", 2))
.path(defaultPath)
.lambda(createLambda())
.signalType(OchSignalType.FIXED_GRID)
.priority(PRIORITY)
.build();
}
......@@ -83,7 +84,7 @@ public class OpticalPathIntentTest extends AbstractIntentTest {
}
/**
* Checks that the optical path ntent objects are created correctly.
* Checks that the optical path intent objects are created correctly.
*/
@Test
public void testContents() {
......
......@@ -31,6 +31,7 @@ import org.onosproject.net.GridType;
import org.onosproject.net.Link;
import org.onosproject.net.OchPort;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.OmsPort;
import org.onosproject.net.Path;
import org.onosproject.net.Port;
......@@ -127,6 +128,8 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
// Create installable optical path intent
LambdaResourceAllocation lambdaAlloc = getWavelength(path, linkAllocs);
OchSignal ochSignal = getOchSignal(lambdaAlloc, omsPort.minFrequency(), omsPort.grid());
// Only support fixed grid for now
OchSignalType signalType = OchSignalType.FIXED_GRID;
Intent newIntent = OpticalPathIntent.builder()
.appId(intent.appId())
......@@ -134,6 +137,7 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
.dst(intent.getDst())
.path(path)
.lambda(ochSignal)
.signalType(signalType)
.build();
return ImmutableList.of(newIntent);
......
......@@ -103,6 +103,7 @@ public class OpticalPathIntentCompiler implements IntentCompiler<OpticalPathInte
current = link.dst();
selectorBuilder.matchInPort(link.dst().port());
selectorBuilder.add(Criteria.matchLambda(intent.lambda()));
selectorBuilder.add(Criteria.matchOchSignalType(intent.signalType()));
}
// Build the egress ROADM rule
......
......@@ -26,6 +26,7 @@ import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.Link;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
......@@ -95,6 +96,7 @@ public class OpticalPathIntentCompilerTest {
.dst(d3p1)
.path(new DefaultPath(PID, links, hops))
.lambda(createLambda())
.signalType(OchSignalType.FIXED_GRID)
.build();
intentExtensionService = createMock(IntentExtensionService.class);
intentExtensionService.registerCompiler(OpticalPathIntent.class, sut);
......
......@@ -24,62 +24,30 @@ import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotSta
import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply;
import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFFlowModCommand;
import org.projectfloodlight.openflow.protocol.OFInstructionType;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFObject;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsType;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.protocol.OFActionType;
import org.projectfloodlight.openflow.types.CircuitSignalID;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.U8;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Set;
import java.util.BitSet;
import java.util.stream.Collectors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
import static org.projectfloodlight.openflow.protocol.OFFlowMod.Builder;
/**
* LINC-OE Optical Emulator switch class.
*/
public class OFOpticalSwitchImplLINC13
extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
// default number of lambdas, assuming 50GHz channels.
private static final int NUM_CHLS = 80;
private final OFFactory factory = OFFactories.getFactory(OFVersion.OF_13);
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
private long barrierXidToWaitFor = -1;
private OFCircuitPortsReply wPorts;
// book-keeping maps for allocated Linc-OE lambdas
protected final ConcurrentMap<OFPort, BitSet> portChannelMap = new ConcurrentHashMap<>();
protected final ConcurrentMap<Match, Integer> matchMap = new ConcurrentHashMap<>();
@Override
public void startDriverHandshake() {
......@@ -201,139 +169,4 @@ public class OFOpticalSwitchImplLINC13
public Set<PortDescPropertyType> getPortTypes() {
return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT);
}
@Override
public OFMessage prepareMessage(OFMessage msg) {
if (OFVersion.OF_13 != msg.getVersion() || msg.getType() != OFType.FLOW_MOD) {
return msg;
}
OFFlowMod fm = (OFFlowMod) msg;
Match match = fm.getMatch();
// Don't touch FlowMods that aren't Optical-related.
if (match.get(MatchField.OCH_SIGTYPE) == null) {
return msg;
}
OFMessage newFM;
Builder builder = null;
List<OFAction> actions = new ArrayList<>();
if (fm.getCommand() == OFFlowModCommand.ADD) {
builder = factory.buildFlowAdd();
int lambda = allocateLambda(match.get(MatchField.IN_PORT), match);
CircuitSignalID sigid = new CircuitSignalID((byte) 1, (byte) 2, (short) lambda, (short) 1);
List<OFInstruction> instructions = fm.getInstructions();
newFM = buildFlowMod(builder, fm, buildMatch(match, sigid), buildActions(instructions, sigid));
} else if (fm.getCommand() == OFFlowModCommand.DELETE) {
builder = factory.buildFlowDelete();
int lambda = freeLambda(match.get(MatchField.IN_PORT), match);
CircuitSignalID sigid = new CircuitSignalID((byte) 1, (byte) 2, (short) lambda, (short) 1);
newFM = buildFlowMod(builder, fm, buildMatch(match, sigid), actions);
} else {
newFM = msg;
}
log.debug("new FM = {}", newFM);
return newFM;
}
// fetch the next available channel as the flat lambda value, or the lambda
// associated with a port/match combination
private int allocateLambda(OFPort port, Match match) {
Integer lambda = null;
synchronized (this) {
BitSet channels = portChannelMap.getOrDefault(port, new BitSet(NUM_CHLS + 1));
lambda = matchMap.get(match);
if (lambda == null) {
// TODO : double check behavior when bitset is full
// Linc lambdas start at 1.
lambda = channels.nextClearBit(1);
channels.set(lambda);
portChannelMap.put(port, channels);
matchMap.put(match, lambda);
}
}
return lambda;
}
// free lambda that was mapped to Port/Match combination and return its
// value to caller.
private int freeLambda(OFPort port, Match match) {
synchronized (this) {
Integer lambda = matchMap.get(match);
if (lambda != null) {
portChannelMap.get(port).clear(lambda);
return lambda;
}
// 1 is a sane-ish default for Linc.
return 1;
}
}
// build matches - *tons of assumptions are made here based on Linc-OE's behavior.*
// gridType = 1 (DWDM)
// channelSpacing = 2 (50GHz)
// spectralWidth = 1 (fixed grid default value)
private Match buildMatch(Match original, CircuitSignalID sigid) {
Match.Builder mBuilder = factory.buildMatch();
original.getMatchFields().forEach(mf -> {
String name = mf.getName();
if (MatchField.OCH_SIGID.getName().equals(name)) {
mBuilder.setExact(MatchField.OCH_SIGID, sigid);
} else if (MatchField.OCH_SIGTYPE.getName().equals(name)) {
mBuilder.setExact(MatchField.OCH_SIGTYPE, U8.of((short) 1));
} else if (MatchField.IN_PORT.getName().equals(name)) {
mBuilder.setExact(MatchField.IN_PORT, original.get(MatchField.IN_PORT));
}
});
return mBuilder.build();
}
private List<OFAction> buildActions(List<OFInstruction> iList, CircuitSignalID sigid) {
Map<OFInstructionType, OFInstruction> instructions = iList.stream()
.collect(Collectors.toMap(OFInstruction::getType, inst -> inst));
OFInstruction inst = instructions.get(OFInstructionType.APPLY_ACTIONS);
if (inst == null) {
return Collections.emptyList();
}
List<OFAction> actions = new ArrayList<>();
OFInstructionApplyActions iaa = (OFInstructionApplyActions) inst;
if (iaa.getActions() == null) {
return actions;
}
iaa.getActions().forEach(action -> {
if (OFActionType.EXPERIMENTER == action.getType()) {
OFActionCircuit.Builder cBuilder = factory.actions().buildCircuit()
.setField(factory.oxms()
.buildOchSigid()
.setValue(sigid)
.build());
actions.add(cBuilder.build());
} else {
actions.add(action);
}
});
return actions;
}
private OFMessage buildFlowMod(Builder builder, OFFlowMod fm, Match m, List<OFAction> act) {
return builder
.setXid(fm.getXid())
.setCookie(fm.getCookie())
.setCookieMask(fm.getCookieMask())
.setTableId(fm.getTableId())
.setIdleTimeout(fm.getIdleTimeout())
.setHardTimeout(fm.getHardTimeout())
.setBufferId(fm.getBufferId())
.setOutPort(fm.getOutPort())
.setOutGroup(fm.getOutGroup())
.setFlags(fm.getFlags())
.setMatch(m)
.setActions(act)
.build();
}
}
......
......@@ -148,16 +148,4 @@ public interface OpenFlowSwitch {
* @return string representation of the connection to the device
*/
String channelId();
/**
* Prepares a message to be sent, if necessary. Default is to do nothing,
* since most Devices do not need to pre-process a message that's about to
* be sent.
*
* @param msg The message to prepare for sending
* @return the prepared OFMessage
*/
default OFMessage prepareMessage(OFMessage msg) {
return msg;
}
}
......
......@@ -97,7 +97,7 @@ public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
@Override
public final void sendMsg(OFMessage m) {
if (role == RoleState.MASTER && channel.isWritable()) {
channel.write(Collections.singletonList(prepareMessage(m)));
channel.write(Collections.singletonList(m));
}
}
......
......@@ -40,7 +40,7 @@ import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
import org.onosproject.net.flow.criteria.OpticalSignalTypeCriterion;
import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.SctpPortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
......@@ -388,10 +388,9 @@ public abstract class FlowModBuilder {
}
break;
case OCH_SIGTYPE:
OpticalSignalTypeCriterion sc =
(OpticalSignalTypeCriterion) c;
mBuilder.setExact(MatchField.OCH_SIGTYPE,
U8.of(sc.signalType()));
OchSignalTypeCriterion sc = (OchSignalTypeCriterion) c;
byte signalType = FlowModBuilderHelper.convertOchSignalType(sc.signalType());
mBuilder.setExact(MatchField.OCH_SIGTYPE, U8.of(signalType));
break;
case ARP_OP:
case ARP_SHA:
......
......@@ -17,6 +17,7 @@ package org.onosproject.provider.of.flow.impl;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.OchSignalType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -87,4 +88,22 @@ final class FlowModBuilderHelper {
throw new UnsupportedChannelSpacingException(spacing);
}
}
/**
* Converts a {@link OchSignalType} to the corresponding byte value.
*
* @param signalType optical signal type
* @return byte value corresponding to the specified OCh signal type
*/
static byte convertOchSignalType(OchSignalType signalType) {
switch (signalType) {
case FIXED_GRID:
return (byte) 1;
case FLEX_GRID:
return (byte) 2;
default:
log.info("OchSignalType {} is not supported", signalType);
return (byte) 0;
}
}
}
......
......@@ -67,7 +67,7 @@ from mininet.link import Link, Intf
from mininet.cli import CLI
# Sleep time and timeout values in seconds
SLEEP_TIME = .5
SLEEP_TIME = 2
TIMEOUT = 60
class OpticalSwitch(Switch):
......