Madan Jampani

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

Showing 88 changed files with 1048 additions and 1420 deletions
package org.onlab.onos.ifwd;
import static org.slf4j.LoggerFactory.getLogger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.CoreService;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.PortNumber;
......@@ -16,7 +16,6 @@ import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.HostToHostIntent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.packet.DefaultOutboundPacket;
import org.onlab.onos.net.packet.InboundPacket;
......@@ -28,6 +27,8 @@ import org.onlab.onos.net.topology.TopologyService;
import org.onlab.packet.Ethernet;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;
/**
* WORK-IN-PROGRESS: Sample reactive forwarding application using intent framework.
*/
......@@ -37,6 +38,9 @@ public class IntentReactiveForwarding {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
......@@ -49,11 +53,11 @@ public class IntentReactiveForwarding {
protected HostService hostService;
private ReactivePacketProcessor processor = new ReactivePacketProcessor();
private static long intentId = 0x123000;
private ApplicationId appId;
@Activate
public void activate() {
appId = coreService.registerApplication("org.onlab.onos.ifwd");
packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
log.info("Started");
}
......@@ -126,8 +130,7 @@ public class IntentReactiveForwarding {
TrafficSelector selector = DefaultTrafficSelector.builder().build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
HostToHostIntent intent =
new HostToHostIntent(new IntentId(intentId++), srcId, dstId,
HostToHostIntent intent = new HostToHostIntent(appId, srcId, dstId,
selector, treatment);
intentService.submit(intent);
......
package org.onlab.onos.sdnip;
import java.util.List;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.sdnip.config.BgpPeer;
......@@ -22,6 +20,8 @@ import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Manages the connectivity requirements between peers.
*/
......@@ -38,11 +38,13 @@ public class PeerConnectivityManager {
private final InterfaceService interfaceService;
private final IntentService intentService;
// TODO this sucks.
private int intentId = 0;
private final ApplicationId appId;
public PeerConnectivityManager(SdnIpConfigService configInfoService,
InterfaceService interfaceService, IntentService intentService) {
public PeerConnectivityManager(ApplicationId appId,
SdnIpConfigService configInfoService,
InterfaceService interfaceService,
IntentService intentService) {
this.appId = appId;
this.configInfoService = configInfoService;
this.interfaceService = interfaceService;
this.intentService = intentService;
......@@ -134,8 +136,8 @@ public class PeerConnectivityManager {
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.build();
PointToPointIntent intentMatchDstTcpPort = new PointToPointIntent(
nextIntentId(), selector, treatment,
PointToPointIntent intentMatchDstTcpPort =
new PointToPointIntent(appId, selector, treatment,
bgpdConnectPoint, bgpdPeerConnectPoint);
intentService.submit(intentMatchDstTcpPort);
log.debug("Submitted BGP path intent matching dst TCP port 179 "
......@@ -152,8 +154,8 @@ public class PeerConnectivityManager {
.matchTcpSrc(BGP_PORT)
.build();
PointToPointIntent intentMatchSrcTcpPort = new PointToPointIntent(
nextIntentId(), selector, treatment,
PointToPointIntent intentMatchSrcTcpPort =
new PointToPointIntent(appId, selector, treatment,
bgpdConnectPoint, bgpdPeerConnectPoint);
intentService.submit(intentMatchSrcTcpPort);
log.debug("Submitted BGP path intent matching src TCP port 179"
......@@ -170,8 +172,8 @@ public class PeerConnectivityManager {
.matchTcpDst(BGP_PORT)
.build();
PointToPointIntent reversedIntentMatchDstTcpPort = new PointToPointIntent(
nextIntentId(), selector, treatment,
PointToPointIntent reversedIntentMatchDstTcpPort =
new PointToPointIntent(appId, selector, treatment,
bgpdPeerConnectPoint, bgpdConnectPoint);
intentService.submit(reversedIntentMatchDstTcpPort);
log.debug("Submitted BGP path intent matching dst TCP port 179"
......@@ -188,8 +190,8 @@ public class PeerConnectivityManager {
.matchTcpSrc(BGP_PORT)
.build();
PointToPointIntent reversedIntentMatchSrcTcpPort = new PointToPointIntent(
nextIntentId(), selector, treatment,
PointToPointIntent reversedIntentMatchSrcTcpPort =
new PointToPointIntent(appId, selector, treatment,
bgpdPeerConnectPoint, bgpdConnectPoint);
intentService.submit(reversedIntentMatchSrcTcpPort);
log.debug("Submitted BGP path intent matching src TCP port 179"
......@@ -258,8 +260,8 @@ public class PeerConnectivityManager {
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.build();
PointToPointIntent intent = new PointToPointIntent(
nextIntentId(), selector, treatment,
PointToPointIntent intent =
new PointToPointIntent(appId, selector, treatment,
bgpdConnectPoint, bgpdPeerConnectPoint);
intentService.submit(intent);
log.debug("Submitted ICMP path intent from BGPd {} to peer {} :"
......@@ -273,8 +275,8 @@ public class PeerConnectivityManager {
.matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
.build();
PointToPointIntent reversedIntent = new PointToPointIntent(
nextIntentId(), selector, treatment,
PointToPointIntent reversedIntent =
new PointToPointIntent(appId, selector, treatment,
bgpdPeerConnectPoint, bgpdConnectPoint);
intentService.submit(reversedIntent);
log.debug("Submitted ICMP path intent from BGP peer {} to BGPd"
......@@ -284,7 +286,4 @@ public class PeerConnectivityManager {
}
}
private IntentId nextIntentId() {
return new IntentId(intentId++);
}
}
......
package org.onlab.onos.sdnip;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import com.google.common.base.Objects;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.googlecode.concurrenttrees.common.KeyValuePair;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import org.apache.commons.lang3.tuple.Pair;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.flow.DefaultTrafficSelector;
......@@ -29,7 +24,6 @@ import org.onlab.onos.net.host.HostEvent;
import org.onlab.onos.net.host.HostListener;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
import org.onlab.onos.sdnip.config.BgpPeer;
......@@ -42,20 +36,25 @@ import org.onlab.packet.MacAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Objects;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.googlecode.concurrenttrees.common.KeyValuePair;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
/**
* This class processes BGP route update, translates each update into a intent
* and submits the intent.
*
* <p/>
* TODO: Make it thread-safe.
*/
public class Router implements RouteListener {
......@@ -82,8 +81,7 @@ public class Router implements RouteListener {
private ExecutorService bgpUpdatesExecutor;
private ExecutorService bgpIntentsSynchronizerExecutor;
// TODO temporary
private int intentId = Integer.MAX_VALUE / 2;
private final ApplicationId appId;
//
// State to deal with SDN-IP Leader election and pushing Intents
......@@ -104,9 +102,10 @@ public class Router implements RouteListener {
* @param configInfoService the configuration service
* @param interfaceService the interface service
*/
public Router(IntentService intentService, HostService hostService,
SdnIpConfigService configInfoService, InterfaceService interfaceService) {
public Router(ApplicationId appId, IntentService intentService,
HostService hostService, SdnIpConfigService configInfoService,
InterfaceService interfaceService) {
this.appId = appId;
this.intentService = intentService;
this.hostService = hostService;
this.configInfoService = configInfoService;
......@@ -609,8 +608,8 @@ public class Router implements RouteListener {
.build();
MultiPointToSinglePointIntent intent =
new MultiPointToSinglePointIntent(nextIntentId(),
selector, treatment, ingressPorts, egressPort);
new MultiPointToSinglePointIntent(appId, selector, treatment,
ingressPorts, egressPort);
if (isElectedLeader && isActivatedLeader) {
log.debug("Intent installation: adding Intent for prefix: {}",
......@@ -745,15 +744,6 @@ public class Router implements RouteListener {
}
/**
* Generates a new unique intent ID.
*
* @return the new intent ID.
*/
private IntentId nextIntentId() {
return new IntentId(intentId++);
}
/**
* Listener for host events.
*/
class InternalHostListener implements HostListener {
......
......@@ -10,6 +10,8 @@ import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.CoreService;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.sdnip.bgp.BgpRouteEntry;
......@@ -24,9 +26,14 @@ import org.slf4j.Logger;
@Service
public class SdnIp implements SdnIpService {
private static final String SDN_ID_APP = "org.onlab.onos.sdnip";
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
......@@ -46,10 +53,11 @@ public class SdnIp implements SdnIpService {
InterfaceService interfaceService = new HostToInterfaceAdaptor(hostService);
peerConnectivity = new PeerConnectivityManager(config, interfaceService, intentService);
ApplicationId appId = coreService.registerApplication(SDN_ID_APP);
peerConnectivity = new PeerConnectivityManager(appId, config, interfaceService, intentService);
peerConnectivity.start();
router = new Router(intentService, hostService, config, interfaceService);
router = new Router(appId, intentService, hostService, config, interfaceService);
router.start();
bgpSessionManager = new BgpSessionManager(router);
......
package org.onlab.onos.sdnip;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reportMatcher;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Sets;
import org.easymock.IArgumentMatcher;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber;
......@@ -25,7 +13,6 @@ import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.sdnip.bgp.BgpConstants;
......@@ -40,13 +27,32 @@ import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static org.easymock.EasyMock.*;
/**
* Unit tests for PeerConnectivityManager interface.
*/
public class PeerConnectivityManagerTest {
private static final ApplicationId APPID = new ApplicationId() {
@Override
public short id() {
return 0;
}
@Override
public String name() {
return "foo";
}
};
private PeerConnectivityManager peerConnectivityManager;
private IntentService intentService;
private SdnIpConfigService configInfoService;
......@@ -81,9 +87,6 @@ public class PeerConnectivityManagerTest {
private final ConnectPoint s2Eth1 =
new ConnectPoint(deviceId2, PortNumber.portNumber(1));
// We don't compare the intent ID so all expected intents can use the same ID
private final IntentId testIntentId = new IntentId(0);
private final TrafficTreatment noTreatment =
DefaultTrafficTreatment.builder().build();
......@@ -257,7 +260,7 @@ public class PeerConnectivityManagerTest {
}
PointToPointIntent intent = new PointToPointIntent(
testIntentId, builder.build(), noTreatment,
APPID, builder.build(), noTreatment,
srcConnectPoint, dstConnectPoint);
intentList.add(intent);
......@@ -429,7 +432,7 @@ public class PeerConnectivityManagerTest {
.build();
PointToPointIntent intent = new PointToPointIntent(
testIntentId, selector, noTreatment,
APPID, selector, noTreatment,
srcConnectPoint, dstConnectPoint);
intentList.add(intent);
......@@ -511,7 +514,7 @@ public class PeerConnectivityManagerTest {
intentService = createMock(IntentService.class);
replay(intentService);
peerConnectivityManager = new PeerConnectivityManager(configInfoService,
peerConnectivityManager = new PeerConnectivityManager(APPID, configInfoService,
interfaceService, intentService);
}
......@@ -557,7 +560,7 @@ public class PeerConnectivityManagerTest {
providedIntentString = providedIntent.toString();
PointToPointIntent matchIntent =
new PointToPointIntent(providedIntent.id(),
new PointToPointIntent(providedIntent.appId(),
intent.selector(), intent.treatment(),
intent.ingressPoint(), intent.egressPoint());
......
......@@ -2,6 +2,8 @@ package org.onlab.onos.cli;
import org.apache.karaf.shell.commands.Option;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.CoreService;
import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.osgi.ServiceNotFoundException;
......@@ -27,6 +29,15 @@ public abstract class AbstractShellCommand extends OsgiCommandSupport {
}
/**
* Returns application ID for the CLI.
*
* @return command-line application identifier
*/
protected ApplicationId appId() {
return get(CoreService.class).registerApplication("org.onlab.onos.cli");
}
/**
* Prints the arguments using the specified format.
*
* @param format format string; see {@link String#format}
......
......@@ -9,7 +9,6 @@ import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.HostToHostIntent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentService;
/**
......@@ -27,8 +26,6 @@ public class AddHostToHostIntentCommand extends AbstractShellCommand {
required = true, multiValued = false)
String two = null;
private static long id = 0x7870001;
@Override
protected void execute() {
IntentService service = get(IntentService.class);
......@@ -39,8 +36,7 @@ public class AddHostToHostIntentCommand extends AbstractShellCommand {
TrafficSelector selector = DefaultTrafficSelector.builder().build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
HostToHostIntent intent =
new HostToHostIntent(new IntentId(id++), oneId, twoId,
HostToHostIntent intent = new HostToHostIntent(appId(), oneId, twoId,
selector, treatment);
service.submit(intent);
}
......
package org.onlab.onos.cli.net;
import java.util.HashSet;
import java.util.Set;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.onos.cli.AbstractShellCommand;
......@@ -14,11 +11,16 @@ import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
import org.onlab.packet.Ethernet;
import java.util.HashSet;
import java.util.Set;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.PortNumber.portNumber;
/**
* Installs point-to-point connectivity intents.
*/
......@@ -31,8 +33,6 @@ public class AddMultiPointToSinglePointIntentCommand extends AbstractShellComman
required = true, multiValued = true)
String[] deviceStrings = null;
private static long id = 0x7070001;
@Override
protected void execute() {
IntentService service = get(IntentService.class);
......@@ -42,33 +42,26 @@ public class AddMultiPointToSinglePointIntentCommand extends AbstractShellComman
}
String egressDeviceString = deviceStrings[deviceStrings.length - 1];
DeviceId egressDeviceId = DeviceId.deviceId(getDeviceId(egressDeviceString));
PortNumber egressPortNumber =
PortNumber.portNumber(getPortNumber(egressDeviceString));
DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString));
PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString));
ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
Set<ConnectPoint> ingressPoints = new HashSet<>();
for (int index = 0; index < deviceStrings.length - 1; index++) {
String ingressDeviceString = deviceStrings[index];
DeviceId ingressDeviceId = DeviceId.deviceId(getDeviceId(ingressDeviceString));
PortNumber ingressPortNumber =
PortNumber.portNumber(getPortNumber(ingressDeviceString));
DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString));
PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString));
ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
ingressPoints.add(ingress);
}
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
Intent intent =
new MultiPointToSinglePointIntent(new IntentId(id++),
selector,
treatment,
ingressPoints,
egress);
Intent intent = new MultiPointToSinglePointIntent(appId(), selector, treatment,
ingressPoints, egress);
service.submit(intent);
}
......
......@@ -11,11 +11,13 @@ import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.packet.Ethernet;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.PortNumber.portNumber;
/**
* Installs point-to-point connectivity intents.
*/
......@@ -33,20 +35,16 @@ public class AddPointToPointIntentCommand extends AbstractShellCommand {
required = true, multiValued = false)
String egressDeviceString = null;
private static long id = 0x7470001;
@Override
protected void execute() {
IntentService service = get(IntentService.class);
DeviceId ingressDeviceId = DeviceId.deviceId(getDeviceId(ingressDeviceString));
PortNumber ingressPortNumber =
PortNumber.portNumber(getPortNumber(ingressDeviceString));
DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString));
PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString));
ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
DeviceId egressDeviceId = DeviceId.deviceId(getDeviceId(egressDeviceString));
PortNumber egressPortNumber =
PortNumber.portNumber(getPortNumber(egressDeviceString));
DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString));
PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString));
ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
TrafficSelector selector = DefaultTrafficSelector.builder()
......@@ -54,12 +52,8 @@ public class AddPointToPointIntentCommand extends AbstractShellCommand {
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
Intent intent =
new PointToPointIntent(new IntentId(id++),
selector,
treatment,
ingress,
egress);
Intent intent = new PointToPointIntent(appId(), selector, treatment,
ingress, egress);
service.submit(intent);
}
......
package org.onlab.onos.cli.net;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.onos.cli.AbstractShellCommand;
......@@ -16,13 +13,18 @@ import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentEvent;
import org.onlab.onos.net.intent.IntentEvent.Type;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentListener;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.packet.Ethernet;
import org.onlab.packet.MacAddress;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.PortNumber.portNumber;
/**
* Installs point-to-point connectivity intents.
*/
......@@ -57,14 +59,12 @@ public class IntentPushTestCommand extends AbstractShellCommand
protected void execute() {
service = get(IntentService.class);
DeviceId ingressDeviceId = DeviceId.deviceId(getDeviceId(ingressDeviceString));
PortNumber ingressPortNumber =
PortNumber.portNumber(getPortNumber(ingressDeviceString));
DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString));
PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString));
ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
DeviceId egressDeviceId = DeviceId.deviceId(getDeviceId(egressDeviceString));
PortNumber egressPortNumber =
PortNumber.portNumber(getPortNumber(egressDeviceString));
DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString));
PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString));
ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
......@@ -81,12 +81,8 @@ public class IntentPushTestCommand extends AbstractShellCommand
TrafficSelector s = selector
.matchEthSrc(MacAddress.valueOf(i))
.build();
Intent intent =
new PointToPointIntent(new IntentId(id++),
s,
treatment,
ingress,
egress);
Intent intent = new PointToPointIntent(appId(), s, treatment,
ingress, egress);
service.submit(intent);
}
try {
......
......@@ -7,6 +7,8 @@ import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentService;
import java.math.BigInteger;
/**
* Removes host-to-host connectivity intent.
*/
......@@ -22,13 +24,11 @@ public class IntentRemoveCommand extends AbstractShellCommand {
protected void execute() {
IntentService service = get(IntentService.class);
int radix = id.startsWith("0x") ? 16 : 10;
if (radix == 16) {
if (id.startsWith("0x")) {
id = id.replaceFirst("0x", "");
}
IntentId intentId = new IntentId(Long.parseLong(id, radix));
IntentId intentId = IntentId.valueOf(new BigInteger(id, 16).longValue());
Intent intent = service.getIntent(intentId);
if (intent != null) {
service.withdraw(intent);
......
......@@ -18,7 +18,8 @@ public class IntentsListCommand extends AbstractShellCommand {
IntentService service = get(IntentService.class);
for (Intent intent : service.getIntents()) {
IntentState state = service.getIntentState(intent.id());
print("%s %s %s", intent.id(), state, intent);
print("id=%s, state=%s, appId=%s, %s",
intent.id(), state, intent.appId().name(), intent);
}
}
......
package org.onlab.onos.cluster;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableList;
/**
* A container for detailed role information for a device,
......@@ -18,9 +16,7 @@ public class RoleInfo {
public RoleInfo(NodeId master, List<NodeId> backups) {
this.master = master;
this.backups = new LinkedList<>();
this.backups.addAll(checkNotNull(backups));
this.backups = ImmutableList.copyOf(backups);
}
public NodeId master() {
......@@ -28,7 +24,7 @@ public class RoleInfo {
}
public List<NodeId> backups() {
return Collections.unmodifiableList(backups);
return backups;
}
@Override
......@@ -57,10 +53,10 @@ public class RoleInfo {
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("master: \n\t").append(master).append("\n");
builder.append("backups: \n");
builder.append("master:").append(master).append(",");
builder.append("backups:");
for (NodeId n : backups) {
builder.append("\t").append(n).append("\n");
builder.append(" ").append(n);
}
return builder.toString();
}
......
......@@ -3,7 +3,7 @@ package org.onlab.onos.net;
/**
* Abstraction of a network infrastructure link.
*/
public interface Link extends Annotated, Provided {
public interface Link extends Annotated, Provided, NetworkResource {
/**
* Coarse representation of the link type.
......
......@@ -8,7 +8,6 @@ import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
......@@ -27,7 +26,7 @@ public final class DefaultTrafficSelector implements TrafficSelector {
* @param criteria criteria
*/
private DefaultTrafficSelector(Set<Criterion> criteria) {
this.criteria = Collections.unmodifiableSet(criteria);
this.criteria = ImmutableSet.copyOf(criteria);
}
@Override
......
......@@ -7,7 +7,8 @@ import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import java.util.Collections;
import com.google.common.collect.ImmutableList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
......@@ -25,7 +26,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
* @param instructions treatment instructions
*/
private DefaultTrafficTreatment(List<Instruction> instructions) {
this.instructions = Collections.unmodifiableList(instructions);
this.instructions = ImmutableList.copyOf(instructions);
}
@Override
......
......@@ -24,7 +24,18 @@ public class FlowRuleEvent extends AbstractEvent<FlowRuleEvent.Type, FlowRule> {
/**
* Signifies that a rule has been updated.
*/
RULE_UPDATED
RULE_UPDATED,
// internal event between Manager <-> Store
/*
* Signifies that a request to add flow rule has been added to the store.
*/
RULE_ADD_REQUESTED,
/*
* Signifies that a request to remove flow rule has been added to the store.
*/
RULE_REMOVE_REQUESTED,
}
/**
......
......@@ -44,16 +44,18 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat
* Stores a new flow rule without generating events.
*
* @param rule the flow rule to add
* @return true if the rule should be handled locally
*/
void storeFlowRule(FlowRule rule);
boolean storeFlowRule(FlowRule rule);
/**
* Marks a flow rule for deletion. Actual deletion will occur
* when the provider indicates that the flow has been removed.
*
* @param rule the flow rule to delete
* @return true if the rule should be handled locally
*/
void deleteFlowRule(FlowRule rule);
boolean deleteFlowRule(FlowRule rule);
/**
* Stores a new flow rule, or updates an existing entry.
......
package org.onlab.onos.net.intent;
/**
* Base intent implementation.
*/
public abstract class AbstractIntent implements Intent {
private final IntentId id;
/**
* Creates a base intent with the specified identifier.
*
* @param id intent identifier
*/
protected AbstractIntent(IntentId id) {
this.id = id;
}
/**
* Constructor for serializer.
*/
protected AbstractIntent() {
this.id = null;
}
@Override
public IntentId id() {
return id;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AbstractIntent that = (AbstractIntent) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
}
package org.onlab.onos.net.intent;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.NetworkResource;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import java.util.Collection;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Abstraction of connectivity intent for traffic matching some criteria.
*/
public abstract class ConnectivityIntent extends AbstractIntent {
public abstract class ConnectivityIntent extends Intent {
// TODO: other forms of intents should be considered for this family:
// point-to-point with constraints (waypoints/obstacles)
......@@ -19,24 +24,26 @@ public abstract class ConnectivityIntent extends AbstractIntent {
// ...
private final TrafficSelector selector;
// TODO: should consider which is better for multiple actions,
// defining compound action class or using list of actions.
private final TrafficTreatment treatment;
/**
* Creates a connectivity intent that matches on the specified intent
* and applies the specified treatement.
* Creates a connectivity intent that matches on the specified selector
* and applies the specified treatment.
*
* @param intentId intent identifier
* @param id intent identifier
* @param appId application identifier
* @param resources required network resources (optional)
* @param selector traffic selector
* @param treatement treatement
* @param treatment treatment
* @throws NullPointerException if the selector or treatement is null
*/
protected ConnectivityIntent(IntentId intentId, TrafficSelector selector,
TrafficTreatment treatement) {
super(intentId);
protected ConnectivityIntent(IntentId id, ApplicationId appId,
Collection<NetworkResource> resources,
TrafficSelector selector,
TrafficTreatment treatment) {
super(id, appId, resources);
this.selector = checkNotNull(selector);
this.treatment = checkNotNull(treatement);
this.treatment = checkNotNull(treatment);
}
/**
......@@ -66,19 +73,14 @@ public abstract class ConnectivityIntent extends AbstractIntent {
return treatment;
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) {
return false;
}
ConnectivityIntent that = (ConnectivityIntent) o;
return Objects.equal(this.selector, that.selector)
&& Objects.equal(this.treatment, that.treatment);
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), selector, treatment);
/**
* Produces a collection of network resources from the given links.
*
* @param links collection of links
* @return collection of link resources
*/
protected static Collection<NetworkResource> resources(Collection<Link> links) {
return ImmutableSet.<NetworkResource>copyOf(links);
}
}
......
package org.onlab.onos.net.intent;
import com.google.common.base.MoreObjects;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
......@@ -18,25 +17,33 @@ public final class HostToHostIntent extends ConnectivityIntent {
private final HostId two;
/**
* Creates a new point-to-point intent with the supplied ingress/egress
* ports.
* Creates a new host-to-host intent with the supplied host pair.
*
* @param intentId intent identifier
* @param appId application identifier
* @param one first host
* @param two second host
* @param selector action
* @param treatment ingress port
* @throws NullPointerException if {@code ingressPort} or {@code egressPort}
* is null.
* @throws NullPointerException if {@code one} or {@code two} is null.
*/
public HostToHostIntent(IntentId intentId, HostId one, HostId two,
public HostToHostIntent(ApplicationId appId, HostId one, HostId two,
TrafficSelector selector,
TrafficTreatment treatment) {
super(intentId, selector, treatment);
super(id(HostToHostIntent.class, min(one, two), max(one, two),
selector, treatment),
appId, null, selector, treatment);
this.one = checkNotNull(one);
this.two = checkNotNull(two);
}
private static HostId min(HostId one, HostId two) {
return one.hashCode() < two.hashCode() ? one : two;
}
private static HostId max(HostId one, HostId two) {
return one.hashCode() > two.hashCode() ? one : two;
}
/**
* Returns identifier of the first host.
*
......@@ -56,31 +63,10 @@ public final class HostToHostIntent extends ConnectivityIntent {
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
HostToHostIntent that = (HostToHostIntent) o;
return Objects.equals(this.one, that.one)
&& Objects.equals(this.two, that.two);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), one, two);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("id", id())
.add("appId", appId())
.add("selector", selector())
.add("treatment", treatment())
.add("one", one)
......
package org.onlab.onos.net.intent;
//TODO is this the right package?
/**
* A generalized interface for ID generation
*
* {@link #getNewId()} generates a globally unique ID instance on
* each invocation.
*
* @param <T> the type of ID
*/
// TODO: do we need to define a base marker interface for ID,
// then changed the type parameter to <T extends BaseId> something
// like that?
public interface IdGenerator<T> {
/**
* Returns a globally unique ID instance.
*
* @return globally unique ID instance
*/
T getNewId();
}
package org.onlab.onos.net.intent;
import org.onlab.onos.net.Link;
import java.util.Collection;
/**
* Abstraction of an intent that can be installed into
* the underlying system without additional compilation.
*/
public interface InstallableIntent extends Intent {
/**
* Returns the collection of links that are required for this installable
* intent to exist.
*
* @return collection of links
*/
// FIXME: replace this with 'NetworkResource'
Collection<Link> requiredLinks();
}
package org.onlab.onos.net.intent;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.NetworkResource;
import java.util.Collection;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Abstraction of an application level intent.
* <p/>
* Make sure that an Intent should be immutable when a new type is defined.
*/
public interface Intent extends BatchOperationTarget {
public abstract class Intent implements BatchOperationTarget {
private final IntentId id;
private final ApplicationId appId;
private final Collection<NetworkResource> resources;
/**
* Constructor for serializer.
*/
protected Intent() {
this.id = null;
this.appId = null;
this.resources = null;
}
/**
* Creates a new intent.
*
* @param id intent identifier
* @param appId application identifier
* @param resources required network resources (optional)
*/
protected Intent(IntentId id, ApplicationId appId,
Collection<NetworkResource> resources) {
this.appId = checkNotNull(appId, "Application ID cannot be null");
this.id = checkNotNull(id, "Fingerprint cannot be null");
this.resources = resources;
}
/**
* Returns the intent identifier.
*
* @return intent fingerprint
*/
public IntentId id() {
return id;
}
/**
* Returns the identifier of the application that requested the intent.
*
* @return application identifier
*/
public ApplicationId appId() {
return appId;
}
/**
* Returns the collection of resources required for this intent.
*
* @return collection of resources; may be null
*/
public Collection<NetworkResource> resources() {
return resources;
}
/**
* Produces an intent identifier backed by hash-like fingerprint for the
* specified class of intent and its constituent fields.
*
* @param fields intent fields
* @return intent identifier
*/
IntentId id();
protected static IntentId id(Object... fields) {
return IntentId.valueOf(Objects.hash(fields));
}
/**
* Indicates whether or not the intent is installable.
*
* @return true if installable
*/
public boolean isInstallable() {
return false;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final Intent other = (Intent) obj;
return Objects.equals(this.id, other.id);
}
}
......
......@@ -38,7 +38,7 @@ public interface IntentExtensionService {
* @param installer intent installer
* @param <T> the type of installable intent
*/
<T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer);
<T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer);
/**
* Unregisters the installer for the given installable intent class.
......@@ -46,12 +46,12 @@ public interface IntentExtensionService {
* @param cls installable intent class
* @param <T> the type of installable intent
*/
<T extends InstallableIntent> void unregisterInstaller(Class<T> cls);
<T extends Intent> void unregisterInstaller(Class<T> cls);
/**
* Returns immutable set of bindings of currently registered intent installers.
*
* @return the set of installer bindings
*/
Map<Class<? extends InstallableIntent>, IntentInstaller<? extends InstallableIntent>> getInstallers();
Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers();
}
......
......@@ -7,43 +7,37 @@ package org.onlab.onos.net.intent;
*/
public final class IntentId implements BatchOperationTarget {
private static final int DEC = 10;
private static final int HEX = 16;
private final long id;
private final long fingerprint;
/**
* Creates an intent identifier from the specified string representation.
*
* @param value long value
* @param fingerprint long value
* @return intent identifier
*/
public static IntentId valueOf(String value) {
long id = value.toLowerCase().startsWith("0x")
? Long.parseLong(value.substring(2), HEX)
: Long.parseLong(value, DEC);
return new IntentId(id);
public static IntentId valueOf(long fingerprint) {
return new IntentId(fingerprint);
}
/**
* Constructor for serializer.
*/
protected IntentId() {
this.id = 0;
IntentId() {
this.fingerprint = 0;
}
/**
* Constructs the ID corresponding to a given long value.
*
* @param id the underlying value of this ID
* @param fingerprint the underlying value of this ID
*/
public IntentId(long id) {
this.id = id;
IntentId(long fingerprint) {
this.fingerprint = fingerprint;
}
@Override
public int hashCode() {
return (int) (id ^ (id >>> 32));
return (int) (fingerprint ^ (fingerprint >>> 32));
}
@Override
......@@ -51,18 +45,16 @@ public final class IntentId implements BatchOperationTarget {
if (obj == this) {
return true;
}
if (!(obj instanceof IntentId)) {
return false;
}
IntentId that = (IntentId) obj;
return this.id == that.id;
return this.fingerprint == that.fingerprint;
}
@Override
public String toString() {
return "0x" + Long.toHexString(id);
return "0x" + Long.toHexString(fingerprint);
}
}
......
......@@ -7,7 +7,7 @@ import org.onlab.onos.net.flow.FlowRuleBatchOperation;
/**
* Abstraction of entity capable of installing intents to the environment.
*/
public interface IntentInstaller<T extends InstallableIntent> {
public interface IntentInstaller<T extends Intent> {
/**
* Installs the specified intent to the environment.
*
......
......@@ -77,8 +77,7 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> {
* @param intentId original intent identifier
* @param installableIntents compiled installable intents
*/
void addInstallableIntents(IntentId intentId,
List<InstallableIntent> installableIntents);
void addInstallableIntents(IntentId intentId, List<Intent> installableIntents);
/**
* Returns the list of the installable events associated with the specified
......@@ -87,7 +86,7 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> {
* @param intentId original intent identifier
* @return compiled installable intents
*/
List<InstallableIntent> getInstallableIntents(IntentId intentId);
List<Intent> getInstallableIntents(IntentId intentId);
// TODO: this should be triggered from with the store as a result of removeIntent call
......
package org.onlab.onos.net.intent;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import com.google.common.base.MoreObjects;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import com.google.common.base.MoreObjects;
import java.util.Set;
/**
* Abstraction of a connectivity intent that is implemented by a set of path
* segments.
*/
public final class LinkCollectionIntent extends ConnectivityIntent implements InstallableIntent {
public final class LinkCollectionIntent extends ConnectivityIntent {
private final Set<Link> links;
......@@ -25,34 +23,33 @@ public final class LinkCollectionIntent extends ConnectivityIntent implements In
* Creates a new point-to-point intent with the supplied ingress/egress
* ports and using the specified explicit path.
*
* @param id intent identifier
* @param appId application identifier
* @param selector traffic match
* @param treatment action
* @param links traversed links
* @param egressPoint egress point
* @throws NullPointerException {@code path} is null
*/
public LinkCollectionIntent(IntentId id,
public LinkCollectionIntent(ApplicationId appId,
TrafficSelector selector,
TrafficTreatment treatment,
Set<Link> links,
ConnectPoint egressPoint) {
super(id, selector, treatment);
super(id(LinkCollectionIntent.class, selector, treatment, links, egressPoint),
appId, resources(links), selector, treatment);
this.links = links;
this.egressPoint = egressPoint;
}
/**
* Constructor for serializer.
*/
protected LinkCollectionIntent() {
super();
this.links = null;
this.egressPoint = null;
}
@Override
public Collection<Link> requiredLinks() {
return links;
}
/**
* Returns the set of links that represent the network connections needed
* by this intent.
......@@ -73,34 +70,17 @@ public final class LinkCollectionIntent extends ConnectivityIntent implements In
}
@Override
public boolean equals(Object o) {
if (this == o) {
public boolean isInstallable() {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
LinkCollectionIntent that = (LinkCollectionIntent) o;
return Objects.equals(this.links, that.links) &&
Objects.equals(this.egressPoint, that.egressPoint);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), links, egressPoint);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("id", id())
.add("match", selector())
.add("action", treatment())
.add("appId", appId())
.add("selector", selector())
.add("treatment", treatment())
.add("links", links())
.add("egress", egressPoint())
.toString();
......
......@@ -2,11 +2,11 @@ package org.onlab.onos.net.intent;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Sets;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import java.util.Objects;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
......@@ -22,11 +22,11 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent {
/**
* Creates a new multi-to-single point connectivity intent for the specified
* traffic match and action.
* traffic selector and treatment.
*
* @param id intent identifier
* @param match traffic match
* @param action action
* @param appId application identifier
* @param selector traffic selector
* @param treatment treatment
* @param ingressPoints set of ports from which ingress traffic originates
* @param egressPoint port to which traffic will egress
* @throws NullPointerException if {@code ingressPoints} or
......@@ -34,15 +34,16 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent {
* @throws IllegalArgumentException if the size of {@code ingressPoints} is
* not more than 1
*/
public MultiPointToSinglePointIntent(IntentId id, TrafficSelector match,
TrafficTreatment action,
public MultiPointToSinglePointIntent(ApplicationId appId,
TrafficSelector selector,
TrafficTreatment treatment,
Set<ConnectPoint> ingressPoints,
ConnectPoint egressPoint) {
super(id, match, action);
super(id(MultiPointToSinglePointIntent.class, selector, treatment,
ingressPoints, egressPoint), appId, null, selector, treatment);
checkNotNull(ingressPoints);
checkArgument(!ingressPoints.isEmpty(),
"there should be at least one ingress port");
checkArgument(!ingressPoints.isEmpty(), "Ingress point set cannot be empty");
this.ingressPoints = Sets.newHashSet(ingressPoints);
this.egressPoint = checkNotNull(egressPoint);
......@@ -77,35 +78,14 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent {
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
MultiPointToSinglePointIntent that = (MultiPointToSinglePointIntent) o;
return Objects.equals(this.ingressPoints, that.ingressPoints)
&& Objects.equals(this.egressPoint, that.egressPoint);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), ingressPoints, egressPoint);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("id", id())
.add("match", selector())
.add("action", treatment())
.add("ingressPoints", ingressPoints())
.add("egressPoint", egressPoint())
.add("appId", appId())
.add("selector", selector())
.add("treatment", treatment())
.add("ingress", ingressPoints())
.add("egress", egressPoint())
.toString();
}
}
......
package org.onlab.onos.net.intent;
import org.onlab.onos.net.ConnectPoint;
// TODO: consider if this intent should be sub-class of ConnectivityIntent
/**
* An optical layer Intent for a connectivity from a transponder port to another
* transponder port.
* <p/>
* This class doesn't accepts lambda specifier. This class computes path between
* ports and assign lambda automatically. The lambda can be specified using
* OpticalPathFlow class.
*/
public class OpticalConnectivityIntent extends AbstractIntent {
protected ConnectPoint src;
protected ConnectPoint dst;
/**
* Constructor.
*
* @param id ID for this new Intent object.
* @param src The source transponder port.
* @param dst The destination transponder port.
*/
public OpticalConnectivityIntent(IntentId id, ConnectPoint src, ConnectPoint dst) {
super(id);
this.src = src;
this.dst = dst;
}
/**
* Constructor for serializer.
*/
protected OpticalConnectivityIntent() {
super();
this.src = null;
this.dst = null;
}
/**
* Gets source transponder port.
*
* @return The source transponder port.
*/
public ConnectPoint getSrcConnectPoint() {
return src;
}
/**
* Gets destination transponder port.
*
* @return The source transponder port.
*/
public ConnectPoint getDst() {
return dst;
}
}
package org.onlab.onos.net.intent;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.TrafficSelector;
// TODO: consider if this intent should be sub-class of Connectivity intent
/**
* A packet layer Intent for a connectivity from a set of ports to a set of
* ports.
* <p>
* TODO: Design methods to support the ReactiveForwarding and the SDN-IP. <br>
* NOTE: Should this class support modifier methods? Should this object a
* read-only object?
*/
public class PacketConnectivityIntent extends AbstractIntent {
protected Set<ConnectPoint> srcConnectPoints;
protected TrafficSelector selector;
protected Set<ConnectPoint> dstConnectPoints;
protected boolean canSetupOpticalFlow;
protected int idleTimeoutValue;
protected int hardTimeoutValue;
/**
* Creates a connectivity intent for the packet layer.
* <p>
* When the "canSetupOpticalFlow" option is true, this intent will compute
* the packet/optical converged path, decompose it to the OpticalPathFlow
* and the PacketPathFlow objects, and execute the operations to add them
* considering the dependency between the packet and optical layers.
*
* @param id ID for this new Intent object.
* @param srcConnectPoints The set of source switch ports.
* @param match Traffic specifier for this object.
* @param dstConnectPoints The set of destination switch ports.
* @param canSetupOpticalFlow The flag whether this intent can create
* optical flows if needed.
*/
public PacketConnectivityIntent(IntentId id,
Collection<ConnectPoint> srcConnectPoints, TrafficSelector match,
Collection<ConnectPoint> dstConnectPoints, boolean canSetupOpticalFlow) {
super(id);
this.srcConnectPoints = new HashSet<ConnectPoint>(srcConnectPoints);
this.selector = match;
this.dstConnectPoints = new HashSet<ConnectPoint>(dstConnectPoints);
this.canSetupOpticalFlow = canSetupOpticalFlow;
this.idleTimeoutValue = 0;
this.hardTimeoutValue = 0;
// TODO: check consistency between these parameters.
}
/**
* Constructor for serializer.
*/
protected PacketConnectivityIntent() {
super();
this.srcConnectPoints = null;
this.selector = null;
this.dstConnectPoints = null;
this.canSetupOpticalFlow = false;
this.idleTimeoutValue = 0;
this.hardTimeoutValue = 0;
}
/**
* Gets the set of source switch ports.
*
* @return the set of source switch ports.
*/
public Collection<ConnectPoint> getSrcConnectPoints() {
return Collections.unmodifiableCollection(srcConnectPoints);
}
/**
* Gets the traffic specifier.
*
* @return The traffic specifier.
*/
public TrafficSelector getMatch() {
return selector;
}
/**
* Gets the set of destination switch ports.
*
* @return the set of destination switch ports.
*/
public Collection<ConnectPoint> getDstConnectPoints() {
return Collections.unmodifiableCollection(dstConnectPoints);
}
/**
* Adds the specified port to the set of source ports.
*
* @param port ConnectPoint object to be added
*/
public void addSrcConnectPoint(ConnectPoint port) {
// TODO implement it.
}
/**
* Adds the specified port to the set of destination ports.
*
* @param port ConnectPoint object to be added
*/
public void addDstConnectPoint(ConnectPoint port) {
// TODO implement it.
}
/**
* Removes the specified port from the set of source ports.
*
* @param port ConnectPoint object to be removed
*/
public void removeSrcConnectPoint(ConnectPoint port) {
// TODO implement it.
}
/**
* Removes the specified port from the set of destination ports.
*
* @param port ConnectPoint object to be removed
*/
public void removeDstConnectPoint(ConnectPoint port) {
// TODO implement it.
}
/**
* Sets idle-timeout value.
*
* @param timeout Idle-timeout value (seconds)
*/
public void setIdleTimeout(int timeout) {
idleTimeoutValue = timeout;
}
/**
* Sets hard-timeout value.
*
* @param timeout Hard-timeout value (seconds)
*/
public void setHardTimeout(int timeout) {
hardTimeoutValue = timeout;
}
/**
* Gets idle-timeout value.
*
* @return Idle-timeout value (seconds)
*/
public int getIdleTimeout() {
return idleTimeoutValue;
}
/**
* Gets hard-timeout value.
*
* @return Hard-timeout value (seconds)
*/
public int getHardTimeout() {
return hardTimeoutValue;
}
/**
* Returns whether this intent can create optical flows if needed.
*
* @return whether this intent can create optical flows.
*/
public boolean canSetupOpticalFlow() {
return canSetupOpticalFlow;
}
}
package org.onlab.onos.net.intent;
import com.google.common.base.MoreObjects;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Link;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import java.util.Collection;
import java.util.Objects;
/**
* Abstraction of explicitly path specified connectivity intent.
*/
public class PathIntent extends PointToPointIntent implements InstallableIntent {
public class PathIntent extends ConnectivityIntent {
private final Path path;
......@@ -21,21 +17,22 @@ public class PathIntent extends PointToPointIntent implements InstallableIntent
* Creates a new point-to-point intent with the supplied ingress/egress
* ports and using the specified explicit path.
*
* @param id intent identifier
* @param match traffic match
* @param action action
* @param ingressPort ingress port
* @param egressPort egress port
* @param appId application identifier
* @param selector traffic selector
* @param treatment treatment
* @param path traversed links
* @throws NullPointerException {@code path} is null
*/
public PathIntent(IntentId id, TrafficSelector match, TrafficTreatment action,
ConnectPoint ingressPort, ConnectPoint egressPort,
Path path) {
super(id, match, action, ingressPort, egressPort);
public PathIntent(ApplicationId appId, TrafficSelector selector,
TrafficTreatment treatment, Path path) {
super(id(PathIntent.class, selector, treatment, path), appId,
resources(path.links()), selector, treatment);
this.path = path;
}
/**
* Constructor for serializer.
*/
protected PathIntent() {
super();
this.path = null;
......@@ -51,46 +48,19 @@ public class PathIntent extends PointToPointIntent implements InstallableIntent
}
@Override
public boolean equals(Object o) {
if (this == o) {
public boolean isInstallable() {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
PathIntent that = (PathIntent) o;
if (!path.equals(that.path)) {
return false;
}
return true;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), path);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("id", id())
.add("match", selector())
.add("action", treatment())
.add("ingressPort", ingressPoint())
.add("egressPort", egressPoint())
.add("appId", appId())
.add("selector", selector())
.add("treatment", treatment())
.add("path", path)
.toString();
}
@Override
public Collection<Link> requiredLinks() {
return path.links();
}
}
......
package org.onlab.onos.net.intent;
import com.google.common.base.MoreObjects;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
......@@ -21,18 +20,19 @@ public class PointToPointIntent extends ConnectivityIntent {
* Creates a new point-to-point intent with the supplied ingress/egress
* ports.
*
* @param id intent identifier
* @param appId application identifier
* @param selector traffic selector
* @param treatment treatment
* @param ingressPoint ingress port
* @param egressPoint egress port
* @throws NullPointerException if {@code ingressPoint} or {@code egressPoints} is null.
*/
public PointToPointIntent(IntentId id, TrafficSelector selector,
public PointToPointIntent(ApplicationId appId, TrafficSelector selector,
TrafficTreatment treatment,
ConnectPoint ingressPoint,
ConnectPoint egressPoint) {
super(id, selector, treatment);
super(id(PointToPointIntent.class, selector, treatment, ingressPoint, egressPoint),
appId, null, selector, treatment);
this.ingressPoint = checkNotNull(ingressPoint);
this.egressPoint = checkNotNull(egressPoint);
}
......@@ -66,35 +66,14 @@ public class PointToPointIntent extends ConnectivityIntent {
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
PointToPointIntent that = (PointToPointIntent) o;
return Objects.equals(this.ingressPoint, that.ingressPoint)
&& Objects.equals(this.egressPoint, that.egressPoint);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), ingressPoint, egressPoint);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("id", id())
.add("match", selector())
.add("action", treatment())
.add("ingressPoint", ingressPoint)
.add("egressPoints", egressPoint)
.add("appId", appId())
.add("selector", selector())
.add("treatment", treatment())
.add("ingress", ingressPoint)
.add("egress", egressPoint)
.toString();
}
......
......@@ -2,11 +2,11 @@ package org.onlab.onos.net.intent;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Sets;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import java.util.Objects;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
......@@ -23,7 +23,7 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent {
/**
* Creates a new single-to-multi point connectivity intent.
*
* @param id intent identifier
* @param appId application identifier
* @param selector traffic selector
* @param treatment treatment
* @param ingressPoint port on which traffic will ingress
......@@ -33,16 +33,15 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent {
* @throws IllegalArgumentException if the size of {@code egressPoints} is
* not more than 1
*/
public SinglePointToMultiPointIntent(IntentId id, TrafficSelector selector,
public SinglePointToMultiPointIntent(ApplicationId appId,
TrafficSelector selector,
TrafficTreatment treatment,
ConnectPoint ingressPoint,
Set<ConnectPoint> egressPoints) {
super(id, selector, treatment);
super(id(SinglePointToMultiPointIntent.class, selector, treatment,
ingressPoint, egressPoints), appId, null, selector, treatment);
checkNotNull(egressPoints);
checkArgument(!egressPoints.isEmpty(),
"there should be at least one egress port");
checkArgument(!egressPoints.isEmpty(), "Egress point set cannot be empty");
this.ingressPoint = checkNotNull(ingressPoint);
this.egressPoints = Sets.newHashSet(egressPoints);
}
......@@ -75,35 +74,14 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent {
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
SinglePointToMultiPointIntent that = (SinglePointToMultiPointIntent) o;
return Objects.equals(this.ingressPoint, that.ingressPoint)
&& Objects.equals(this.egressPoints, that.egressPoints);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), ingressPoint, egressPoints);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("id", id())
.add("match", selector())
.add("action", treatment())
.add("ingressPoint", ingressPoint)
.add("egressPort", egressPoints)
.add("appId", appId())
.add("selector", selector())
.add("treatment", treatment())
.add("ingress", ingressPoint)
.add("egress", egressPoints)
.toString();
}
......
package org.onlab.onos.net.resource;
/**
* Representation of allocated bandwidth resource.
*/
public interface BandwidthResourceAllocation extends BandwidthResourceRequest {
}
package org.onlab.onos.net.resource;
/**
* Representation of a request for bandwidth resource.
*/
public interface BandwidthResourceRequest {
/**
* Returns the bandwidth resource.
*
* @return the bandwidth resource
*/
Bandwidth bandwidth();
}
......@@ -30,6 +30,7 @@ public final class Lambda extends LinkResource {
/**
* Returns lambda as an int value.
*
* @return lambda as an int value
*/
public int toInt() {
......
package org.onlab.onos.net.resource;
/**
* Representation of allocated lambda resource.
*/
public interface LambdaResourceAllocation extends LambdaResourceRequest {
/**
* Returns the lambda resource.
*
* @return the lambda resource
*/
Lambda lambda();
}
package org.onlab.onos.net.resource;
/**
* Representation of a request for lambda resource.
*/
public interface LambdaResourceRequest {
}
package org.onlab.onos.net.resource;
import org.onlab.onos.net.Link;
/**
* Representation of allocated link resources.
*/
public interface LinkResourceAllocations extends LinkResourceRequest {
/**
* Returns allocated resource for the given link.
*
* @param link the target link
* @return allocated resource for the link
*/
ResourceAllocation getResourceAllocation(Link link);
}
package org.onlab.onos.net.resource;
import java.util.Collection;
import java.util.Set;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.intent.IntentId;
/**
* Representation of a request for link resource.
*/
public interface LinkResourceRequest extends ResourceRequest {
/**
* Returns the {@link IntentId} associated with the request.
*
* @return the {@link IntentId} associated with the request
*/
IntentId intendId();
/**
* Returns the set of target links.
*
* @return the set of target links
*/
Collection<Link> links();
/**
* Returns the set of resource requests.
*
* @return the set of resource requests
*/
Set<ResourceRequest> resources();
}
package org.onlab.onos.net.resource;
import java.util.Map;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.PathIntent;
/**
* Service for providing link resource allocation.
......@@ -12,49 +9,48 @@ import org.onlab.onos.net.intent.PathIntent;
public interface LinkResourceService {
/**
* Allocates resources along the path.
* <p>
* Tries to allocate given resources on the links along the path specified
* by the given intent.
* Requests resources.
*
* @param res resources to be allocated
* @param intent an intent to be used for specifying the path
* @param req resources to be allocated
* @return allocated resources
*/
void allocateResource(LinkResources res, PathIntent intent);
LinkResourceAllocations requestResources(LinkResourceRequest req);
/**
* Releases resources along the path.
* Releases resources.
*
* @param intentId an ID for the intent for specifying the path
* @param allocations resources to be released
*/
void releaseResource(IntentId intentId);
void releaseResources(LinkResourceAllocations allocations);
/**
* Returns all allocated resources to each link.
* Returns all allocated resources.
*
* @return allocated resources to each link with {@link IntentId}
* @return allocated resources
*/
Map<Link, Map<IntentId, LinkResources>> allocatedResources();
Iterable<LinkResourceAllocations> getAllocations();
/**
* Returns all allocated resources to given link.
*
* @param link a target link
* @return allocated resources to the target link with {@link IntentId}
* @return allocated resources
*/
Map<IntentId, LinkResources> allocatedResources(Link link);
Iterable<LinkResourceAllocations> getAllocations(Link link);
/**
* Returns available resources for each link.
* Returns all IDs of intents using the given link.
*
* @return available resources for each link
* @param link a target link
* @return IDs of intents using the link
*/
Map<Link, LinkResources> availableResources();
Iterable<IntentId> getIntents(Link link);
/**
* Returns available resources for given link.
*
* @param link a target link
* @return available resources for the target link
*/
LinkResources availableResources(Link link);
ResourceRequest getAvailableResources(Link link);
}
......
package org.onlab.onos.net.resource;
/**
* Abstraction of allocated resource.
*/
public interface ResourceAllocation extends ResourceRequest {
}
package org.onlab.onos.net.resource;
/**
* Representation of ID for allocated resource.
*/
public interface ResourceId {
}
package org.onlab.onos.net.resource;
/**
* Abstraction of resource request.
*/
public interface ResourceRequest {
}
/**
* Services for reserving network resources, e.g.&nbsp;bandwidth, lambdas.
*/
package org.onlab.onos.net.resource;
\ No newline at end of file
......@@ -2,6 +2,8 @@ package org.onlab.onos.net.intent;
import java.util.Set;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.TestApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber;
......@@ -15,6 +17,8 @@ import org.onlab.onos.net.flow.TrafficTreatment;
*/
public abstract class ConnectivityIntentTest extends IntentTest {
public static final ApplicationId APPID = new TestApplicationId("foo");
public static final IntentId IID = new IntentId(123);
public static final TrafficSelector MATCH = DefaultTrafficSelector.builder().build();
public static final TrafficTreatment NOP = DefaultTrafficTreatment.builder().build();
......
......@@ -18,11 +18,11 @@ public class FakeIntentManager implements TestableIntentService {
private final Map<IntentId, Intent> intents = new HashMap<>();
private final Map<IntentId, IntentState> intentStates = new HashMap<>();
private final Map<IntentId, List<InstallableIntent>> installables = new HashMap<>();
private final Map<IntentId, List<Intent>> installables = new HashMap<>();
private final Set<IntentListener> listeners = new HashSet<>();
private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>();
private final Map<Class<? extends InstallableIntent>, IntentInstaller<? extends InstallableIntent>> installers
private final Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> installers
= new HashMap<>();
private final ExecutorService executor = Executors.newSingleThreadExecutor();
......@@ -54,7 +54,7 @@ public class FakeIntentManager implements TestableIntentService {
@Override
public void run() {
try {
List<InstallableIntent> installable = getInstallable(intent.id());
List<Intent> installable = getInstallable(intent.id());
executeWithdrawingPhase(intent, installable);
} catch (IntentException e) {
exceptions.add(e);
......@@ -73,7 +73,7 @@ public class FakeIntentManager implements TestableIntentService {
return compiler;
}
private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) {
private <T extends Intent> IntentInstaller<T> getInstaller(T intent) {
@SuppressWarnings("unchecked")
IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent
.getClass());
......@@ -87,9 +87,9 @@ public class FakeIntentManager implements TestableIntentService {
setState(intent, IntentState.COMPILING);
try {
// For the fake, we compile using a single level pass
List<InstallableIntent> installable = new ArrayList<>();
List<Intent> installable = new ArrayList<>();
for (Intent compiled : getCompiler(intent).compile(intent)) {
installable.add((InstallableIntent) compiled);
installable.add((Intent) compiled);
}
executeInstallingPhase(intent, installable);
......@@ -100,10 +100,10 @@ public class FakeIntentManager implements TestableIntentService {
}
private void executeInstallingPhase(Intent intent,
List<InstallableIntent> installable) {
List<Intent> installable) {
setState(intent, IntentState.INSTALLING);
try {
for (InstallableIntent ii : installable) {
for (Intent ii : installable) {
registerSubclassInstallerIfNeeded(ii);
getInstaller(ii).install(ii);
}
......@@ -118,10 +118,10 @@ public class FakeIntentManager implements TestableIntentService {
}
private void executeWithdrawingPhase(Intent intent,
List<InstallableIntent> installable) {
List<Intent> installable) {
setState(intent, IntentState.WITHDRAWING);
try {
for (InstallableIntent ii : installable) {
for (Intent ii : installable) {
getInstaller(ii).uninstall(ii);
}
removeInstallable(intent.id());
......@@ -139,7 +139,7 @@ public class FakeIntentManager implements TestableIntentService {
intentStates.put(intent.id(), state);
}
private void putInstallable(IntentId id, List<InstallableIntent> installable) {
private void putInstallable(IntentId id, List<Intent> installable) {
installables.put(id, installable);
}
......@@ -147,8 +147,8 @@ public class FakeIntentManager implements TestableIntentService {
installables.remove(id);
}
private List<InstallableIntent> getInstallable(IntentId id) {
List<InstallableIntent> installable = installables.get(id);
private List<Intent> getInstallable(IntentId id) {
List<Intent> installable = installables.get(id);
if (installable != null) {
return installable;
} else {
......@@ -228,19 +228,19 @@ public class FakeIntentManager implements TestableIntentService {
}
@Override
public <T extends InstallableIntent> void registerInstaller(Class<T> cls,
public <T extends Intent> void registerInstaller(Class<T> cls,
IntentInstaller<T> installer) {
installers.put(cls, installer);
}
@Override
public <T extends InstallableIntent> void unregisterInstaller(Class<T> cls) {
public <T extends Intent> void unregisterInstaller(Class<T> cls) {
installers.remove(cls);
}
@Override
public Map<Class<? extends InstallableIntent>,
IntentInstaller<? extends InstallableIntent>> getInstallers() {
public Map<Class<? extends Intent>,
IntentInstaller<? extends Intent>> getInstallers() {
return Collections.unmodifiableMap(installers);
}
......@@ -261,13 +261,13 @@ public class FakeIntentManager implements TestableIntentService {
}
}
private void registerSubclassInstallerIfNeeded(InstallableIntent intent) {
private void registerSubclassInstallerIfNeeded(Intent intent) {
if (!installers.containsKey(intent.getClass())) {
Class<?> cls = intent.getClass();
while (cls != Object.class) {
// As long as we're within the InstallableIntent class
// As long as we're within the Intent class
// descendants
if (InstallableIntent.class.isAssignableFrom(cls)) {
if (Intent.class.isAssignableFrom(cls)) {
IntentInstaller<?> installer = installers.get(cls);
if (installer != null) {
installers.put(intent.getClass(), installer);
......
package org.onlab.onos.net.intent;
/**
* This interface is for generator of IntentId. It is defined only for
* testing purpose to keep type safety on mock creation.
*
* <p>
* {@link #getNewId()} generates a globally unique {@link IntentId} instance
* on each invocation. Application developers should not generate IntentId
* by themselves. Instead use an implementation of this interface.
* </p>
*/
public interface IntentIdGenerator extends IdGenerator<IntentId> {
}
......@@ -44,14 +44,8 @@ public class IntentIdTest {
@Test
public void valueOf() {
IntentId id = new IntentId(12345);
assertEquals("incorrect valueOf", id, IntentId.valueOf("12345"));
}
@Test
public void valueOfHex() {
IntentId id = new IntentId(0xdeadbeefL);
assertEquals("incorrect valueOf", id, IntentId.valueOf(id.toString()));
assertEquals("incorrect valueOf", id, IntentId.valueOf(0xdeadbeefL));
}
}
......
package org.onlab.onos.net.intent;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Base facilities to test various intent tests.
......@@ -33,11 +31,7 @@ public abstract class IntentTest {
assertTrue("should be equal", one.equals(like));
assertEquals("incorrect hashCode", one.hashCode(), like.hashCode());
assertFalse("should not be equal", one.equals(another));
assertFalse("should not be equal", one.equals(null));
assertFalse("should not be equal", one.equals("foo"));
}
@Test
......
......@@ -12,7 +12,7 @@ public class MultiPointToSinglePointIntentTest extends ConnectivityIntentTest {
@Test
public void basics() {
MultiPointToSinglePointIntent intent = createOne();
assertEquals("incorrect id", IID, intent.id());
assertEquals("incorrect id", APPID, intent.appId());
assertEquals("incorrect match", MATCH, intent.selector());
assertEquals("incorrect ingress", PS1, intent.ingressPoints());
assertEquals("incorrect egress", P2, intent.egressPoint());
......@@ -20,11 +20,11 @@ public class MultiPointToSinglePointIntentTest extends ConnectivityIntentTest {
@Override
protected MultiPointToSinglePointIntent createOne() {
return new MultiPointToSinglePointIntent(IID, MATCH, NOP, PS1, P2);
return new MultiPointToSinglePointIntent(APPID, MATCH, NOP, PS1, P2);
}
@Override
protected MultiPointToSinglePointIntent createAnother() {
return new MultiPointToSinglePointIntent(IID, MATCH, NOP, PS2, P1);
return new MultiPointToSinglePointIntent(APPID, MATCH, NOP, PS2, P1);
}
}
......
......@@ -16,21 +16,19 @@ public class PathIntentTest extends ConnectivityIntentTest {
@Test
public void basics() {
PathIntent intent = createOne();
assertEquals("incorrect id", IID, intent.id());
assertEquals("incorrect id", APPID, intent.appId());
assertEquals("incorrect match", MATCH, intent.selector());
assertEquals("incorrect action", NOP, intent.treatment());
assertEquals("incorrect ingress", P1, intent.ingressPoint());
assertEquals("incorrect egress", P2, intent.egressPoint());
assertEquals("incorrect path", PATH1, intent.path());
}
@Override
protected PathIntent createOne() {
return new PathIntent(IID, MATCH, NOP, P1, P2, PATH1);
return new PathIntent(APPID, MATCH, NOP, PATH1);
}
@Override
protected PathIntent createAnother() {
return new PathIntent(IID, MATCH, NOP, P1, P3, PATH2);
return new PathIntent(APPID, MATCH, NOP, PATH2);
}
}
......
......@@ -12,7 +12,7 @@ public class PointToPointIntentTest extends ConnectivityIntentTest {
@Test
public void basics() {
PointToPointIntent intent = createOne();
assertEquals("incorrect id", IID, intent.id());
assertEquals("incorrect id", APPID, intent.appId());
assertEquals("incorrect match", MATCH, intent.selector());
assertEquals("incorrect ingress", P1, intent.ingressPoint());
assertEquals("incorrect egress", P2, intent.egressPoint());
......@@ -20,11 +20,11 @@ public class PointToPointIntentTest extends ConnectivityIntentTest {
@Override
protected PointToPointIntent createOne() {
return new PointToPointIntent(IID, MATCH, NOP, P1, P2);
return new PointToPointIntent(APPID, MATCH, NOP, P1, P2);
}
@Override
protected PointToPointIntent createAnother() {
return new PointToPointIntent(IID, MATCH, NOP, P2, P1);
return new PointToPointIntent(APPID, MATCH, NOP, P2, P1);
}
}
......
......@@ -12,7 +12,7 @@ public class SinglePointToMultiPointIntentTest extends ConnectivityIntentTest {
@Test
public void basics() {
SinglePointToMultiPointIntent intent = createOne();
assertEquals("incorrect id", IID, intent.id());
assertEquals("incorrect id", APPID, intent.appId());
assertEquals("incorrect match", MATCH, intent.selector());
assertEquals("incorrect ingress", P1, intent.ingressPoint());
assertEquals("incorrect egress", PS2, intent.egressPoints());
......@@ -20,11 +20,11 @@ public class SinglePointToMultiPointIntentTest extends ConnectivityIntentTest {
@Override
protected SinglePointToMultiPointIntent createOne() {
return new SinglePointToMultiPointIntent(IID, MATCH, NOP, P1, PS2);
return new SinglePointToMultiPointIntent(APPID, MATCH, NOP, P1, PS2);
}
@Override
protected SinglePointToMultiPointIntent createAnother() {
return new SinglePointToMultiPointIntent(IID, MATCH, NOP, P2, PS1);
return new SinglePointToMultiPointIntent(APPID, MATCH, NOP, P2, PS1);
}
}
......
package org.onlab.onos.net.intent;
//TODO is this the right package?
import org.onlab.onos.net.Link;
import java.util.Collection;
import org.onlab.onos.TestApplicationId;
/**
* An installable intent used in the unit test.
*
* FIXME: we don't want to expose this class publicly, but the current Kryo
* serialization mechanism does not allow this class to be private and placed
* on testing directory.
*/
public class TestInstallableIntent extends AbstractIntent implements InstallableIntent {
public class TestInstallableIntent extends Intent {
/**
* Constructs an instance with the specified intent ID.
*
* @param id intent ID
*/
public TestInstallableIntent(IntentId id) {
super(id);
super(id, new TestApplicationId("foo"), null);
}
/**
......@@ -30,7 +23,8 @@ public class TestInstallableIntent extends AbstractIntent implements Installable
}
@Override
public Collection<Link> requiredLinks() {
return null;
public boolean isInstallable() {
return true;
}
}
......
package org.onlab.onos.net.intent;
//TODO is this the right package?
import org.onlab.onos.TestApplicationId;
/**
* An intent used in the unit test.
*
* FIXME: we don't want to expose this class publicly, but the current Kryo
* serialization mechanism does not allow this class to be private and placed
* on testing directory.
*/
public class TestIntent extends AbstractIntent {
public class TestIntent extends Intent {
/**
* Constructs an instance with the specified intent ID.
*
* @param id intent ID
*/
public TestIntent(IntentId id) {
super(id);
super(id, new TestApplicationId("foo"), null);
}
/**
......
package org.onlab.onos.net.intent;
//TODO is this the right package?
/**
* An intent used in the unit test.
*
* FIXME: we don't want to expose this class publicly, but the current Kryo
* serialization mechanism does not allow this class to be private and placed
* on testing directory.
*/
public class TestSubclassInstallableIntent extends TestInstallableIntent implements InstallableIntent {
public class TestSubclassInstallableIntent extends TestInstallableIntent {
/**
* Constructs an instance with the specified intent ID.
*
......
package org.onlab.onos.net.intent;
//TODO is this the right package?
/**
* An intent used in the unit test.
*
* FIXME: we don't want to expose this class publicly, but the current Kryo
* serialization mechanism does not allow this class to be private and placed
* on testing directory.
*/
public class TestSubclassIntent extends TestIntent {
/**
......
......@@ -27,6 +27,7 @@ public class CoreManager implements CoreService {
private static Version version = Version.version("1.0.0-SNAPSHOT");
private final Map<Short, DefaultApplicationId> appIds = new ConcurrentHashMap<>();
private final Map<String, DefaultApplicationId> appIdsByName = new ConcurrentHashMap<>();
// TODO: work in progress
......@@ -50,9 +51,13 @@ public class CoreManager implements CoreService {
@Override
public ApplicationId registerApplication(String name) {
DefaultApplicationId appId = appIdsByName.get(name);
if (appId == null) {
short id = (short) ID_DISPENSER.getAndIncrement();
DefaultApplicationId appId = new DefaultApplicationId(id, name);
appId = new DefaultApplicationId(id, name);
appIds.put(id, appId);
appIdsByName.put(name, appId);
}
return appId;
}
......
......@@ -104,24 +104,52 @@ public class FlowRuleManager
public void applyFlowRules(FlowRule... flowRules) {
for (int i = 0; i < flowRules.length; i++) {
FlowRule f = flowRules[i];
final Device device = deviceService.getDevice(f.deviceId());
final FlowRuleProvider frp = getProvider(device.providerId());
store.storeFlowRule(f);
boolean local = store.storeFlowRule(f);
if (local) {
// TODO: aggregate all local rules and push down once?
applyFlowRulesToProviders(f);
}
}
}
private void applyFlowRulesToProviders(FlowRule... flowRules) {
DeviceId did = null;
FlowRuleProvider frp = null;
for (FlowRule f : flowRules) {
if (!f.deviceId().equals(did)) {
did = f.deviceId();
final Device device = deviceService.getDevice(did);
frp = getProvider(device.providerId());
}
if (frp != null) {
frp.applyFlowRule(f);
}
}
}
@Override
public void removeFlowRules(FlowRule... flowRules) {
FlowRule f;
FlowRuleProvider frp;
Device device;
for (int i = 0; i < flowRules.length; i++) {
f = flowRules[i];
device = deviceService.getDevice(f.deviceId());
store.deleteFlowRule(f);
if (device != null) {
boolean local = store.deleteFlowRule(f);
if (local) {
// TODO: aggregate all local rules and push down once?
removeFlowRulesFromProviders(f);
}
}
}
private void removeFlowRulesFromProviders(FlowRule... flowRules) {
DeviceId did = null;
FlowRuleProvider frp = null;
for (FlowRule f : flowRules) {
if (!f.deviceId().equals(did)) {
did = f.deviceId();
final Device device = deviceService.getDevice(did);
frp = getProvider(device.providerId());
}
if (frp != null) {
frp.removeFlowRule(f);
}
}
......@@ -135,8 +163,11 @@ public class FlowRuleManager
for (FlowRule f : rules) {
store.deleteFlowRule(f);
// FIXME: only accept request and push to provider on internal event
device = deviceService.getDevice(f.deviceId());
frp = getProvider(device.providerId());
// FIXME: flows removed from store and flows removed from might diverge
// get rid of #removeRulesById?
frp.removeRulesById(id, f);
}
}
......@@ -352,7 +383,23 @@ public class FlowRuleManager
private class InternalStoreDelegate implements FlowRuleStoreDelegate {
@Override
public void notify(FlowRuleEvent event) {
switch (event.type()) {
case RULE_ADD_REQUESTED:
applyFlowRulesToProviders(event.subject());
break;
case RULE_REMOVE_REQUESTED:
removeFlowRulesFromProviders(event.subject());
break;
case RULE_ADDED:
case RULE_REMOVED:
case RULE_UPDATED:
// only dispatch events related to switch
eventDispatcher.post(event);
break;
default:
break;
}
}
}
......
package org.onlab.onos.net.intent.impl;
import org.onlab.onos.net.intent.IdGenerator;
/**
* Base class of {@link IdGenerator} implementations which use {@link IdBlockAllocator} as
* backend.
*
* @param <T> the type of ID
*/
public abstract class AbstractBlockAllocatorBasedIdGenerator<T> implements IdGenerator<T> {
protected final IdBlockAllocator allocator;
protected IdBlock idBlock;
/**
* Constructs an ID generator which use {@link IdBlockAllocator} as backend.
*
* @param allocator
*/
protected AbstractBlockAllocatorBasedIdGenerator(IdBlockAllocator allocator) {
this.allocator = allocator;
this.idBlock = allocator.allocateUniqueIdBlock();
}
@Override
public synchronized T getNewId() {
try {
return convertFrom(idBlock.getNextId());
} catch (UnavailableIdException e) {
idBlock = allocator.allocateUniqueIdBlock();
return convertFrom(idBlock.getNextId());
}
}
/**
* Returns an ID instance of {@code T} type from the long value.
*
* @param value original long value
* @return ID instance
*/
protected abstract T convertFrom(long value);
}
package org.onlab.onos.net.intent.impl;
public class DummyIdBlockAllocator implements IdBlockAllocator {
private long blockTop;
private static final long BLOCK_SIZE = 0x1000000L;
/**
* Returns a block of IDs which are unique and unused.
* Range of IDs is fixed size and is assigned incrementally as this method
* called.
*
* @return an IdBlock containing a set of unique IDs
*/
@Override
public IdBlock allocateUniqueIdBlock() {
synchronized (this) {
long blockHead = blockTop;
long blockTail = blockTop + BLOCK_SIZE;
IdBlock block = new IdBlock(blockHead, BLOCK_SIZE);
blockTop = blockTail;
return block;
}
}
@Override
public IdBlock allocateUniqueIdBlock(long range) {
throw new UnsupportedOperationException("Not supported yet");
}
}
......@@ -11,11 +11,9 @@ import org.onlab.onos.net.Path;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.HostToHostIntent;
import org.onlab.onos.net.intent.IdGenerator;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentCompiler;
import org.onlab.onos.net.intent.IntentExtensionService;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.onos.net.topology.PathService;
......@@ -41,12 +39,8 @@ public class HostToHostIntentCompiler
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
intentManager.registerCompiler(HostToHostIntent.class, this);
}
......@@ -70,13 +64,10 @@ public class HostToHostIntentCompiler
// Creates a path intent from the specified path and original connectivity intent.
private Intent createPathIntent(Path path, Host src, Host dst,
HostToHostIntent intent) {
TrafficSelector selector = builder(intent.selector())
.matchEthSrc(src.mac()).matchEthDst(dst.mac()).build();
return new PathIntent(intentIdGenerator.getNewId(),
selector, intent.treatment(),
path.src(), path.dst(), path);
return new PathIntent(intent.appId(), selector, intent.treatment(),
path);
}
private Path getPath(HostId one, HostId two) {
......
package org.onlab.onos.net.intent.impl;
import static com.google.common.base.Preconditions.checkArgument;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import com.google.common.base.MoreObjects;
/**
* A class representing an ID space.
*/
public final class IdBlock {
private final long start;
private final long size;
private final AtomicLong currentId;
/**
* Constructs a new ID block with the specified size and initial value.
*
* @param start initial value of the block
* @param size size of the block
* @throws IllegalArgumentException if the size is less than or equal to 0
*/
public IdBlock(long start, long size) {
checkArgument(size > 0, "size should be more than 0, but %s", size);
this.start = start;
this.size = size;
this.currentId = new AtomicLong(start);
}
// TODO: consider if this method is needed or not
/**
* Returns the initial value.
*
* @return initial value
*/
public long getStart() {
return start;
}
// TODO: consider if this method is needed or not
/**
* Returns the last value.
*
* @return last value
*/
public long getEnd() {
return start + size - 1;
}
/**
* Returns the block size.
*
* @return block size
*/
public long getSize() {
return size;
}
/**
* Returns the next ID in the block.
*
* @return next ID
* @throws UnavailableIdException if there is no available ID in the block.
*/
public long getNextId() {
final long id = currentId.getAndIncrement();
if (id > getEnd()) {
throw new UnavailableIdException(String.format(
"used all IDs in allocated space (size: %d, end: %d, current: %d)",
size, getEnd(), id
));
}
return id;
}
// TODO: Do we really need equals and hashCode? Should it contain currentId?
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
IdBlock that = (IdBlock) o;
return Objects.equals(this.start, that.start)
&& Objects.equals(this.size, that.size)
&& Objects.equals(this.currentId.get(), that.currentId.get());
}
@Override
public int hashCode() {
return Objects.hash(start, size, currentId);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("start", start)
.add("size", size)
.add("currentId", currentId)
.toString();
}
}
package org.onlab.onos.net.intent.impl;
/**
* An interface that gives unique ID spaces.
*/
public interface IdBlockAllocator {
/**
* Allocates a unique Id Block.
*
* @return Id Block.
*/
IdBlock allocateUniqueIdBlock();
/**
* Allocates next unique id and retrieve a new range of ids if needed.
*
* @param range range to use for the identifier
* @return Id Block.
*/
IdBlock allocateUniqueIdBlock(long range);
}
package org.onlab.onos.net.intent.impl;
import org.onlab.onos.net.intent.IntentId;
/**
* An implementation of {@link org.onlab.onos.net.intent.IdGenerator} of intent ID,
* which uses {@link IdBlockAllocator}.
*/
public class IdBlockAllocatorBasedIntentIdGenerator extends AbstractBlockAllocatorBasedIdGenerator<IntentId> {
/**
* Constructs an intent ID generator, which uses the specified ID block allocator
* to generate a global unique intent ID.
*
* @param allocator the ID block allocator to use for generating intent IDs
*/
public IdBlockAllocatorBasedIntentIdGenerator(IdBlockAllocator allocator) {
super(allocator);
}
@Override
protected IntentId convertFrom(long value) {
return new IntentId(value);
}
}
package org.onlab.onos.net.intent.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.onos.net.intent.IntentState.COMPILING;
import static org.onlab.onos.net.intent.IntentState.FAILED;
import static org.onlab.onos.net.intent.IntentState.INSTALLED;
import static org.onlab.onos.net.intent.IntentState.INSTALLING;
import static org.onlab.onos.net.intent.IntentState.RECOMPILING;
import static org.onlab.onos.net.intent.IntentState.WITHDRAWING;
import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
import static org.onlab.util.Tools.namedThreads;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -36,7 +14,6 @@ import org.onlab.onos.event.EventDeliveryService;
import org.onlab.onos.net.flow.CompletedBatchOperation;
import org.onlab.onos.net.flow.FlowRuleBatchOperation;
import org.onlab.onos.net.flow.FlowRuleService;
import org.onlab.onos.net.intent.InstallableIntent;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentCompiler;
import org.onlab.onos.net.intent.IntentEvent;
......@@ -52,9 +29,24 @@ import org.onlab.onos.net.intent.IntentStore;
import org.onlab.onos.net.intent.IntentStoreDelegate;
import org.slf4j.Logger;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.onos.net.intent.IntentState.*;
import static org.onlab.util.Tools.namedThreads;
import static org.slf4j.LoggerFactory.getLogger;
/**
* An implementation of Intent Manager.
......@@ -71,8 +63,8 @@ public class IntentManager
// Collections for compiler, installer, and listener are ONOS instance local
private final ConcurrentMap<Class<? extends Intent>,
IntentCompiler<? extends Intent>> compilers = new ConcurrentHashMap<>();
private final ConcurrentMap<Class<? extends InstallableIntent>,
IntentInstaller<? extends InstallableIntent>> installers = new ConcurrentHashMap<>();
private final ConcurrentMap<Class<? extends Intent>,
IntentInstaller<? extends Intent>> installers = new ConcurrentHashMap<>();
private final AbstractListenerRegistry<IntentEvent, IntentListener>
listenerRegistry = new AbstractListenerRegistry<>();
......@@ -186,17 +178,17 @@ public class IntentManager
}
@Override
public <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
public <T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
installers.put(cls, installer);
}
@Override
public <T extends InstallableIntent> void unregisterInstaller(Class<T> cls) {
public <T extends Intent> void unregisterInstaller(Class<T> cls) {
installers.remove(cls);
}
@Override
public Map<Class<? extends InstallableIntent>, IntentInstaller<? extends InstallableIntent>> getInstallers() {
public Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers() {
return ImmutableMap.copyOf(installers);
}
......@@ -223,7 +215,7 @@ public class IntentManager
* @param <T> the type of installable intent
* @return intent installer corresponding to the specified installable intent
*/
private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) {
private <T extends Intent> IntentInstaller<T> getInstaller(T intent) {
@SuppressWarnings("unchecked")
IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass());
if (installer == null) {
......@@ -243,7 +235,7 @@ public class IntentManager
try {
// Compile the intent into installable derivatives.
List<InstallableIntent> installable = compileIntent(intent);
List<Intent> installable = compileIntent(intent);
// If all went well, associate the resulting list of installable
// intents with the top-level intent and proceed to install.
......@@ -264,12 +256,12 @@ public class IntentManager
* @param intent intent
* @return result of compilation
*/
private List<InstallableIntent> compileIntent(Intent intent) {
if (intent instanceof InstallableIntent) {
return ImmutableList.of((InstallableIntent) intent);
private List<Intent> compileIntent(Intent intent) {
if (intent.isInstallable()) {
return ImmutableList.of(intent);
}
List<InstallableIntent> installable = new ArrayList<>();
List<Intent> installable = new ArrayList<>();
// TODO do we need to registerSubclassCompiler?
for (Intent compiled : getCompiler(intent).compile(intent)) {
installable.addAll(compileIntent(compiled));
......@@ -290,12 +282,12 @@ public class IntentManager
List<FlowRuleBatchOperation> installWork = Lists.newArrayList();
try {
List<InstallableIntent> installables = store.getInstallableIntents(intent.id());
List<Intent> installables = store.getInstallableIntents(intent.id());
if (installables != null) {
for (InstallableIntent installable : installables) {
for (Intent installable : installables) {
registerSubclassInstallerIfNeeded(installable);
trackerService.addTrackedResources(intent.id(),
installable.requiredLinks());
installable.resources());
List<FlowRuleBatchOperation> batch = getInstaller(installable).install(installable);
installWork.addAll(batch);
}
......@@ -324,14 +316,13 @@ public class IntentManager
try {
// Compile the intent into installable derivatives.
List<InstallableIntent> installable = compileIntent(intent);
List<Intent> installable = compileIntent(intent);
// If all went well, compare the existing list of installable
// intents with the newly compiled list. If they are the same,
// bail, out since the previous approach was determined not to
// be viable.
List<InstallableIntent> originalInstallable =
store.getInstallableIntents(intent.id());
List<Intent> originalInstallable = store.getInstallableIntents(intent.id());
if (Objects.equals(originalInstallable, installable)) {
eventDispatcher.post(store.setState(intent, FAILED));
......@@ -376,9 +367,9 @@ public class IntentManager
private void uninstallIntent(Intent intent, IntentState nextState) {
List<FlowRuleBatchOperation> uninstallWork = Lists.newArrayList();
try {
List<InstallableIntent> installables = store.getInstallableIntents(intent.id());
List<Intent> installables = store.getInstallableIntents(intent.id());
if (installables != null) {
for (InstallableIntent installable : installables) {
for (Intent installable : installables) {
List<FlowRuleBatchOperation> batches = getInstaller(installable).uninstall(installable);
uninstallWork.addAll(batches);
}
......@@ -422,12 +413,12 @@ public class IntentManager
*
* @param intent intent
*/
private void registerSubclassInstallerIfNeeded(InstallableIntent intent) {
private void registerSubclassInstallerIfNeeded(Intent intent) {
if (!installers.containsKey(intent.getClass())) {
Class<?> cls = intent.getClass();
while (cls != Object.class) {
// As long as we're within the InstallableIntent class descendants
if (InstallableIntent.class.isAssignableFrom(cls)) {
// As long as we're within the Intent class descendants
if (Intent.class.isAssignableFrom(cls)) {
IntentInstaller<?> installer = installers.get(cls);
if (installer != null) {
installers.put(intent.getClass(), installer);
......@@ -531,9 +522,7 @@ public class IntentManager
}
/**
* Apply a list of FlowRules.
*
* @param rules rules to apply
* Applies the next batch.
*/
private Future<CompletedBatchOperation> applyNextBatch() {
if (work.isEmpty()) {
......
package org.onlab.onos.net.intent.impl;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -13,16 +8,19 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.intent.IdGenerator;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentCompiler;
import org.onlab.onos.net.intent.IntentExtensionService;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.LinkCollectionIntent;
import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.net.topology.PathService;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* An intent compiler for
* {@link org.onlab.onos.net.intent.MultiPointToSinglePointIntent}.
......@@ -37,12 +35,8 @@ public class MultiPointToSinglePointIntentCompiler
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PathService pathService;
protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
intentManager.registerCompiler(MultiPointToSinglePointIntent.class, this);
}
......@@ -60,7 +54,7 @@ public class MultiPointToSinglePointIntentCompiler
links.addAll(path.links());
}
Intent result = new LinkCollectionIntent(intentIdGenerator.getNewId(),
Intent result = new LinkCollectionIntent(intent.appId(),
intent.selector(), intent.treatment(),
links, intent.egressPoint());
return Arrays.asList(result);
......
......@@ -11,6 +11,7 @@ import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.event.Event;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.LinkKey;
import org.onlab.onos.net.NetworkResource;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.link.LinkEvent;
import org.onlab.onos.net.topology.TopologyEvent;
......@@ -27,8 +28,8 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Multimaps.synchronizedSetMultimap;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
import static org.onlab.onos.net.LinkKey.linkKey;
import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
import static org.onlab.util.Tools.namedThreads;
import static org.slf4j.LoggerFactory.getLogger;
......@@ -81,16 +82,22 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
}
@Override
public void addTrackedResources(IntentId intentId, Collection<Link> resources) {
for (Link link : resources) {
intentsByLink.put(linkKey(link), intentId);
public void addTrackedResources(IntentId intentId,
Collection<NetworkResource> resources) {
for (NetworkResource resource : resources) {
if (resource instanceof Link) {
intentsByLink.put(linkKey((Link) resource), intentId);
}
}
}
@Override
public void removeTrackedResources(IntentId intentId, Collection<Link> resources) {
for (Link link : resources) {
intentsByLink.remove(linkKey(link), intentId);
public void removeTrackedResources(IntentId intentId,
Collection<NetworkResource> resources) {
for (NetworkResource resource : resources) {
if (resource instanceof Link) {
intentsByLink.remove(linkKey((Link) resource), intentId);
}
}
}
......
package org.onlab.onos.net.intent.impl;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.NetworkResource;
import org.onlab.onos.net.intent.IntentId;
import java.util.Collection;
......@@ -31,7 +31,8 @@ public interface ObjectiveTrackerService {
* @param intentId intent identity on whose behalf the path is being tracked
* @param resources resources to track
*/
public void addTrackedResources(IntentId intentId, Collection<Link> resources);
public void addTrackedResources(IntentId intentId,
Collection<NetworkResource> resources);
/**
* Removes a path flow to be tracked.
......@@ -39,6 +40,7 @@ public interface ObjectiveTrackerService {
* @param intentId intent identity on whose behalf the path is being tracked
* @param resources resources to stop tracking
*/
public void removeTrackedResources(IntentId intentId, Collection<Link> resources);
public void removeTrackedResources(IntentId intentId,
Collection<NetworkResource> resources);
}
......
package org.onlab.onos.net.intent.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -16,16 +11,19 @@ import org.onlab.onos.net.DefaultPath;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.IdGenerator;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentCompiler;
import org.onlab.onos.net.intent.IntentExtensionService;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.PathService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* A intent compiler for {@link org.onlab.onos.net.intent.HostToHostIntent}.
*/
......@@ -43,12 +41,8 @@ public class PointToPointIntentCompiler
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
intentManager.registerCompiler(PointToPointIntent.class, this);
}
......@@ -80,10 +74,8 @@ public class PointToPointIntentCompiler
*/
private Intent createPathIntent(Path path,
PointToPointIntent intent) {
return new PathIntent(intentIdGenerator.getNewId(),
intent.selector(), intent.treatment(),
path.src(), path.dst(), path);
return new PathIntent(intent.appId(),
intent.selector(), intent.treatment(), path);
}
/**
......
package org.onlab.onos.net.intent;
import org.junit.Test;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.TestApplicationId;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
......@@ -16,15 +18,13 @@ import static org.onlab.onos.net.NetTestTools.hid;
*/
public class TestHostToHostIntent {
private static final ApplicationId APPID = new TestApplicationId("foo");
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
private HostToHostIntent makeHostToHost(long id, HostId one, HostId two) {
return new HostToHostIntent(new IntentId(id),
one,
two,
selector,
treatment);
private HostToHostIntent makeHostToHost(HostId one, HostId two) {
return new HostToHostIntent(APPID, one, two, selector, treatment);
}
/**
......@@ -36,8 +36,8 @@ public class TestHostToHostIntent {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(12, one, two);
HostToHostIntent i1 = makeHostToHost(one, two);
HostToHostIntent i2 = makeHostToHost(one, two);
assertThat(i1, is(equalTo(i2)));
}
......@@ -47,42 +47,39 @@ public class TestHostToHostIntent {
* to different Hosts. These should compare not equal.
*/
@Test
public void testLinksDifferentEquals() {
public void testSameEquals2() {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(12, two, one);
HostToHostIntent i1 = makeHostToHost(one, two);
HostToHostIntent i2 = makeHostToHost(two, one);
assertThat(i1, is(not(equalTo(i2))));
assertThat(i1, is(equalTo(i2)));
}
/**
* Tests the equals() method where two HostToHostIntents have different
* ids. These should compare not equal.
* Tests that the hashCode() values for two equivalent HostToHostIntent
* objects are the same.
*/
@Test
public void testBaseDifferentEquals() {
public void testHashCodeEquals() {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(11, one, two);
HostToHostIntent i1 = makeHostToHost(one, two);
HostToHostIntent i2 = makeHostToHost(one, two);
assertThat(i1, is(not(equalTo(i2))));
assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
}
/**
* Tests that the hashCode() values for two equivalent HostToHostIntent
* objects are the same.
* Tests that the hashCode() values for two distinct LinkCollectionIntent
* objects are different.
*/
@Test
public void testHashCodeEquals() {
public void testHashCodeEquals2() {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(12, one, two);
HostToHostIntent i1 = makeHostToHost(one, two);
HostToHostIntent i2 = makeHostToHost(two, one);
assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
}
......@@ -91,13 +88,13 @@ public class TestHostToHostIntent {
* Tests that the hashCode() values for two distinct LinkCollectionIntent
* objects are different.
*/
@Test
public void testHashCodeDifferent() {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(112, one, two);
HostId three = hid("00:00:00:00:00:32/-1");
HostToHostIntent i1 = makeHostToHost(one, two);
HostToHostIntent i2 = makeHostToHost(one, three);
assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
}
......
......@@ -11,6 +11,8 @@ import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.TestApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
......@@ -23,6 +25,8 @@ import org.onlab.onos.net.flow.TrafficTreatment;
*/
public class TestLinkCollectionIntent {
private static final ApplicationId APPID = new TestApplicationId("foo");
private Link link1 = link("dev1", 1, "dev2", 2);
private Link link2 = link("dev1", 1, "dev3", 2);
private Link link3 = link("dev2", 1, "dev3", 2);
......@@ -38,10 +42,9 @@ public class TestLinkCollectionIntent {
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
private LinkCollectionIntent makeLinkCollection(long id, Set<Link> links,
private LinkCollectionIntent makeLinkCollection(Set<Link> links,
ConnectPoint egress) {
return new LinkCollectionIntent(new IntentId(id),
selector, treatment, links, egress);
return new LinkCollectionIntent(APPID, selector, treatment, links, egress);
}
@Before
......@@ -64,8 +67,8 @@ public class TestLinkCollectionIntent {
links2.add(link2);
links2.add(link1);
LinkCollectionIntent i1 = makeLinkCollection(12, links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(12, links2, egress1);
LinkCollectionIntent i1 = makeLinkCollection(links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(links2, egress1);
assertThat(i1, is(equalTo(i2)));
}
......@@ -82,8 +85,8 @@ public class TestLinkCollectionIntent {
links2.add(link3);
links2.add(link1);
LinkCollectionIntent i1 = makeLinkCollection(12, links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(12, links2, egress1);
LinkCollectionIntent i1 = makeLinkCollection(links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(links2, egress1);
assertThat(i1, is(not(equalTo(i2))));
}
......@@ -102,26 +105,8 @@ public class TestLinkCollectionIntent {
links2.add(link2);
links2.add(link1);
LinkCollectionIntent i1 = makeLinkCollection(12, links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(12, links2, egress2);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests the equals() method where two LinkCollectionIntents have different
* ids. These should compare not equal.
*/
@Test
public void testBaseDifferentEquals() {
links1.add(link1);
links1.add(link2);
links2.add(link2);
links2.add(link1);
LinkCollectionIntent i1 = makeLinkCollection(1, links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(2, links2, egress1);
LinkCollectionIntent i1 = makeLinkCollection(links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(links2, egress2);
assertThat(i1, is(not(equalTo(i2))));
}
......@@ -140,8 +125,8 @@ public class TestLinkCollectionIntent {
links2.add(link2);
links2.add(link1);
LinkCollectionIntent i1 = makeLinkCollection(1, links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(1, links2, egress1);
LinkCollectionIntent i1 = makeLinkCollection(links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(links2, egress1);
assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
}
......@@ -158,8 +143,8 @@ public class TestLinkCollectionIntent {
links2.add(link1);
links2.add(link3);
LinkCollectionIntent i1 = makeLinkCollection(1, links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(1, links2, egress2);
LinkCollectionIntent i1 = makeLinkCollection(links1, egress1);
LinkCollectionIntent i2 = makeLinkCollection(links2, egress2);
assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
}
......
package org.onlab.onos.net.intent;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.TestApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import java.util.HashSet;
import java.util.Set;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
......@@ -20,6 +22,8 @@ import static org.onlab.onos.net.NetTestTools.connectPoint;
*/
public class TestMultiPointToSinglePointIntent {
private static final ApplicationId APPID = new TestApplicationId("foo");
private ConnectPoint point1 = connectPoint("dev1", 1);
private ConnectPoint point2 = connectPoint("dev2", 1);
private ConnectPoint point3 = connectPoint("dev3", 1);
......@@ -33,19 +37,14 @@ public class TestMultiPointToSinglePointIntent {
/**
* Creates a MultiPointToSinglePointIntent object.
*
* @param id identifier to use for the new intent
* @param ingress set of ingress points
* @param egress egress point
* @return MultiPointToSinglePoint intent
*/
private MultiPointToSinglePointIntent makeIntent(long id,
Set<ConnectPoint> ingress,
private MultiPointToSinglePointIntent makeIntent(Set<ConnectPoint> ingress,
ConnectPoint egress) {
return new MultiPointToSinglePointIntent(new IntentId(id),
selector,
treatment,
ingress,
egress);
return new MultiPointToSinglePointIntent(APPID, selector, treatment,
ingress, egress);
}
/**
......@@ -72,8 +71,8 @@ public class TestMultiPointToSinglePointIntent {
ingress2.add(point3);
ingress2.add(point2);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(12, ingress2, point1);
Intent i1 = makeIntent(ingress1, point1);
Intent i2 = makeIntent(ingress2, point1);
assertThat(i1, is(equalTo(i2)));
}
......@@ -89,23 +88,8 @@ public class TestMultiPointToSinglePointIntent {
ingress2.add(point3);
ingress2.add(point2);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(12, ingress2, point1);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests the equals() method where two MultiPointToSinglePoint have different
* ids. These should compare not equal.
*/
@Test
public void testBaseDifferentEquals() {
ingress1.add(point3);
ingress2.add(point3);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(11, ingress2, point1);
Intent i1 = makeIntent(ingress1, point1);
Intent i2 = makeIntent(ingress2, point1);
assertThat(i1, is(not(equalTo(i2))));
}
......@@ -122,8 +106,8 @@ public class TestMultiPointToSinglePointIntent {
ingress2.add(point3);
ingress2.add(point2);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(12, ingress2, point1);
Intent i1 = makeIntent(ingress1, point1);
Intent i2 = makeIntent(ingress2, point1);
assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
}
......@@ -139,8 +123,8 @@ public class TestMultiPointToSinglePointIntent {
ingress2.add(point3);
ingress2.add(point2);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(12, ingress2, point1);
Intent i1 = makeIntent(ingress1, point1);
Intent i2 = makeIntent(ingress2, point1);
assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
......
package org.onlab.onos.net.intent;
import org.junit.Test;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.TestApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.*;
import static org.onlab.onos.net.NetTestTools.connectPoint;
/**
......@@ -16,20 +16,17 @@ import static org.onlab.onos.net.NetTestTools.connectPoint;
*/
public class TestPointToPointIntent {
private static final ApplicationId APPID = new TestApplicationId("foo");
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
private ConnectPoint point1 = connectPoint("dev1", 1);
private ConnectPoint point2 = connectPoint("dev2", 1);
private PointToPointIntent makePointToPoint(long id,
ConnectPoint ingress,
private PointToPointIntent makePointToPoint(ConnectPoint ingress,
ConnectPoint egress) {
return new PointToPointIntent(new IntentId(id),
selector,
treatment,
ingress,
egress);
return new PointToPointIntent(APPID, selector, treatment, ingress, egress);
}
/**
......@@ -38,8 +35,8 @@ public class TestPointToPointIntent {
*/
@Test
public void testSameEquals() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(12, point1, point2);
PointToPointIntent i1 = makePointToPoint(point1, point2);
PointToPointIntent i2 = makePointToPoint(point1, point2);
assertThat(i1, is(equalTo(i2)));
}
......@@ -50,22 +47,8 @@ public class TestPointToPointIntent {
*/
@Test
public void testLinksDifferentEquals() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(12, point2, point1);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests the equals() method where two HostToHostIntents have different
* ids. These should compare not equal.
*/
@Test
public void testBaseDifferentEquals() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(11, point1, point2);
PointToPointIntent i1 = makePointToPoint(point1, point2);
PointToPointIntent i2 = makePointToPoint(point2, point1);
assertThat(i1, is(not(equalTo(i2))));
}
......@@ -76,8 +59,8 @@ public class TestPointToPointIntent {
*/
@Test
public void testHashCodeEquals() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(12, point1, point2);
PointToPointIntent i1 = makePointToPoint(point1, point2);
PointToPointIntent i2 = makePointToPoint(point1, point2);
assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
}
......@@ -88,8 +71,8 @@ public class TestPointToPointIntent {
*/
@Test
public void testHashCodeDifferent() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(22, point1, point2);
PointToPointIntent i1 = makePointToPoint(point1, point2);
PointToPointIntent i2 = makePointToPoint(point2, point1);
assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
}
......
package org.onlab.onos.net.intent.impl;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.TestApplicationId;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.flow.TrafficSelector;
......@@ -12,16 +12,14 @@ import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.HostToHostIntent;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentTestsMocks;
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import java.util.List;
import static org.easymock.EasyMock.*;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
......@@ -40,6 +38,8 @@ public class TestHostToHostIntentCompiler {
private static final String HOST_ONE = HOST_ONE_MAC + "/" + HOST_ONE_VLAN;
private static final String HOST_TWO = HOST_TWO_MAC + "/" + HOST_TWO_VLAN;
private static final ApplicationId APPID = new TestApplicationId("foo");
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
......@@ -73,11 +73,8 @@ public class TestHostToHostIntentCompiler {
* @return HostToHostIntent for the two hosts
*/
private HostToHostIntent makeIntent(String oneIdString, String twoIdString) {
return new HostToHostIntent(new IntentId(12),
hid(oneIdString),
hid(twoIdString),
selector,
treatment);
return new HostToHostIntent(APPID, hid(oneIdString), hid(twoIdString),
selector, treatment);
}
/**
......@@ -91,9 +88,6 @@ public class TestHostToHostIntentCompiler {
new HostToHostIntentCompiler();
compiler.pathService = new IntentTestsMocks.MockPathService(hops);
compiler.hostService = mockHostService;
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
compiler.intentIdGenerator =
new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
return compiler;
}
......
package org.onlab.onos.net.intent.impl;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.TestApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.ElementId;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentTestsMocks;
import org.onlab.onos.net.intent.LinkCollectionIntent;
import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.PathService;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
......@@ -32,6 +33,8 @@ import static org.onlab.onos.net.intent.LinksHaveEntryWithSourceDestinationPairM
*/
public class TestMultiPointToSinglePointIntentCompiler {
private static final ApplicationId APPID = new TestApplicationId("foo");
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
......@@ -85,12 +88,8 @@ public class TestMultiPointToSinglePointIntentCompiler {
ingressPoints.add(connectPoint(ingressId, 1));
}
return new MultiPointToSinglePointIntent(
new IntentId(12),
selector,
treatment,
ingressPoints,
egressPoint);
return new MultiPointToSinglePointIntent(APPID, selector, treatment,
ingressPoints, egressPoint);
}
/**
......@@ -103,9 +102,6 @@ public class TestMultiPointToSinglePointIntentCompiler {
MultiPointToSinglePointIntentCompiler compiler =
new MultiPointToSinglePointIntentCompiler();
compiler.pathService = new MockPathService(hops);
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
compiler.intentIdGenerator =
new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
return compiler;
}
......
package org.onlab.onos.net.intent.impl;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.TestApplicationId;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentTestsMocks;
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.onos.net.intent.PointToPointIntent;
import java.util.List;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
......@@ -24,6 +25,8 @@ import static org.onlab.onos.net.intent.LinksHaveEntryWithSourceDestinationPairM
*/
public class TestPointToPointIntentCompiler {
private static final ApplicationId APPID = new TestApplicationId("foo");
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
......@@ -36,9 +39,7 @@ public class TestPointToPointIntentCompiler {
*/
private PointToPointIntent makeIntent(String ingressIdString,
String egressIdString) {
return new PointToPointIntent(new IntentId(12),
selector,
treatment,
return new PointToPointIntent(APPID, selector, treatment,
connectPoint(ingressIdString, 1),
connectPoint(egressIdString, 1));
}
......@@ -53,9 +54,6 @@ public class TestPointToPointIntentCompiler {
PointToPointIntentCompiler compiler =
new PointToPointIntentCompiler();
compiler.pathService = new IntentTestsMocks.MockPathService(hops);
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
compiler.intentIdGenerator =
new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
return compiler;
}
......
......@@ -2,6 +2,7 @@ package org.onlab.onos.store.flow.impl;
import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onlab.onos.store.flow.impl.FlowStoreMessageSubjects.*;
import java.io.IOException;
import java.util.Collection;
......@@ -30,6 +31,7 @@ import org.onlab.onos.net.flow.StoredFlowEntry;
import org.onlab.onos.store.AbstractStore;
import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
import org.onlab.onos.store.cluster.messaging.ClusterMessageResponse;
import org.onlab.onos.store.flow.ReplicaInfo;
import org.onlab.onos.store.flow.ReplicaInfoService;
......@@ -80,10 +82,44 @@ public class DistributedFlowRuleStore
};
// TODO: make this configurable
private static final long FLOW_RULE_STORE_TIMEOUT_MILLIS = 1000;
private static final long FLOW_RULE_STORE_TIMEOUT_MILLIS = 5000;
@Activate
public void activate() {
clusterCommunicator.addSubscriber(STORE_FLOW_RULE, new ClusterMessageHandler() {
@Override
public void handle(ClusterMessage message) {
FlowRule rule = SERIALIZER.decode(message.payload());
log.info("received add request for {}", rule);
storeFlowEntryInternal(rule);
// FIXME what to respond.
try {
// FIXME: #respond() not working. responded message is
// handled by this sender node and never goes back.
message.respond(SERIALIZER.encode("ACK"));
} catch (IOException e) {
log.error("Failed to respond back", e);
}
}
});
clusterCommunicator.addSubscriber(DELETE_FLOW_RULE, new ClusterMessageHandler() {
@Override
public void handle(ClusterMessage message) {
FlowRule rule = SERIALIZER.decode(message.payload());
log.info("received delete request for {}", rule);
deleteFlowRuleInternal(rule);
// FIXME what to respond.
try {
message.respond(SERIALIZER.encode("ACK"));
} catch (IOException e) {
log.error("Failed to respond back", e);
}
}
});
log.info("Started");
}
......@@ -131,13 +167,14 @@ public class DistributedFlowRuleStore
}
@Override
public void storeFlowRule(FlowRule rule) {
public boolean storeFlowRule(FlowRule rule) {
ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(rule.deviceId());
if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) {
storeFlowEntryInternal(rule);
return;
return storeFlowEntryInternal(rule);
}
log.warn("Not my flow forwarding to {}", replicaInfo.master().orNull());
ClusterMessage message = new ClusterMessage(
clusterService.getLocalNode().id(),
FlowStoreMessageSubjects.STORE_FLOW_RULE,
......@@ -150,26 +187,29 @@ public class DistributedFlowRuleStore
// FIXME: throw a FlowStoreException
throw new RuntimeException(e);
}
return false;
}
private synchronized void storeFlowEntryInternal(FlowRule flowRule) {
private synchronized boolean storeFlowEntryInternal(FlowRule flowRule) {
StoredFlowEntry flowEntry = new DefaultFlowEntry(flowRule);
DeviceId deviceId = flowRule.deviceId();
// write to local copy.
if (!flowEntries.containsEntry(deviceId, flowEntry)) {
flowEntries.put(deviceId, flowEntry);
flowEntriesById.put(flowRule.appId(), flowEntry);
notifyDelegate(new FlowRuleEvent(Type.RULE_ADD_REQUESTED, flowRule));
return true;
}
// write to backup.
// TODO: write to a hazelcast map.
return false;
}
@Override
public synchronized void deleteFlowRule(FlowRule rule) {
public synchronized boolean deleteFlowRule(FlowRule rule) {
ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(rule.deviceId());
if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) {
deleteFlowRuleInternal(rule);
return;
return deleteFlowRuleInternal(rule);
}
ClusterMessage message = new ClusterMessage(
......@@ -184,15 +224,21 @@ public class DistributedFlowRuleStore
// FIXME: throw a FlowStoreException
throw new RuntimeException(e);
}
return false;
}
private synchronized void deleteFlowRuleInternal(FlowRule flowRule) {
private synchronized boolean deleteFlowRuleInternal(FlowRule flowRule) {
StoredFlowEntry entry = getFlowEntryInternal(flowRule);
if (entry == null) {
return;
return false;
}
entry.setState(FlowEntryState.PENDING_REMOVE);
// TODO: also update backup.
notifyDelegate(new FlowRuleEvent(Type.RULE_REMOVE_REQUESTED, flowRule));
return true;
}
@Override
......
package org.onlab.onos.store.intent.impl;
import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentEvent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentState;
import org.onlab.onos.net.intent.IntentStore;
import org.onlab.onos.net.intent.IntentStoreDelegate;
import org.onlab.onos.store.AbstractStore;
import org.slf4j.Logger;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.onlab.onos.net.intent.IntentState.*;
import static org.slf4j.LoggerFactory.getLogger;
//FIXME: I LIE I AM NOT DISTRIBUTED
@Component(immediate = true)
@Service
public class DistributedIntentStore
extends AbstractStore<IntentEvent, IntentStoreDelegate>
implements IntentStore {
private final Logger log = getLogger(getClass());
private final Map<IntentId, Intent> intents = new ConcurrentHashMap<>();
private final Map<IntentId, IntentState> states = new ConcurrentHashMap<>();
private final Map<IntentId, List<Intent>> installable = new ConcurrentHashMap<>();
@Activate
public void activate() {
log.info("Started");
}
@Deactivate
public void deactivate() {
log.info("Stopped");
}
@Override
public IntentEvent createIntent(Intent intent) {
intents.put(intent.id(), intent);
return this.setState(intent, IntentState.SUBMITTED);
}
@Override
public IntentEvent removeIntent(IntentId intentId) {
Intent intent = intents.remove(intentId);
installable.remove(intentId);
IntentEvent event = this.setState(intent, WITHDRAWN);
states.remove(intentId);
return event;
}
@Override
public long getIntentCount() {
return intents.size();
}
@Override
public Iterable<Intent> getIntents() {
return ImmutableSet.copyOf(intents.values());
}
@Override
public Intent getIntent(IntentId intentId) {
return intents.get(intentId);
}
@Override
public IntentState getIntentState(IntentId id) {
return states.get(id);
}
@Override
public IntentEvent setState(Intent intent, IntentState state) {
IntentId id = intent.id();
states.put(id, state);
IntentEvent.Type type = (state == SUBMITTED ? IntentEvent.Type.SUBMITTED :
(state == INSTALLED ? IntentEvent.Type.INSTALLED :
(state == FAILED ? IntentEvent.Type.FAILED :
state == WITHDRAWN ? IntentEvent.Type.WITHDRAWN :
null)));
return type == null ? null : new IntentEvent(type, intent);
}
@Override
public void addInstallableIntents(IntentId intentId, List<Intent> result) {
installable.put(intentId, result);
}
@Override
public List<Intent> getInstallableIntents(IntentId intentId) {
return installable.get(intentId);
}
@Override
public void removeInstalledIntents(IntentId intentId) {
installable.remove(intentId);
}
}
......@@ -8,6 +8,7 @@ import java.util.HashMap;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.cluster.RoleInfo;
import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultAnnotations;
......@@ -26,7 +27,12 @@ import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.device.DefaultDeviceDescription;
import org.onlab.onos.net.device.DefaultPortDescription;
import org.onlab.onos.net.flow.DefaultFlowRule;
import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.FlowId;
import org.onlab.onos.net.flow.criteria.Criteria;
import org.onlab.onos.net.flow.criteria.Criterion;
import org.onlab.onos.net.flow.instructions.Instructions;
import org.onlab.onos.net.host.DefaultHostDescription;
import org.onlab.onos.net.host.HostDescription;
import org.onlab.onos.net.link.DefaultLinkDescription;
......@@ -88,7 +94,22 @@ public final class KryoNamespaces {
HostDescription.class,
DefaultHostDescription.class,
DefaultFlowRule.class,
FlowId.class
FlowId.class,
DefaultTrafficSelector.class,
Criteria.PortCriterion.class,
Criteria.EthCriterion.class,
Criteria.EthTypeCriterion.class,
Criteria.IPCriterion.class,
Criteria.IPProtocolCriterion.class,
Criteria.VlanIdCriterion.class,
Criteria.VlanPcpCriterion.class,
Criteria.TcpPortCriterion.class,
Criterion.class,
Criterion.Type.class,
DefaultTrafficTreatment.class,
Instructions.DropInstruction.class,
Instructions.OutputInstruction.class,
RoleInfo.class
)
.register(URI.class, new URISerializer())
.register(NodeId.class, new NodeIdSerializer())
......
......@@ -3,6 +3,7 @@ package org.onlab.onos.store.serializers;
import static org.junit.Assert.assertEquals;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.PortNumber.portNumber;
import static java.util.Arrays.asList;
import java.nio.ByteBuffer;
......@@ -11,6 +12,7 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.cluster.RoleInfo;
import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.Annotations;
import org.onlab.onos.net.ConnectPoint;
......@@ -198,6 +200,12 @@ public class KryoSerializerTest {
}
@Test
public void testRoleInfo() {
testSerialized(new RoleInfo(new NodeId("master"),
asList(new NodeId("stby1"), new NodeId("stby2"))));
}
@Test
public void testAnnotations() {
// Annotations does not have equals defined, manually test equality
final byte[] a1Bytes = serializer.encode(A1);
......
......@@ -148,8 +148,9 @@ public class SimpleFlowRuleStore
}
@Override
public void storeFlowRule(FlowRule rule) {
public boolean storeFlowRule(FlowRule rule) {
final boolean added = storeFlowRuleInternal(rule);
return added;
}
private boolean storeFlowRuleInternal(FlowRule rule) {
......@@ -166,13 +167,14 @@ public class SimpleFlowRuleStore
}
// new flow rule added
existing.add(f);
// TODO: notify through delegate about remote event?
// TODO: Should we notify only if it's "remote" event?
//notifyDelegate(new FlowRuleEvent(Type.RULE_ADD_REQUESTED, rule));
return true;
}
}
@Override
public void deleteFlowRule(FlowRule rule) {
public boolean deleteFlowRule(FlowRule rule) {
List<StoredFlowEntry> entries = getFlowEntries(rule.deviceId(), rule.id());
synchronized (entries) {
......@@ -180,12 +182,15 @@ public class SimpleFlowRuleStore
if (entry.equals(rule)) {
synchronized (entry) {
entry.setState(FlowEntryState.PENDING_REMOVE);
return;
// TODO: Should we notify only if it's "remote" event?
//notifyDelegate(new FlowRuleEvent(Type.RULE_REMOVE_REQUESTED, rule));
return true;
}
}
}
}
//log.warn("Cannot find rule {}", rule);
return false;
}
@Override
......
package org.onlab.onos.store.trivial.impl;
import static org.onlab.onos.net.intent.IntentState.FAILED;
import static org.onlab.onos.net.intent.IntentState.INSTALLED;
import static org.onlab.onos.net.intent.IntentState.SUBMITTED;
import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.net.intent.InstallableIntent;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentEvent;
import org.onlab.onos.net.intent.IntentId;
......@@ -24,7 +14,12 @@ import org.onlab.onos.net.intent.IntentStoreDelegate;
import org.onlab.onos.store.AbstractStore;
import org.slf4j.Logger;
import com.google.common.collect.ImmutableSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.onlab.onos.net.intent.IntentState.*;
import static org.slf4j.LoggerFactory.getLogger;
@Component(immediate = true)
@Service
......@@ -35,7 +30,7 @@ public class SimpleIntentStore
private final Logger log = getLogger(getClass());
private final Map<IntentId, Intent> intents = new ConcurrentHashMap<>();
private final Map<IntentId, IntentState> states = new ConcurrentHashMap<>();
private final Map<IntentId, List<InstallableIntent>> installable =
private final Map<IntentId, List<Intent>> installable =
new ConcurrentHashMap<>();
@Activate
......@@ -96,12 +91,12 @@ public class SimpleIntentStore
}
@Override
public void addInstallableIntents(IntentId intentId, List<InstallableIntent> result) {
public void addInstallableIntents(IntentId intentId, List<Intent> result) {
installable.put(intentId, result);
}
@Override
public List<InstallableIntent> getInstallableIntents(IntentId intentId) {
public List<Intent> getInstallableIntents(IntentId intentId) {
return installable.get(intentId);
}
......
......@@ -572,7 +572,7 @@
<group>
<title>Sample Applications</title>
<packages>
org.onlab.onos.tvue:org.onlab.onos.fwd:org.onlab.onos.ifwd:org.onlab.onos.mobility:org.onlab.onos.proxyarp:org.onlab.onos.foo:org.onlab.onos.calendar
org.onlab.onos.tvue:org.onlab.onos.fwd:org.onlab.onos.ifwd:org.onlab.onos.mobility:org.onlab.onos.proxyarp:org.onlab.onos.foo:org.onlab.onos.calendar:org.onlab.onos.sdnip:org.onlab.onos.sdnip.*:org.onlab.onos.optical:org.onlab.onos.optical.*
</packages>
</group>
</groups>
......
......@@ -171,6 +171,7 @@ public final class KryoNamespace implements KryoFactory {
Kryo kryo = getKryo();
try {
kryo.writeClassAndObject(out, obj);
out.flush();
return out.toBytes();
} finally {
putKryo(kryo);
......@@ -188,6 +189,7 @@ public final class KryoNamespace implements KryoFactory {
Kryo kryo = getKryo();
try {
kryo.writeClassAndObject(out, obj);
out.flush();
} finally {
putKryo(kryo);
}
......