aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/core/api/src/main/java/org
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
committerAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
commit13d05bc8458758ee39cb829098241e89616717ee (patch)
tree22a4d1ce65f15952f07a3df5af4b462b4697cb3a /framework/src/onos/core/api/src/main/java/org
parent6139282e1e93c2322076de4b91b1c85d0bc4a8b3 (diff)
ONOS checkin based on commit tag e796610b1f721d02f9b0e213cf6f7790c10ecd60
Change-Id: Ife8810491034fe7becdba75dda20de4267bd15cd
Diffstat (limited to 'framework/src/onos/core/api/src/main/java/org')
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationAdminService.java70
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java89
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationEvent.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationException.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationService.java70
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationState.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStore.java108
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java125
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/app/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigEvent.java74
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigService.java74
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStore.java45
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java279
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cfg/package-info.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java54
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java32
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterEvent.java72
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterEventListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterService.java68
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterStore.java84
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ControllerNode.java61
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ControllerNodeToNodeId.java45
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/DefaultControllerNode.java103
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Leadership.java164
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipEvent.java107
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipEventListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipService.java124
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java58
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/RoleInfo.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/codec/CodecContext.java50
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/codec/CodecService.java57
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/codec/JsonCodec.java115
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/codec/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/Application.java87
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationId.java36
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationIdStore.java59
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationRole.java38
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/CoreService.java83
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplication.java149
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java81
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java66
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/GroupId.java31
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/IdBlock.java102
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/IdBlockStore.java31
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/IdGenerator.java31
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/MetricsHelper.java56
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/UnavailableIdException.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/Version.java144
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/core/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/AbstractEvent.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/AbstractListenerManager.java58
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/DefaultEventSinkRegistry.java62
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/Event.java45
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/EventDeliveryService.java38
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/EventDispatcher.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/EventFilter.java34
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/EventListener.java30
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/EventSink.java36
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/EventSinkRegistry.java60
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/ListenerRegistry.java99
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/ListenerService.java38
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/event/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipAdminService.java45
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipEvent.java95
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipService.java101
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipStore.java125
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipTerm.java71
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipTermService.java35
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/mastership/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractAnnotated.java48
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractDescription.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractElement.java45
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractModel.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Annotated.java30
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java145
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Annotations.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationsUtil.java45
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/ChannelSpacing.java44
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/ConnectPoint.java175
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java254
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultDevice.java142
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultEdgeLink.java96
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultHost.java117
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultLink.java131
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPath.java105
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPort.java127
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Description.java26
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Device.java83
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/DeviceId.java99
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/EdgeLink.java39
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Element.java30
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/ElementId.java22
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/GridType.java29
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Host.java68
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/HostId.java129
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/HostLocation.java67
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/IndexedLambda.java71
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/IpElementId.java61
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Lambda.java45
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Link.java114
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/LinkKey.java110
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/MastershipRole.java42
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/MutableAnnotations.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/NetTools.java37
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/NetworkResource.java22
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/OchPort.java115
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignal.java176
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignalType.java32
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/OduCltPort.java97
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/OduSignalType.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/OmsPort.java131
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Path.java42
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Port.java100
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/PortNumber.java182
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/Provided.java32
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/SparseAnnotations.java44
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java87
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeDescription.java46
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeName.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ControllerConfig.java39
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ControllerInfo.java38
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultBridgeDescription.java87
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultNextGroup.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultTunnelDescription.java87
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/IpTunnelEndPoint.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/MplsQuery.java35
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/NextGroup.java30
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/Pipeliner.java57
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PipelinerContext.java41
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PortAdmin.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PortConfig.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/QueueConfig.java56
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/QueueInfo.java56
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java55
-rwxr-xr-xframework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelDescription.java86
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java28
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelName.java79
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/VlanQuery.java35
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/package-info.java21
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/Config.java312
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigApplyDelegate.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigFactory.java122
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigOperator.java31
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigEvent.java92
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigRegistry.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigService.java146
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStore.java130
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/SubjectFactory.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/AllowedEntityConfig.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java70
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java130
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java27
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java90
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java175
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/SubjectFactories.java93
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java145
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortDescription.java120
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortStatistics.java346
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceAdminService.java34
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceClockService.java41
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceDescription.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceEvent.java141
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProvider.java57
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProviderRegistry.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProviderService.java82
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceService.java132
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceStore.java170
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OchPortDescription.java111
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OduCltPortDescription.java77
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OmsPortDescription.java109
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/PortDescription.java56
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/PortStatistics.java100
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/AbstractBehaviour.java37
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/AbstractHandlerBehaviour.java38
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/Behaviour.java39
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java214
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverData.java100
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverHandler.java67
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverProvider.java86
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverProviderService.java23
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/Driver.java132
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverAdminService.java46
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverConnect.java36
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverData.java50
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverHandler.java57
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverProvider.java34
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverResolver.java34
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverService.java83
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/HandlerBehaviour.java38
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/XmlDriverLoader.java176
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/package-info.java68
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortEvent.java59
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortService.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperation.java128
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperationEntry.java90
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperationResult.java38
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/CompletedBatchOperation.java96
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowEntry.java137
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java390
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java365
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java479
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowEntry.java102
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowId.java58
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java265
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEntry.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEvent.java116
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchOperation.java54
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchRequest.java59
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleEvent.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleExtPayLoad.java67
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperation.java67
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperations.java181
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperationsContext.java28
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProvider.java58
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProviderRegistry.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProviderService.java52
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleService.java107
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStore.java96
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/StoredFlowEntry.java50
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java420
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java431
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java36
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java527
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java181
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/EthCriterion.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/EthTypeCriterion.java89
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPCriterion.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPDscpCriterion.java76
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPEcnCriterion.java76
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPProtocolCriterion.java76
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6ExthdrFlagsCriterion.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6FlowLabelCriterion.java76
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6NDLinkLayerAddressCriterion.java81
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6NDTargetAddressCriterion.java77
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IcmpCodeCriterion.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IcmpTypeCriterion.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Icmpv6CodeCriterion.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Icmpv6TypeCriterion.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IndexedLambdaCriterion.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/LambdaCriterion.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MetadataCriterion.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MplsBosCriterion.java48
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MplsCriterion.java67
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OchSignalCriterion.java81
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OchSignalTypeCriterion.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OpticalSignalTypeCriterion.java83
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/PortCriterion.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/SctpPortCriterion.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/TcpPortCriterion.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/TunnelIdCriterion.java74
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/UdpPortCriterion.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/VlanIdCriterion.java76
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/VlanPcpCriterion.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java84
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java742
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L0ModificationInstruction.java139
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java517
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java231
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L4ModificationInstruction.java114
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/package-info.java26
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java239
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultForwardingObjective.java241
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultNextObjective.java222
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java158
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveService.java65
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveStore.java50
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveStoreDelegate.java26
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ForwardingObjective.java158
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/NextObjective.java167
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/Objective.java134
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveContext.java47
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveError.java60
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveEvent.java64
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/package-info.java22
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java229
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java252
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java204
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupKey.java55
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/Group.java99
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupBucket.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupBuckets.java76
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupDescription.java91
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupEvent.java99
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupKey.java31
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupOperation.java181
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupOperations.java50
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProvider.java37
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProviderRegistry.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProviderService.java47
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupService.java139
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupStore.java175
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/StoredGroupBucketEntry.java37
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/StoredGroupEntry.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java122
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostAdminService.java66
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostDescription.java58
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostEvent.java73
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProvider.java37
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProviderRegistry.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProviderService.java42
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostService.java146
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostStore.java167
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/InterfaceIpAddress.java192
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/PortAddresses.java127
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/ConnectivityIntent.java187
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Constraint.java53
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/FlowRuleIntent.java110
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java194
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Intent.java218
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentBatchDelegate.java35
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentClockService.java34
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentCompiler.java44
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentData.java327
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentEvent.java146
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentException.java53
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentExtensionService.java51
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentId.java87
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentListener.java26
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentOperation.java124
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentService.java123
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentState.java117
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java143
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentStoreDelegate.java42
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java163
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/LinkCollectionIntent.java241
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsIntent.java261
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsPathIntent.java167
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MultiPointToSinglePointIntent.java223
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalCircuitIntent.java219
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalConnectivityIntent.java223
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalPathIntent.java234
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionEvent.java35
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionEventListener.java26
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionService.java48
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java202
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PointToPointIntent.java215
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/SinglePointToMultiPointIntent.java219
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/TwoWayP2PIntent.java195
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/AnnotationConstraint.java113
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/AsymmetricPathConstraint.java64
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java96
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BooleanConstraint.java64
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LambdaConstraint.java91
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LatencyConstraint.java93
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LinkTypeConstraint.java108
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/ObstacleConstraint.java92
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/PartialFailureConstraint.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/WaypointConstraint.java117
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/package-info.java83
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/DefaultLinkDescription.java73
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkAdminService.java50
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkDescription.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkEvent.java68
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProvider.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProviderRegistry.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProviderService.java57
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkService.java116
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkStore.java117
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/Band.java133
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/BandEntry.java37
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultBand.java136
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java233
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java171
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/Meter.java179
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterContext.java38
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterEntry.java57
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterEvent.java62
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterFailReason.java89
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterId.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterOperation.java88
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterOperations.java50
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProvider.java48
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProviderRegistry.java27
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProviderService.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java147
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterService.java61
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterState.java43
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStore.java90
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStoreResult.java66
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAdminService.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAllocation.java94
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceConsumer.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java146
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java155
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java90
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/package-info.java21
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultInboundPacket.java91
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultOutboundPacket.java89
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultPacketContext.java95
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultPacketRequest.java84
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/InboundPacket.java50
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/OutboundPacket.java51
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketContext.java73
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketEvent.java56
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketPriority.java53
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProcessor.java83
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProvider.java32
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProviderRegistry.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProviderService.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketRequest.java47
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketService.java79
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketStore.java59
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/package-info.java21
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractListenerProviderRegistry.java66
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProvider.java39
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProviderRegistry.java111
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProviderService.java61
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/Provider.java30
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderId.java135
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderRegistry.java57
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderService.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java64
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java45
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStoreDelegate.java35
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceAllocation.java31
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceAllocationException.java36
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceException.java51
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceId.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceRequest.java32
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceType.java39
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/DeviceResourceService.java85
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/DeviceResourceStore.java89
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java72
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceAllocation.java77
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceRequest.java77
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceAllocations.java112
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java186
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResource.java93
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceAllocation.java77
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java37
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResource.java22
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceAllocations.java59
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceEvent.java48
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java93
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java95
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStore.java73
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResources.java63
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabel.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceAllocation.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java37
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/package-info.java21
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/DefaultLoad.java111
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/Load.java51
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/StatisticService.java85
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/StatisticStore.java65
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/ClusterId.java76
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultGraphDescription.java141
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyCluster.java97
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyEdge.java84
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyVertex.java66
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/GraphDescription.java57
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/LinkWeight.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathService.java51
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/Topology.java71
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyCluster.java51
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyEdge.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyEvent.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyGraph.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProvider.java30
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProviderRegistry.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProviderService.java37
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyService.java135
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyStore.java144
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyVertex.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractApiDocRegistrator.java53
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractInjectionResource.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractWebResource.java98
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/rest/ApiDocProvider.java98
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/rest/ApiDocService.java58
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/rest/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/security/AppGuard.java38
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/security/AppPermission.java110
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/security/Permission.java77
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/security/SecurityAdminService.java77
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/security/SecurityUtil.java82
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/security/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/AbstractStore.java72
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/Store.java51
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/StoreDelegate.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/Timestamp.java53
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterCommunicationService.java166
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessage.java160
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessageHandler.java28
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/Endpoint.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/MessageSubject.java68
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/MessagingService.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AsyncAtomicCounter.java61
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AsyncConsistentMap.java283
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicCounter.java59
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicCounterBuilder.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValue.java69
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueBuilder.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueEvent.java109
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueEventListener.java28
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMap.java291
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMapBuilder.java143
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMapException.java48
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DatabaseUpdate.java220
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedQueue.java62
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedQueueBuilder.java79
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedSet.java41
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedSetBuilder.java132
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMap.java207
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapBuilder.java187
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapEvent.java124
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapListener.java29
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/LogicalClockService.java35
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapEvent.java135
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapEventListener.java28
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapInfo.java47
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MultiValuedTimestamp.java111
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/PartitionInfo.java81
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Serializer.java81
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/SetEvent.java113
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/SetEventListener.java28
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageAdminService.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageException.java48
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageService.java83
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Transaction.java102
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContextBuilder.java47
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionException.java54
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionalMap.java93
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Versioned.java138
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/WallClockTimestamp.java85
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/package-info.java21
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/JsonUtils.java143
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/RequestHandler.java142
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiConnection.java42
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiExtension.java200
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiExtensionService.java53
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiMessageHandler.java207
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiMessageHandlerFactory.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java122
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlayFactory.java34
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiView.java165
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiViewHidden.java41
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/CellComparator.java46
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/CellFormatter.java34
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableModel.java304
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableRequestHandler.java111
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableUtils.java58
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AbstractCellComparator.java61
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AbstractCellFormatter.java42
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java41
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/ConnectPointFormatter.java41
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/DefaultCellComparator.java52
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/DefaultCellFormatter.java39
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/EnumFormatter.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/HexFormatter.java39
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/HostLocationFormatter.java41
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/TimeFormatter.java72
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/AbstractHighlight.java75
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BaseLink.java43
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BaseLinkMap.java31
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BiLink.java104
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BiLinkMap.java90
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/ButtonId.java70
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/DeviceHighlight.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/Highlights.java190
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/HostHighlight.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/LinkHighlight.java147
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/Mod.java66
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeHighlight.java27
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeSelection.java252
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/PropertyPanel.java353
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoConstants.java129
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoElementType.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java160
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoUtils.java159
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/package-info.java21
621 files changed, 52804 insertions, 0 deletions
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationAdminService.java
new file mode 100644
index 00000000..3713e218
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationAdminService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.security.Permission;
+
+import java.io.InputStream;
+import java.util.Set;
+
+/**
+ * Service for managing network control applications.
+ */
+public interface ApplicationAdminService extends ApplicationService {
+
+ /**
+ * Installs the application contained in the specified application archive
+ * input stream. This can be either a ZIP stream containing a compressed
+ * application archive or a plain XML stream containing just the
+ * {@code app.xml} application descriptor file.
+ *
+ * @param appDescStream application descriptor input stream
+ * @return installed application descriptor
+ * @throws org.onosproject.app.ApplicationException if unable to read the app archive stream
+ */
+ Application install(InputStream appDescStream);
+
+ /**
+ * Uninstalls the specified application.
+ *
+ * @param appId application identifier
+ */
+ void uninstall(ApplicationId appId);
+
+ /**
+ * Activates the specified application.
+ *
+ * @param appId application identifier
+ */
+ void activate(ApplicationId appId);
+
+ /**
+ * Deactivates the specified application.
+ *
+ * @param appId application identifier
+ */
+ void deactivate(ApplicationId appId);
+
+ /**
+ * Updates the permissions granted to the applications.
+ *
+ * @param appId application identifier
+ * @param permissions set of granted permissions
+ */
+ void setPermissions(ApplicationId appId, Set<Permission> permissions);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java
new file mode 100644
index 00000000..2561280b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+import org.onosproject.core.ApplicationRole;
+import org.onosproject.core.Version;
+import org.onosproject.security.Permission;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Description of a network control/management application.
+ */
+public interface ApplicationDescription {
+
+ /**
+ * Returns the application name id.
+ *
+ * @return application identifier
+ */
+ String name();
+
+ /**
+ * Returns the application version.
+ *
+ * @return application version
+ */
+ Version version();
+
+ /**
+ * Returns description of the application.
+ *
+ * @return application description text
+ */
+ String description();
+
+ /**
+ * Returns the name of the application origin, group or company.
+ *
+ * @return application origin
+ */
+ String origin();
+
+ /**
+ * Returns the role of the application.
+ *
+ * @return application role
+ */
+ ApplicationRole role();
+
+ /**
+ * Returns the permissions requested by the application.
+ *
+ * @return requested permissions
+ */
+ Set<Permission> permissions();
+
+ /**
+ * Returns the feature repository URI. Null value signifies that the
+ * application did not provide its own features repository.
+ *
+ * @return optional feature repo URL
+ */
+ Optional<URI> featuresRepo();
+
+ /**
+ * Returns the list of features comprising the application. At least one
+ * feature must be given.
+ *
+ * @return application features
+ */
+ List<String> features();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationEvent.java
new file mode 100644
index 00000000..5bf1323d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationEvent.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes application lifecycle event.
+ */
+public class ApplicationEvent extends AbstractEvent<ApplicationEvent.Type, Application> {
+
+ public enum Type {
+ /**
+ * Signifies that an application has been installed.
+ */
+ APP_INSTALLED,
+
+ /**
+ * Signifies that an application has been activated.
+ */
+ APP_ACTIVATED,
+
+ /**
+ * Signifies that an application has been deactivated.
+ */
+ APP_DEACTIVATED,
+
+ /**
+ * Signifies that an application has been uninstalled.
+ */
+ APP_UNINSTALLED,
+
+ /**
+ * Signifies that application granted permissions have changed.
+ */
+ APP_PERMISSIONS_CHANGED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified app and the
+ * current time.
+ *
+ * @param type app event type
+ * @param app event app subject
+ */
+ public ApplicationEvent(Type type, Application app) {
+ super(type, app);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified app and time.
+ *
+ * @param type app event type
+ * @param app event app subject
+ * @param time occurrence time
+ */
+ public ApplicationEvent(Type type, Application app, long time) {
+ super(type, app, time);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationException.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationException.java
new file mode 100644
index 00000000..2888c70b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationException.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+/**
+ * Represents class of errors related to application management.
+ */
+public class ApplicationException extends RuntimeException {
+
+ private static final long serialVersionUID = -2287403908433720122L;
+
+ /**
+ * Constructs an exception with no message and no underlying cause.
+ */
+ public ApplicationException() {
+ }
+
+ /**
+ * Constructs an exception with the specified message.
+ *
+ * @param message the message describing the specific nature of the error
+ */
+ public ApplicationException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception with the specified message and the underlying cause.
+ *
+ * @param message the message describing the specific nature of the error
+ * @param cause the underlying cause of this error
+ */
+ public ApplicationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationListener.java
new file mode 100644
index 00000000..7a680572
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving application related events.
+ */
+public interface ApplicationListener extends EventListener<ApplicationEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationService.java
new file mode 100644
index 00000000..73dcc86c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.event.ListenerService;
+import org.onosproject.security.Permission;
+
+import java.util.Set;
+
+/**
+ * Service for inspecting inventory of network control applications.
+ */
+public interface ApplicationService
+ extends ListenerService<ApplicationEvent, ApplicationListener> {
+
+ /**
+ * Returns the set of all installed applications.
+ *
+ * @return set of installed apps
+ */
+ Set<Application> getApplications();
+
+ /**
+ * Returns the registered id of the application with the given name.
+ *
+ * @param name application name
+ * @return registered application id
+ */
+ ApplicationId getId(String name);
+
+ /**
+ * Returns the application with the supplied application identifier.
+ *
+ * @param appId application identifier
+ * @return application descriptor
+ */
+ Application getApplication(ApplicationId appId);
+
+ /**
+ * Return the application state.
+ *
+ * @param appId application identifier
+ * @return application state
+ */
+ ApplicationState getState(ApplicationId appId);
+
+ /**
+ * Returns the permissions currently granted to the applications.
+ *
+ * @param appId application identifier
+ * @return set of granted permissions
+ */
+ Set<Permission> getPermissions(ApplicationId appId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationState.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationState.java
new file mode 100644
index 00000000..c480a0c7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationState.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+/**
+ * Representation of an application state.
+ */
+public enum ApplicationState {
+
+ /**
+ * Indicates that application has been installed, but is not running.
+ */
+ INSTALLED,
+
+ /**
+ * Indicates that application is active.
+ */
+ ACTIVE
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStore.java
new file mode 100644
index 00000000..b3cdc43e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStore.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.security.Permission;
+import org.onosproject.store.Store;
+
+import java.io.InputStream;
+import java.util.Set;
+
+/**
+ * Service for managing network control applications.
+ */
+public interface ApplicationStore extends Store<ApplicationEvent, ApplicationStoreDelegate> {
+
+ /**
+ * Returns the set of all installed applications.
+ *
+ * @return set of installed apps
+ */
+ Set<Application> getApplications();
+
+ /**
+ * Returns the registered id of the application with the given name.
+ *
+ * @param name application name
+ * @return registered application id
+ */
+ ApplicationId getId(String name);
+
+ /**
+ * Returns the application with the supplied application identifier.
+ *
+ * @param appId application identifier
+ * @return application descriptor
+ */
+ Application getApplication(ApplicationId appId);
+
+ /**
+ * Returns the current application state.
+ *
+ * @param appId application identifier
+ * @return application state
+ */
+ ApplicationState getState(ApplicationId appId);
+
+ /**
+ * Creates the application from the specified application descriptor
+ * input stream.
+ *
+ * @param appDescStream application archive input stream
+ * @return application descriptor
+ */
+ Application create(InputStream appDescStream);
+
+ /**
+ * Removes the specified application.
+ *
+ * @param appId application identifier
+ */
+ void remove(ApplicationId appId);
+
+ /**
+ * Mark the application as actived.
+ *
+ * @param appId application identifier
+ */
+ void activate(ApplicationId appId);
+
+ /**
+ * Mark the application as deactivated.
+ *
+ * @param appId application identifier
+ */
+ void deactivate(ApplicationId appId);
+
+ /**
+ * Returns the permissions granted to the applications.
+ *
+ * @param appId application identifier
+ * @return set of granted permissions
+ */
+ Set<Permission> getPermissions(ApplicationId appId);
+
+ /**
+ * Updates the permissions granted to the applications.
+ *
+ * @param appId application identifier
+ * @param permissions set of granted permissions
+ */
+ void setPermissions(ApplicationId appId, Set<Permission> permissions);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStoreDelegate.java
new file mode 100644
index 00000000..f339e685
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Application store delegate abstraction.
+ */
+public interface ApplicationStoreDelegate extends StoreDelegate<ApplicationEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java
new file mode 100644
index 00000000..710d0f9c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.app;
+
+import org.onosproject.core.ApplicationRole;
+import org.onosproject.core.Version;
+import org.onosproject.security.Permission;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of network control/management application descriptor.
+ */
+public class DefaultApplicationDescription implements ApplicationDescription {
+
+ private final String name;
+ private final Version version;
+ private final String description;
+ private final String origin;
+ private final ApplicationRole role;
+ private final Set<Permission> permissions;
+ private final Optional<URI> featuresRepo;
+ private final List<String> features;
+
+ /**
+ * Creates a new application descriptor using the supplied data.
+ *
+ * @param name application name
+ * @param version application version
+ * @param description application description
+ * @param origin origin company
+ * @param role application role
+ * @param permissions requested permissions
+ * @param featuresRepo optional features repo URI
+ * @param features application features
+ */
+ public DefaultApplicationDescription(String name, Version version,
+ String description, String origin,
+ ApplicationRole role, Set<Permission> permissions,
+ URI featuresRepo, List<String> features) {
+ this.name = checkNotNull(name, "Name cannot be null");
+ this.version = checkNotNull(version, "Version cannot be null");
+ this.description = checkNotNull(description, "Description cannot be null");
+ this.origin = checkNotNull(origin, "Origin cannot be null");
+ this.role = checkNotNull(role, "Role cannot be null");
+ this.permissions = checkNotNull(permissions, "Permissions cannot be null");
+ this.featuresRepo = Optional.ofNullable(featuresRepo);
+ this.features = checkNotNull(features, "Features cannot be null");
+ checkArgument(!features.isEmpty(), "There must be at least one feature");
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public Version version() {
+ return version;
+ }
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public String origin() {
+ return origin;
+ }
+
+ @Override
+ public ApplicationRole role() {
+ return role;
+ }
+
+ @Override
+ public Set<Permission> permissions() {
+ return permissions;
+ }
+
+ @Override
+ public Optional<URI> featuresRepo() {
+ return featuresRepo;
+ }
+
+ @Override
+ public List<String> features() {
+ return features;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("name", name)
+ .add("version", version)
+ .add("description", description)
+ .add("origin", origin)
+ .add("role", role)
+ .add("permissions", permissions)
+ .add("featuresRepo", featuresRepo)
+ .add("features", features)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/package-info.java
new file mode 100644
index 00000000..f8e5465d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Set of abstractions for managing network control applications.
+ */
+package org.onosproject.app; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigEvent.java
new file mode 100644
index 00000000..0f5a2ee5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigEvent.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes a component configuration event.
+ */
+public class ComponentConfigEvent extends AbstractEvent<ComponentConfigEvent.Type, String> {
+
+ private final String name;
+ private final String value;
+
+ public enum Type {
+ /**
+ * Signifies that a configuration property has set.
+ */
+ PROPERTY_SET,
+
+ /**
+ * Signifies that a configuration property has been unset.
+ */
+ PROPERTY_UNSET
+ }
+
+ /**
+ * Creates an event of a given type and for the specified app and the
+ * current time.
+ *
+ * @param type config property event type
+ * @param componentName component name event subject
+ * @param name config property name
+ * @param value config property value
+ */
+ public ComponentConfigEvent(Type type, String componentName,
+ String name, String value) {
+ super(type, componentName);
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * Returns the property name.
+ *
+ * @return property name
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the property value as a string.
+ *
+ * @return string value
+ */
+ public String value() {
+ return value;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigService.java
new file mode 100644
index 00000000..a311002f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigService.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import java.util.Set;
+
+/**
+ * Service for tracking system-wide configurations for various software components.
+ */
+public interface ComponentConfigService {
+
+ /**
+ * Returns names of all components that have registered their
+ * configuration properties.
+ *
+ * @return set of component names
+ */
+ Set<String> getComponentNames();
+
+ /**
+ * Registers configuration properties for the specified component.
+ *
+ * @param componentClass class of configurable component
+ */
+ void registerProperties(Class<?> componentClass);
+
+ /**
+ * Unregisters configuration properties for the specified component.
+ *
+ * @param componentClass class of configurable component
+ * @param clear true indicates any settings should be cleared
+ */
+ void unregisterProperties(Class<?> componentClass, boolean clear);
+
+ /**
+ * Returns configuration properties of the named components.
+ *
+ * @param componentName component name
+ * @return set of configuration properties
+ */
+ Set<ConfigProperty> getProperties(String componentName);
+
+ /**
+ * Sets the value of the specified configuration property.
+ *
+ * @param componentName component name
+ * @param name property name
+ * @param value new property value
+ */
+ void setProperty(String componentName, String name, String value);
+
+ /**
+ * Clears the value of the specified configuration property thus making
+ * the property take on its default value.
+ *
+ * @param componentName component name
+ * @param name property name
+ */
+ void unsetProperty(String componentName, String name);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStore.java
new file mode 100644
index 00000000..05f58a4c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStore.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import org.onosproject.store.Store;
+
+/**
+ * Service for storing and distributing system-wide configurations for various
+ * software components.
+ */
+public interface ComponentConfigStore
+ extends Store<ComponentConfigEvent, ComponentConfigStoreDelegate> {
+
+ /**
+ * Sets the value of the specified configuration property.
+ *
+ * @param componentName component name
+ * @param name property name
+ * @param value new property value
+ */
+ void setProperty(String componentName, String name, String value);
+
+ /**
+ * Clears the value of the specified configuration property thus making
+ * the property take on its default value.
+ *
+ * @param componentName component name
+ * @param name property name
+ */
+ void unsetProperty(String componentName, String name);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStoreDelegate.java
new file mode 100644
index 00000000..da262789
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Configuration property store delegate abstraction.
+ */
+public interface ComponentConfigStoreDelegate extends StoreDelegate<ComponentConfigEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java
new file mode 100644
index 00000000..36cd22b5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Component configuration property.
+ */
+public final class ConfigProperty {
+
+ private final String name;
+ private final Type type;
+ private final String value;
+ private final String defaultValue;
+ private final String description;
+ private final boolean isSet;
+
+ /**
+ * Representation of the type of property value.
+ */
+ public enum Type {
+ /**
+ * Indicates the value is a string.
+ */
+ STRING,
+
+ /**
+ * Indicates the value is an integer.
+ */
+ INTEGER,
+
+ /**
+ * Indicates the value is a long.
+ */
+ LONG,
+
+ /**
+ * Indicates the value is a float.
+ */
+ FLOAT,
+
+ /**
+ * Indicates the value is a double.
+ */
+ DOUBLE,
+
+ /**
+ * Indicates the value is a boolean.
+ */
+ BOOLEAN
+ }
+
+ /**
+ * Creates a new configuration property with its default value.
+ *
+ * @param name property name
+ * @param type value type
+ * @param defaultValue default value as a string
+ * @param description property description
+ * @return newly defined property
+ */
+ public static ConfigProperty defineProperty(String name, Type type,
+ String defaultValue,
+ String description) {
+ return new ConfigProperty(name, type, description, defaultValue, defaultValue, false);
+ }
+
+ /**
+ * Creates a new configuration property as a copy of an existing one, but
+ * with a new value.
+ *
+ * @param property property to be changed
+ * @param newValue new value as a string
+ * @return newly updated property
+ */
+ public static ConfigProperty setProperty(ConfigProperty property, String newValue) {
+ return new ConfigProperty(property.name, property.type, property.description,
+ property.defaultValue, newValue, true);
+ }
+
+ /**
+ * Creates a new configuration property as a copy of an existing one, but
+ * without a specific value, thus making it take its default value.
+ *
+ * @param property property to be reset
+ * @return newly reset property
+ */
+ public static ConfigProperty resetProperty(ConfigProperty property) {
+ return new ConfigProperty(property.name, property.type, property.description,
+ property.defaultValue, property.defaultValue, false);
+ }
+
+ /**
+ * Creates a new configuration property with its default value.
+ *
+ * @param name property name
+ * @param type value type
+ * @param defaultValue default value as a string
+ * @param description property description
+ * @param value property value
+ * @param isSet indicates whether the property is set or not
+ */
+ private ConfigProperty(String name, Type type, String description,
+ String defaultValue, String value, boolean isSet) {
+ this.name = checkNotNull(name, "Property name cannot be null");
+ this.type = checkNotNull(type, "Property type cannot be null");
+ this.description = checkNotNull(description, "Property description cannot be null");
+ this.defaultValue = defaultValue;
+ this.value = value;
+ this.isSet = isSet;
+ }
+
+ /**
+ * Returns the property name.
+ *
+ * @return property name
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the property type.
+ *
+ * @return property type
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the property description.
+ *
+ * @return string value
+ */
+ public String description() {
+ return description;
+ }
+
+ /**
+ * Returns the property default value as a string.
+ *
+ * @return string default value
+ */
+ public String defaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * Returns the property value as a string.
+ *
+ * @return string value
+ */
+ public String value() {
+ return value;
+ }
+
+ /**
+ * Indicates whether the property is set or whether it assumes its
+ * default value.
+ *
+ * @return true if the property is set
+ */
+ public boolean isSet() {
+ return isSet;
+ }
+
+ /**
+ * Returns the property value as a string.
+ *
+ * @return string value
+ */
+ public String asString() {
+ return value;
+ }
+
+ /**
+ * Returns the property value as an integer.
+ *
+ * @return integer value
+ */
+ public int asInteger() {
+ checkState(type == Type.INTEGER, "Value is not an integer");
+ return Integer.parseInt(value);
+ }
+
+ /**
+ * Returns the property value as a long.
+ *
+ * @return long value
+ */
+ public long asLong() {
+ checkState(type == Type.INTEGER || type == Type.LONG, "Value is not a long or integer");
+ return Long.parseLong(value);
+ }
+
+ /**
+ * Returns the property value as a float.
+ *
+ * @return float value
+ */
+ public float asFloat() {
+ checkState(type == Type.FLOAT, "Value is not a float");
+ return Float.parseFloat(value);
+ }
+
+ /**
+ * Returns the property value as a double.
+ *
+ * @return double value
+ */
+ public double asDouble() {
+ checkState(type == Type.FLOAT || type == Type.DOUBLE, "Value is not a float or double");
+ return Double.parseDouble(value);
+ }
+
+ /**
+ * Returns the property value as a boolean.
+ *
+ * @return string value
+ */
+ public boolean asBoolean() {
+ checkState(type == Type.BOOLEAN, "Value is not a boolean");
+ return Boolean.parseBoolean(value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Equality is considered only on the basis of property name.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ConfigProperty) {
+ final ConfigProperty other = (ConfigProperty) obj;
+ return Objects.equals(this.name, other.name);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("name", name)
+ .add("type", type)
+ .add("value", value)
+ .add("defaultValue", defaultValue)
+ .add("description", description)
+ .add("isSet", isSet)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/package-info.java
new file mode 100644
index 00000000..99fd5be4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Set of abstractions for centrally managing component configurations.
+ * Configuration properties are registered for a component resource which is
+ * auto-generated during the build process based on information specified in
+ * the @Property annotations. This provides an overall inventory of all
+ * supported component configurations.
+ */
+package org.onosproject.cfg; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
new file mode 100644
index 00000000..5f2b5fff
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onlab.packet.IpAddress;
+
+import java.util.Set;
+
+/**
+ * Service for administering the cluster node membership.
+ */
+public interface ClusterAdminService {
+
+ /**
+ * Forms cluster configuration based on the specified set of node
+ * information.&nbsp; This method resets and restarts the controller
+ * instance.
+ *
+ * @param nodes set of nodes that form the cluster
+ * @param ipPrefix IP address prefix, e.g. 10.0.1.*
+ */
+ void formCluster(Set<ControllerNode> nodes, String ipPrefix);
+
+ /**
+ * Adds a new controller node to the cluster.
+ *
+ * @param nodeId controller node identifier
+ * @param ip node IP listen address
+ * @param tcpPort tcp listen port
+ * @return newly added node
+ */
+ ControllerNode addNode(NodeId nodeId, IpAddress ip, int tcpPort);
+
+ /**
+ * Removes the specified node from the cluster node list.
+ *
+ * @param nodeId controller node identifier
+ */
+ void removeNode(NodeId nodeId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java
new file mode 100644
index 00000000..dbe5f71c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java
@@ -0,0 +1,32 @@
+package org.onosproject.cluster;
+
+import java.util.Set;
+
+/**
+ * Service for obtaining the static definition of a controller cluster.
+ */
+public interface ClusterDefinitionService {
+
+ /**
+ * Returns the local controller node.
+ * @return local controller node
+ */
+ ControllerNode localNode();
+
+ /**
+ * Returns the set of seed nodes that should be used for discovering other members
+ * of the cluster.
+ * @return set of seed controller nodes
+ */
+ Set<ControllerNode> seedNodes();
+
+ /**
+ * Forms cluster configuration based on the specified set of node
+ * information. Assumes subsequent restart for the new configuration to
+ * take hold.
+ *
+ * @param nodes set of nodes that form the cluster
+ * @param ipPrefix IP address prefix, e.g. 10.0.1.*
+ */
+ void formCluster(Set<ControllerNode> nodes, String ipPrefix);
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterEvent.java
new file mode 100644
index 00000000..7bdc1d7d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterEvent.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes cluster-related event.
+ */
+public class ClusterEvent extends AbstractEvent<ClusterEvent.Type, ControllerNode> {
+
+ /**
+ * Type of cluster-related events.
+ */
+ public enum Type {
+ /**
+ * Signifies that a new cluster instance has been administratively added.
+ */
+ INSTANCE_ADDED,
+
+ /**
+ * Signifies that a cluster instance has been administratively removed.
+ */
+ INSTANCE_REMOVED,
+
+ /**
+ * Signifies that a cluster instance became active.
+ */
+ INSTANCE_ACTIVATED,
+
+ /**
+ * Signifies that a cluster instance became inactive.
+ */
+ INSTANCE_DEACTIVATED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified instance and the
+ * current time.
+ *
+ * @param type cluster event type
+ * @param instance cluster device subject
+ */
+ public ClusterEvent(Type type, ControllerNode instance) {
+ super(type, instance);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified device and time.
+ *
+ * @param type device event type
+ * @param instance event device subject
+ * @param time occurrence time
+ */
+ public ClusterEvent(Type type, ControllerNode instance, long time) {
+ super(type, instance, time);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterEventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterEventListener.java
new file mode 100644
index 00000000..79ff06ec
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterEventListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving device cluster-related events.
+ */
+public interface ClusterEventListener extends EventListener<ClusterEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterService.java
new file mode 100644
index 00000000..015a6482
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterService.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import java.util.Set;
+
+import org.joda.time.DateTime;
+import org.onosproject.event.ListenerService;
+
+/**
+ * Service for obtaining information about the individual nodes within
+ * the controller cluster.
+ */
+public interface ClusterService
+ extends ListenerService<ClusterEvent, ClusterEventListener> {
+
+ /**
+ * Returns the local controller node.
+ *
+ * @return local controller node
+ */
+ ControllerNode getLocalNode();
+
+ /**
+ * Returns the set of current cluster members.
+ *
+ * @return set of cluster members
+ */
+ Set<ControllerNode> getNodes();
+
+ /**
+ * Returns the specified controller node.
+ *
+ * @param nodeId controller node identifier
+ * @return controller node
+ */
+ ControllerNode getNode(NodeId nodeId);
+
+ /**
+ * Returns the availability state of the specified controller node.
+ *
+ * @param nodeId controller node identifier
+ * @return availability state
+ */
+ ControllerNode.State getState(NodeId nodeId);
+
+ /**
+ * Returns the system time when the availability state was last updated.
+ *
+ * @param nodeId controller node identifier
+ * @return system time when the availability state was last updated.
+ */
+ DateTime getLastUpdated(NodeId nodeId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterStore.java
new file mode 100644
index 00000000..0481d510
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterStore.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.joda.time.DateTime;
+import org.onlab.packet.IpAddress;
+import org.onosproject.store.Store;
+
+import java.util.Set;
+
+/**
+ * Manages inventory of controller cluster nodes; not intended for direct use.
+ */
+public interface ClusterStore extends Store<ClusterEvent, ClusterStoreDelegate> {
+
+ /**
+ * Returns the local controller node.
+ *
+ * @return local controller instance
+ */
+ ControllerNode getLocalNode();
+
+ /**
+ * Returns the set of current cluster members.
+ *
+ * @return set of cluster members
+ */
+ Set<ControllerNode> getNodes();
+
+ /**
+ * Returns the specified controller node.
+ *
+ * @param nodeId controller instance identifier
+ * @return controller instance
+ */
+ ControllerNode getNode(NodeId nodeId);
+
+ /**
+ * Returns the availability state of the specified controller node.
+ *
+ * @param nodeId controller instance identifier
+ * @return availability state
+ */
+ ControllerNode.State getState(NodeId nodeId);
+
+ /**
+ * Returns the system when the availability state was last updated.
+ *
+ * @param nodeId controller node identifier
+ * @return system time when the availability state was last updated.
+ */
+ DateTime getLastUpdated(NodeId nodeId);
+
+ /**
+ * Adds a new controller node to the cluster.
+ *
+ * @param nodeId controller node identifier
+ * @param ip node IP listen address
+ * @param tcpPort tcp listen port
+ * @return newly added node
+ */
+ ControllerNode addNode(NodeId nodeId, IpAddress ip, int tcpPort);
+
+ /**
+ * Removes the specified node from the inventory of cluster nodes.
+ *
+ * @param nodeId controller instance identifier
+ */
+ void removeNode(NodeId nodeId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterStoreDelegate.java
new file mode 100644
index 00000000..50d44305
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Cluster store delegate abstraction.
+ */
+public interface ClusterStoreDelegate extends StoreDelegate<ClusterEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ControllerNode.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ControllerNode.java
new file mode 100644
index 00000000..3cfc9367
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ControllerNode.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onlab.packet.IpAddress;
+
+/**
+ * Represents a controller instance as a member in a cluster.
+ */
+public interface ControllerNode {
+
+ /** Represents the operational state of the instance. */
+ public enum State {
+ /**
+ * Signifies that the instance is active and operating normally.
+ */
+ ACTIVE,
+
+ /**
+ * Signifies that the instance is inactive, which means either down or
+ * up, but not operational.
+ */
+ INACTIVE
+ }
+
+ /**
+ * Returns the instance identifier.
+ *
+ * @return instance identifier
+ */
+ NodeId id();
+
+ /**
+ * Returns the IP address of the controller instance.
+ *
+ * @return IP address
+ */
+ IpAddress ip();
+
+
+ /**
+ * Returns the TCP port on which the node listens for connections.
+ *
+ * @return TCP port
+ */
+ int tcpPort();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ControllerNodeToNodeId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ControllerNodeToNodeId.java
new file mode 100644
index 00000000..4cde8b29
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ControllerNodeToNodeId.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import com.google.common.base.Function;
+
+/**
+ * Function to convert ControllerNode to NodeId.
+ */
+public final class ControllerNodeToNodeId
+ implements Function<ControllerNode, NodeId> {
+
+ private static final ControllerNodeToNodeId INSTANCE = new ControllerNodeToNodeId();
+
+ @Override
+ public NodeId apply(ControllerNode input) {
+ if (input == null) {
+ return null;
+ } else {
+ return input.id();
+ }
+ }
+
+ /**
+ * Returns a Function to convert ControllerNode to NodeId.
+ *
+ * @return ControllerNodeToNodeId instance.
+ */
+ public static ControllerNodeToNodeId toNodeId() {
+ return INSTANCE;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/DefaultControllerNode.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/DefaultControllerNode.java
new file mode 100644
index 00000000..5f3e0e19
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/DefaultControllerNode.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onlab.packet.IpAddress;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of a controller instance descriptor.
+ */
+public class DefaultControllerNode implements ControllerNode {
+
+ public static final int DEFAULT_PORT = 9876;
+
+ private final NodeId id;
+ private final IpAddress ip;
+ private final int tcpPort;
+
+ // For serialization
+ private DefaultControllerNode() {
+ this.id = null;
+ this.ip = null;
+ this.tcpPort = 0;
+ }
+
+ /**
+ * Creates a new instance with the specified id and IP address.
+ *
+ * @param id instance identifier
+ * @param ip instance IP address
+ */
+ public DefaultControllerNode(NodeId id, IpAddress ip) {
+ this(id, ip, DEFAULT_PORT);
+ }
+
+ /**
+ * Creates a new instance with the specified id and IP address and TCP port.
+ *
+ * @param id instance identifier
+ * @param ip instance IP address
+ * @param tcpPort TCP port
+ */
+ public DefaultControllerNode(NodeId id, IpAddress ip, int tcpPort) {
+ this.id = id;
+ this.ip = ip;
+ this.tcpPort = tcpPort;
+ }
+
+ @Override
+ public NodeId id() {
+ return id;
+ }
+
+ @Override
+ public IpAddress ip() {
+ return ip;
+ }
+
+ @Override
+ public int tcpPort() {
+ return tcpPort;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o instanceof DefaultControllerNode) {
+ DefaultControllerNode that = (DefaultControllerNode) o;
+ return Objects.equals(this.id, that.id);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("id", id)
+ .add("ip", ip).add("tcpPort", tcpPort).toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Leadership.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Leadership.java
new file mode 100644
index 00000000..113e19cb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Leadership.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import java.util.Objects;
+import java.util.List;
+import java.util.Optional;
+
+import org.joda.time.DateTime;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Abstract leadership concept. The information carried by this construct
+ * include the topic of contention, the {@link NodeId}s of Nodes that could
+ * become leader for the topic, the epoch when the term for a given leader
+ * began, and the system time when the term began. Note:
+ * <ul>
+ * <li>The list of NodeIds may include the current leader at index 0, and the
+ * rest in decreasing preference order.</li>
+ * <li>The epoch is the logical age of a Leadership construct, and should be
+ * used for comparing two Leaderships, but only of the same topic.</li>
+ * <li>The leader may be null if its accuracy can't be guaranteed. This applies
+ * to CANDIDATES_CHANGED events and candidate board contents.</li>
+ * </ul>
+ */
+public class Leadership {
+
+ private final String topic;
+ private final Optional<NodeId> leader;
+ private final List<NodeId> candidates;
+ private final long epoch;
+ private final long electedTime;
+
+ public Leadership(String topic, NodeId leader, long epoch, long electedTime) {
+ this.topic = topic;
+ this.leader = Optional.of(leader);
+ this.candidates = ImmutableList.of(leader);
+ this.epoch = epoch;
+ this.electedTime = electedTime;
+ }
+
+ public Leadership(String topic, NodeId leader, List<NodeId> candidates,
+ long epoch, long electedTime) {
+ this.topic = topic;
+ this.leader = Optional.of(leader);
+ this.candidates = ImmutableList.copyOf(candidates);
+ this.epoch = epoch;
+ this.electedTime = electedTime;
+ }
+
+ public Leadership(String topic, List<NodeId> candidates,
+ long epoch, long electedTime) {
+ this.topic = topic;
+ this.leader = Optional.empty();
+ this.candidates = ImmutableList.copyOf(candidates);
+ this.epoch = epoch;
+ this.electedTime = electedTime;
+ }
+
+ /**
+ * The topic for which this leadership applies.
+ *
+ * @return leadership topic.
+ */
+ public String topic() {
+ return topic;
+ }
+
+ /**
+ * The nodeId of leader for this topic.
+ *
+ * @return leader node.
+ */
+ // This will return Optional<NodeId> in the future.
+ public NodeId leader() {
+ return leader.orElse(null);
+ }
+
+ /**
+ * Returns an preference-ordered list of nodes that are in the leadership
+ * race for this topic.
+ *
+ * @return a list of NodeIds in priority-order, or an empty list.
+ */
+ public List<NodeId> candidates() {
+ return candidates;
+ }
+
+ /**
+ * The epoch when the leadership was assumed.
+ * <p>
+ * Comparing epochs is only appropriate for leadership events for the same
+ * topic. The system guarantees that for any given topic the epoch for a new
+ * term is higher (not necessarily by 1) than the epoch for any previous
+ * term.
+ *
+ * @return leadership epoch
+ */
+ public long epoch() {
+ return epoch;
+ }
+
+ /**
+ * The system time when the term started.
+ * <p>
+ * The elected time is initially set on the node coordinating
+ * the leader election using its local system time. Due to possible
+ * clock skew, relying on this value for determining event ordering
+ * is discouraged. Epoch is more appropriate for determining
+ * event ordering.
+ *
+ * @return elected time.
+ */
+ public long electedTime() {
+ return electedTime;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(topic, leader, candidates, epoch, electedTime);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Leadership) {
+ final Leadership other = (Leadership) obj;
+ return Objects.equals(this.topic, other.topic) &&
+ Objects.equals(this.leader, other.leader) &&
+ Objects.equals(this.candidates, other.candidates) &&
+ Objects.equals(this.epoch, other.epoch) &&
+ Objects.equals(this.electedTime, other.electedTime);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this.getClass())
+ .add("topic", topic)
+ .add("leader", leader)
+ .add("candidates", candidates)
+ .add("epoch", epoch)
+ .add("electedTime", new DateTime(electedTime))
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipEvent.java
new file mode 100644
index 00000000..faf6dd45
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipEvent.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import java.util.Objects;
+
+import org.onosproject.event.AbstractEvent;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Describes leadership-related event.
+ */
+public class LeadershipEvent extends AbstractEvent<LeadershipEvent.Type, Leadership> {
+
+ /**
+ * Type of leadership-related events.
+ */
+ public enum Type {
+ /**
+ * Signifies that the leader has been elected. The event subject is the
+ * new leader.
+ */
+ LEADER_ELECTED,
+
+ /**
+ * Signifies that the leader has been re-elected. The event subject is the
+ * leader.
+ */
+ LEADER_REELECTED,
+
+ /**
+ * Signifies that the leader has been booted and lost leadership. The
+ * event subject is the former leader.
+ */
+ LEADER_BOOTED,
+
+ /**
+ * Signifies that the list of candidates for leadership for a topic has
+ * changed. This event does not guarantee accurate leader information.
+ */
+ CANDIDATES_CHANGED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified instance and the
+ * current time.
+ *
+ * @param type leadership event type
+ * @param leadership event subject
+ */
+ public LeadershipEvent(Type type, Leadership leadership) {
+ super(type, leadership);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject and time.
+ *
+ * @param type leadership event type
+ * @param leadership event subject
+ * @param time occurrence time
+ */
+ public LeadershipEvent(Type type, Leadership leadership, long time) {
+ super(type, leadership, time);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subject(), time());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof LeadershipEvent) {
+ final LeadershipEvent other = (LeadershipEvent) obj;
+ return Objects.equals(this.type(), other.type()) &&
+ Objects.equals(this.subject(), other.subject()) &&
+ Objects.equals(this.time(), other.time());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this.getClass())
+ .add("type", type())
+ .add("subject", subject())
+ .add("time", time())
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipEventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipEventListener.java
new file mode 100644
index 00000000..53d84b1b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipEventListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving device leadership-related events.
+ */
+public interface LeadershipEventListener extends EventListener<LeadershipEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipService.java
new file mode 100644
index 00000000..7d1f6079
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/LeadershipService.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onosproject.event.ListenerService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Service for leader election.
+ * Leadership contests are organized around topics. A instance can join the
+ * leadership race for a topic or withdraw from a race it has previously joined.
+ * Listeners can be added to receive notifications asynchronously for various
+ * leadership contests.
+ */
+public interface LeadershipService
+ extends ListenerService<LeadershipEvent, LeadershipEventListener> {
+
+ /**
+ * Returns the current leader for the topic.
+ *
+ * @param path topic
+ * @return nodeId of the leader, null if so such topic exists.
+ */
+ NodeId getLeader(String path);
+
+ /**
+ * Returns the current leadership info for the topic.
+ *
+ * @param path topic
+ * @return leadership info or null if so such topic exists.
+ */
+ Leadership getLeadership(String path);
+
+ /**
+ * Returns the set of topics owned by the specified node.
+ *
+ * @param nodeId node Id.
+ * @return set of topics for which this node is the current leader.
+ */
+ Set<String> ownedTopics(NodeId nodeId);
+
+ /**
+ * Joins the leadership contest.
+ *
+ * @param path topic for which this controller node wishes to be a leader
+ * @return {@code Leadership} future
+ */
+ CompletableFuture<Leadership> runForLeadership(String path);
+
+ /**
+ * Withdraws from a leadership contest.
+ *
+ * @param path topic for which this controller node no longer wishes to be a leader
+ * @return future that is successfully completed when withdraw is done
+ */
+ CompletableFuture<Void> withdraw(String path);
+
+ /**
+ * If the local nodeId is the leader for specified topic, this method causes it to
+ * step down temporarily from leadership.
+ * <p>
+ * The node will continue to be in contention for leadership and can
+ * potentially become the leader again if and when it becomes the highest
+ * priority candidate
+ * <p>
+ * If the local nodeId is not the leader, this method will make no changes and
+ * simply return false.
+ *
+ * @param path topic for which this controller node should give up leadership
+ * @return true if this node stepped down from leadership, false otherwise
+ */
+ boolean stepdown(String path);
+
+ /**
+ * Moves the specified nodeId to the top of the candidates list for the topic.
+ * <p>
+ * If the node is not a candidate for this topic, this method will be a noop.
+ *
+ * @param path leadership topic
+ * @param nodeId nodeId to make the top candidate
+ * @return true if nodeId is now the top candidate, false otherwise
+ */
+ boolean makeTopCandidate(String path, NodeId nodeId);
+
+ /**
+ * Returns the current leader board.
+ *
+ * @return mapping from topic to leadership info.
+ */
+ Map<String, Leadership> getLeaderBoard();
+
+ /**
+ * Returns the candidates for all known topics.
+ *
+ * @return A mapping from topics to corresponding list of candidates.
+ */
+ Map<String, List<NodeId>> getCandidates();
+
+ /**
+ * Returns the candidates for a given topic.
+ *
+ * @param path topic
+ * @return A lists of NodeIds, which may be empty.
+ */
+ List<NodeId> getCandidates(String path);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java
new file mode 100644
index 00000000..68b490f2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import java.util.Objects;
+
+/**
+ * Controller cluster identity.
+ */
+public class NodeId {
+
+ private final String id;
+
+ /**
+ * Creates a new cluster node identifier from the specified string.
+ *
+ * @param id string identifier
+ */
+ public NodeId(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NodeId) {
+ final NodeId other = (NodeId) obj;
+ return Objects.equals(this.id, other.id);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return id;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/RoleInfo.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/RoleInfo.java
new file mode 100644
index 00000000..081a6ba2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/RoleInfo.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * An immutable container for role information for a device,
+ * within the current cluster. Role attributes include current
+ * master and a preference-ordered list of backup nodes.
+ */
+public class RoleInfo {
+ private final Optional<NodeId> master;
+ private final List<NodeId> backups;
+
+ public RoleInfo(NodeId master, List<NodeId> backups) {
+ this.master = Optional.ofNullable(master);
+ this.backups = ImmutableList.copyOf(backups);
+ }
+
+ public RoleInfo() {
+ this.master = Optional.empty();
+ this.backups = ImmutableList.of();
+ }
+
+ // This will return a Optional<NodeId> in the future.
+ public NodeId master() {
+ return master.orElseGet(() -> null);
+ }
+
+ public List<NodeId> backups() {
+ return backups;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof RoleInfo)) {
+ return false;
+ }
+ RoleInfo that = (RoleInfo) other;
+
+ return Objects.equals(this.master, that.master)
+ && Objects.equals(this.backups, that.backups);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(master, backups);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this.getClass())
+ .add("master", master.orElseGet(() -> null))
+ .add("backups", backups)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/package-info.java
new file mode 100644
index 00000000..d5ae40c2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Set of abstractions for dealing with controller cluster related topics.
+ */
+package org.onosproject.cluster;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/codec/CodecContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/codec/CodecContext.java
new file mode 100644
index 00000000..272c3e90
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/codec/CodecContext.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Context for codecs to use while encoding/decoding.
+ */
+public interface CodecContext {
+
+ /**
+ * Returns the JSON object mapper.
+ *
+ * @return object mapper
+ */
+ ObjectMapper mapper();
+
+ /**
+ * Returns the JSON codec for the specified entity class.
+ *
+ * @param entityClass entity class
+ * @param <T> entity type
+ * @return JSON codec; null if no codec available for the class
+ */
+ <T> JsonCodec<T> codec(Class<T> entityClass);
+
+ /**
+ * Returns reference to the specified service implementation.
+ *
+ * @param serviceClass service class
+ * @param <T> service type
+ * @return JSON codec; null if no codec available for the class
+ */
+ <T> T getService(Class<T> serviceClass);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/codec/CodecService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/codec/CodecService.java
new file mode 100644
index 00000000..2705569d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/codec/CodecService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec;
+
+import java.util.Set;
+
+/**
+ * Service for registering and retrieving JSON codecs for various entities.
+ */
+public interface CodecService {
+
+ /**
+ * Returns the set of classes with currently registered codecs.
+ *
+ * @return set of entity classes
+ */
+ Set<Class<?>> getCodecs();
+
+ /**
+ * Returns the JSON codec for the specified entity class.
+ *
+ * @param entityClass entity class
+ * @param <T> entity type
+ * @return JSON codec; null if no codec available for the class
+ */
+ <T> JsonCodec<T> getCodec(Class<T> entityClass);
+
+ /**
+ * Registers the specified JSON codec for the given entity class.
+ *
+ * @param entityClass entity class
+ * @param codec JSON codec
+ * @param <T> entity type
+ */
+ <T> void registerCodec(Class<T> entityClass, JsonCodec<T> codec);
+
+ /**
+ * Unregisters the JSON codec for the specified entity class.
+ *
+ * @param entityClass entity class
+ */
+ void unregisterCodec(Class<?> entityClass);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/codec/JsonCodec.java b/framework/src/onos/core/api/src/main/java/org/onosproject/codec/JsonCodec.java
new file mode 100644
index 00000000..6df8f117
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/codec/JsonCodec.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Abstraction of a codec capable for encoding/decoding arbitrary objects to/from JSON.
+ */
+public abstract class JsonCodec<T> {
+
+ /**
+ * Encodes the specified entity into JSON.
+ *
+ * @param entity entity to encode
+ * @param context encoding context
+ * @return JSON node
+ * @throws java.lang.UnsupportedOperationException if the codec does not
+ * support encode operations
+ */
+ public ObjectNode encode(T entity, CodecContext context) {
+ throw new UnsupportedOperationException("encode() not supported");
+ }
+
+ /**
+ * Decodes the specified entity from JSON.
+ *
+ * @param json JSON to decode
+ * @param context decoding context
+ * @return decoded entity
+ * @throws java.lang.UnsupportedOperationException if the codec does not
+ * support decode operations
+ */
+ public T decode(ObjectNode json, CodecContext context) {
+ throw new UnsupportedOperationException("decode() not supported");
+ }
+
+ /**
+ * Encodes the collection of the specified entities.
+ *
+ * @param entities collection of entities to encode
+ * @param context encoding context
+ * @return JSON array
+ * @throws java.lang.UnsupportedOperationException if the codec does not
+ * support encode operations
+ */
+ public ArrayNode encode(Iterable<T> entities, CodecContext context) {
+ ArrayNode result = context.mapper().createArrayNode();
+ for (T entity : entities) {
+ result.add(encode(entity, context));
+ }
+ return result;
+ }
+
+ /**
+ * Decodes the specified JSON array into a collection of entities.
+ *
+ * @param json JSON array to decode
+ * @param context decoding context
+ * @return collection of decoded entities
+ * @throws java.lang.UnsupportedOperationException if the codec does not
+ * support decode operations
+ */
+ public List<T> decode(ArrayNode json, CodecContext context) {
+ List<T> result = new ArrayList<>();
+ for (JsonNode node : json) {
+ result.add(decode((ObjectNode) node, context));
+ }
+ return result;
+ }
+
+ /**
+ * Gets a child Object Node from a parent by name. If the child is not found
+ * or does nor represent an object, null is returned.
+ *
+ * @param parent parent object
+ * @param childName name of child to query
+ * @return child object if found, null if not found or if not an object
+ */
+ protected static ObjectNode get(ObjectNode parent, String childName) {
+ JsonNode node = parent.path(childName);
+ return node.isObject() && !node.isNull() ? (ObjectNode) node : null;
+ }
+
+ /**
+ * Gets a child Object Node from a parent by index. If the child is not found
+ * or does nor represent an object, null is returned.
+ *
+ * @param parent parent object
+ * @param childIndex index of child to query
+ * @return child object if found, null if not found or if not an object
+ */
+ protected static ObjectNode get(JsonNode parent, int childIndex) {
+ JsonNode node = parent.path(childIndex);
+ return node.isObject() && !node.isNull() ? (ObjectNode) node : null;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/codec/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/codec/package-info.java
new file mode 100644
index 00000000..0aa063f5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/codec/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Base JSON codec abstraction and a service for tracking various JSON codecs.
+ */
+package org.onosproject.codec;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/Application.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/Application.java
new file mode 100644
index 00000000..fca53843
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/Application.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+import org.onosproject.security.Permission;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Abstraction of a network control/management application.
+ */
+public interface Application {
+
+ /**
+ * Returns the application name id.
+ *
+ * @return application identifier
+ */
+ ApplicationId id();
+
+ /**
+ * Returns the application version.
+ *
+ * @return application version
+ */
+ Version version();
+
+ /**
+ * Returns description of the application.
+ *
+ * @return application description text
+ */
+ String description();
+
+ /**
+ * Returns the name of the application origin, group or company.
+ *
+ * @return application origin
+ */
+ String origin();
+
+ /**
+ * Returns the role of the application.
+ *
+ * @return application role
+ */
+ ApplicationRole role();
+
+ /**
+ * Returns the permissions requested by the application.
+ *
+ * @return requested permissions
+ */
+ Set<Permission> permissions();
+
+ /**
+ * Returns the feature repository URI. Null value signifies that the
+ * application did not provide its own features repository.
+ *
+ * @return optional feature repo URL
+ */
+ Optional<URI> featuresRepo();
+
+ /**
+ * Returns the list of features comprising the application. At least one
+ * feature must be given.
+ *
+ * @return application features
+ */
+ List<String> features();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationId.java
new file mode 100644
index 00000000..25bc8ce7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationId.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+
+/**
+ * Application identifier.
+ */
+public interface ApplicationId {
+
+ /**
+ * Returns the application id.
+ * @return a short value
+ */
+ short id();
+
+ /**
+ * Returns the applications supplied identifier.
+ * @return a string identifier
+ */
+ String name();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationIdStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationIdStore.java
new file mode 100644
index 00000000..f857fbdc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationIdStore.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+// FIXME: Move to org.onosproject.app package
+
+import java.util.Set;
+
+/**
+ * Manages application IDs.
+ */
+public interface ApplicationIdStore {
+
+ /**
+ * Returns the set of currently registered application identifiers.
+ *
+ * @return set of application ids
+ */
+ Set<ApplicationId> getAppIds();
+
+ /**
+ * Returns an existing application id from a given id.
+ *
+ * @param id the short value of the id
+ * @return an application id; null if no such app registered
+ */
+ ApplicationId getAppId(Short id);
+
+ /**
+ * Returns registered application id from the given name.
+ *
+ * @param name application name
+ * @return an application id; null if no such app registered
+ */
+ ApplicationId getAppId(String name);
+
+ /**
+ * Registers a new application by its name, which is expected
+ * to follow the reverse DNS convention, e.g.
+ * {@code org.flying.circus.app}
+ *
+ * @param identifier string identifier
+ * @return the application id
+ */
+ ApplicationId registerApplication(String identifier);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationRole.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationRole.java
new file mode 100644
index 00000000..5fcb80ba
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/ApplicationRole.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.core;
+
+public enum ApplicationRole {
+ /**
+ * Indicates that an application has an ADMIN role.
+ */
+ ADMIN,
+
+ /**
+ * Indicates that an application has a USER role.
+ */
+ USER,
+
+ /**
+ * Indicates that an application role has not been specified.
+ */
+ UNSPECIFIED,
+
+ /**
+ * More useful roles may be defined.
+ */
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/CoreService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/CoreService.java
new file mode 100644
index 00000000..3dfc6b26
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/CoreService.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.Set;
+
+/**
+ * Service for interacting with the core system of the controller.
+ */
+public interface CoreService {
+
+ /**
+ * Name of the core "application".
+ */
+ static final String CORE_APP_NAME = "org.onosproject.core";
+
+ /**
+ * Identifier of the core "provider".
+ */
+ static final ProviderId CORE_PROVIDER_ID = new ProviderId("core", CORE_APP_NAME);
+
+ /**
+ * Returns the product version.
+ *
+ * @return product version
+ */
+ Version version();
+
+ /**
+ * Returns the set of currently registered application identifiers.
+ *
+ * @return set of application ids
+ */
+ Set<ApplicationId> getAppIds();
+
+ /**
+ * Returns an existing application id from a given id.
+ * @param id the short value of the id
+ * @return an application id
+ */
+ ApplicationId getAppId(Short id);
+
+ /**
+ * Returns an existing application id from a given id.
+ * @param name the name portion of the ID to look up
+ * @return an application id
+ */
+ ApplicationId getAppId(String name);
+
+ /**
+ * Registers a new application by its name, which is expected
+ * to follow the reverse DNS convention, e.g.
+ * {@code org.flying.circus.app}
+ *
+ * @param identifier string identifier
+ * @return the application id
+ */
+ ApplicationId registerApplication(String identifier);
+
+ /**
+ * Returns an id generator for a given topic.
+ *
+ * @param topic topic identified
+ * @return the id generator
+ */
+ IdGenerator getIdGenerator(String topic);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplication.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplication.java
new file mode 100644
index 00000000..d8062ddf
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplication.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+import org.onosproject.security.Permission;
+
+import java.net.URI;
+import java.util.Set;
+import java.util.Optional;
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of network control/management application descriptor.
+ */
+public class DefaultApplication implements Application {
+
+ private final ApplicationId appId;
+ private final Version version;
+ private final String description;
+ private final String origin;
+ private final ApplicationRole role;
+ private final Set<Permission> permissions;
+ private final Optional<URI> featuresRepo;
+ private final List<String> features;
+
+ /**
+ * Creates a new application descriptor using the supplied data.
+ *
+ * @param appId application identifier
+ * @param version application version
+ * @param description application description
+ * @param origin origin company
+ * @param role application role
+ * @param permissions requested permissions
+ * @param featuresRepo optional features repo URI
+ * @param features application features
+ */
+ public DefaultApplication(ApplicationId appId, Version version,
+ String description, String origin,
+ ApplicationRole role, Set<Permission> permissions,
+ Optional<URI> featuresRepo, List<String> features) {
+ this.appId = checkNotNull(appId, "ID cannot be null");
+ this.version = checkNotNull(version, "Version cannot be null");
+ this.description = checkNotNull(description, "Description cannot be null");
+ this.origin = checkNotNull(origin, "Origin cannot be null");
+ this.role = checkNotNull(role, "Role cannot be null");
+ this.permissions = checkNotNull(permissions, "Permissions cannot be null");
+ this.featuresRepo = checkNotNull(featuresRepo, "Features repo cannot be null");
+ this.features = checkNotNull(features, "Features cannot be null");
+ checkArgument(!features.isEmpty(), "There must be at least one feature");
+ }
+
+ @Override
+ public ApplicationId id() {
+ return appId;
+ }
+
+ @Override
+ public Version version() {
+ return version;
+ }
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public String origin() {
+ return origin;
+ }
+
+ @Override
+ public ApplicationRole role() {
+ return role;
+ }
+
+ @Override
+ public Set<Permission> permissions() {
+ return permissions;
+ }
+
+ @Override
+ public Optional<URI> featuresRepo() {
+ return featuresRepo;
+ }
+
+ @Override
+ public List<String> features() {
+ return features;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(appId, version, description, origin, role, permissions,
+ featuresRepo, features);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final DefaultApplication other = (DefaultApplication) obj;
+ return Objects.equals(this.appId, other.appId) &&
+ Objects.equals(this.version, other.version) &&
+ Objects.equals(this.description, other.description) &&
+ Objects.equals(this.origin, other.origin) &&
+ Objects.equals(this.role, other.role) &&
+ Objects.equals(this.permissions, other.permissions) &&
+ Objects.equals(this.featuresRepo, other.featuresRepo) &&
+ Objects.equals(this.features, other.features);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("appId", appId)
+ .add("version", version)
+ .add("description", description)
+ .add("origin", origin)
+ .add("role", role)
+ .add("permissions", permissions)
+ .add("featuresRepo", featuresRepo)
+ .add("features", features)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java
new file mode 100644
index 00000000..c7b5b2da
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Application identifier.
+ */
+public class DefaultApplicationId implements ApplicationId {
+
+ private final short id;
+ private final String name;
+
+ /**
+ * Creates a new application ID.
+ *
+ * @param id application identifier
+ * @param name application name
+ */
+ public DefaultApplicationId(int id, String name) {
+ checkArgument(0 <= id && id <= Short.MAX_VALUE, "id is outside range");
+ this.id = (short) id;
+ this.name = name;
+ }
+
+ // Constructor for serializers.
+ private DefaultApplicationId() {
+ this.id = 0;
+ this.name = null;
+ }
+
+ @Override
+ public short id() {
+ return id;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultApplicationId) {
+ DefaultApplicationId other = (DefaultApplicationId) obj;
+ return Objects.equals(this.id, other.id);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("id", id).add("name", name).toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java
new file mode 100644
index 00000000..9fa8d2b6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Default implementation of {@link GroupId}.
+ */
+public class DefaultGroupId implements GroupId {
+
+ private final int id;
+
+ public DefaultGroupId(int id) {
+ this.id = id;
+ }
+
+ // Constructor for serialization
+ private DefaultGroupId() {
+ this.id = 0;
+ }
+
+ @Override
+ public int id() {
+ return this.id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof DefaultGroupId)) {
+ return false;
+ }
+ final DefaultGroupId other = (DefaultGroupId) obj;
+ return Objects.equals(this.id, other.id);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("id", id)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/GroupId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/GroupId.java
new file mode 100644
index 00000000..739fc7ff
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/GroupId.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+/**
+ * Group identifier.
+ */
+public interface GroupId {
+
+ /**
+ * Returns a group ID as an integer value.
+ * The method is not intended for use by application developers.
+ * Return data type may change in the future release.
+ *
+ * @return a group ID as integer value
+ */
+ int id();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/IdBlock.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/IdBlock.java
new file mode 100644
index 00000000..f4088603
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/IdBlock.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * 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);
+ }
+
+ /**
+ * Returns the initial value.
+ *
+ * @return initial value
+ */
+ private long getStart() {
+ return start;
+ }
+
+ /**
+ * Returns the last value.
+ *
+ * @return last value
+ */
+ private 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;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("start", start)
+ .add("size", size)
+ .add("currentId", currentId)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/IdBlockStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/IdBlockStore.java
new file mode 100644
index 00000000..8ed58ae7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/IdBlockStore.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+/**
+ * Manages id blocks.
+ */
+public interface IdBlockStore {
+
+ /**
+ * Returns a topic-unique block of ids.
+ *
+ * @param topic topic name
+ * @return id block
+ */
+ IdBlock getIdBlock(String topic);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/IdGenerator.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/IdGenerator.java
new file mode 100644
index 00000000..149c834b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/IdGenerator.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+/**
+ * A generalized interface for ID generation
+ *
+ * {@link #getNewId()} generates a globally unique ID instance on
+ * each invocation.
+ */
+public interface IdGenerator {
+ /**
+ * Returns a globally unique ID instance.
+ *
+ * @return globally unique ID instance
+ */
+ long getNewId();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/MetricsHelper.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/MetricsHelper.java
new file mode 100644
index 00000000..b5be0944
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/MetricsHelper.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.core;
+
+import org.onlab.metrics.MetricsComponent;
+import org.onlab.metrics.MetricsFeature;
+import org.onlab.metrics.MetricsService;
+
+import com.codahale.metrics.Timer;
+
+/**
+ * Collection of utility methods used for providing Metrics.
+ */
+public interface MetricsHelper {
+
+ /**
+ * Returns MetricService instance.
+ *
+ * @return MetricService instance
+ */
+ abstract MetricsService metricsService();
+
+
+ /**
+ * Creates a Timer instance with given name.
+ *
+ * @param component component name
+ * @param feature feature name
+ * @param name timer name
+ * @return Timer instance
+ */
+ default Timer createTimer(String component, String feature, String name) {
+ final MetricsService metricsService = metricsService();
+ if (metricsService != null) {
+ MetricsComponent c = metricsService.registerComponent(component);
+ MetricsFeature f = c.registerFeature(feature);
+ return metricsService.createTimer(c, f, name);
+ }
+ return null;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/UnavailableIdException.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/UnavailableIdException.java
new file mode 100644
index 00000000..2e4af264
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/UnavailableIdException.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+/**
+ * Represents that there is no available IDs.
+ */
+public class UnavailableIdException extends RuntimeException {
+
+ private static final long serialVersionUID = -2287403908433720122L;
+
+ /**
+ * Constructs an exception with no message and no underlying cause.
+ */
+ public UnavailableIdException() {
+ }
+
+ /**
+ * Constructs an exception with the specified message.
+ *
+ * @param message the message describing the specific nature of the error
+ */
+ public UnavailableIdException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception with the specified message and the underlying cause.
+ *
+ * @param message the message describing the specific nature of the error
+ * @param cause the underlying cause of this error
+ */
+ public UnavailableIdException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/Version.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/Version.java
new file mode 100644
index 00000000..a5377016
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/Version.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.core;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static java.lang.Integer.parseInt;
+
+/**
+ * Representation of the product version.
+ */
+public final class Version {
+
+ public static final String FORMAT_MINIMAL = "%d.%d";
+ public static final String FORMAT_SHORT = "%d.%d.%s";
+ public static final String FORMAT_LONG = "%d.%d.%s.%s";
+
+ private static final String NEGATIVE = "Version segment cannot be negative";
+ public static final String TOO_SHORT = "Version must have at least major and minor numbers";
+
+ private final int major;
+ private final int minor;
+ private final String patch;
+ private final String build;
+
+ private final String format;
+
+ // Creates a new version descriptor
+ private Version(int major, int minor, String patch, String build) {
+ this.major = major;
+ this.minor = minor;
+ this.patch = patch;
+ this.build = build;
+ this.format =
+ isNullOrEmpty(patch) ?
+ String.format(FORMAT_MINIMAL, major, minor) :
+ (isNullOrEmpty(build) ?
+ String.format(FORMAT_SHORT, major, minor, patch) :
+ String.format(FORMAT_LONG, major, minor, patch, build));
+ }
+
+
+ /**
+ * Creates a new version from the specified constituent numbers.
+ *
+ * @param major major version number
+ * @param minor minor version number
+ * @param patch version patch segment
+ * @param build optional build string
+ * @return version descriptor
+ */
+ public static Version version(int major, int minor, String patch, String build) {
+ checkArgument(major >= 0, NEGATIVE);
+ checkArgument(minor >= 0, NEGATIVE);
+ return new Version(major, minor, patch, build);
+ }
+
+ /**
+ * Creates a new version by parsing the specified string.
+ *
+ * @param string version string
+ * @return version descriptor
+ */
+ public static Version version(String string) {
+ String[] fields = string.split("[.-]");
+ checkArgument(fields.length >= 2, TOO_SHORT);
+ return new Version(parseInt(fields[0]), parseInt(fields[1]),
+ fields.length >= 3 ? fields[2] : null,
+ fields.length >= 4 ? fields[3] : null);
+ }
+
+ /**
+ * Returns the major version number.
+ *
+ * @return major version number
+ */
+ public int major() {
+ return major;
+ }
+
+ /**
+ * Returns the minor version number.
+ *
+ * @return minor version number
+ */
+ public int minor() {
+ return minor;
+ }
+
+ /**
+ * Returns the version patch segment.
+ *
+ * @return patch number
+ */
+ public String patch() {
+ return patch;
+ }
+
+ /**
+ * Returns the version build string.
+ *
+ * @return build string
+ */
+ public String build() {
+ return build;
+ }
+
+ @Override
+ public String toString() {
+ return format;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(format);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Version) {
+ final Version other = (Version) obj;
+ return Objects.equals(this.format, other.format);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/package-info.java
new file mode 100644
index 00000000..3766d49f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * ONOS Core API definitions.
+ */
+package org.onosproject.core;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/AbstractEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/AbstractEvent.java
new file mode 100644
index 00000000..67b10292
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/AbstractEvent.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+import org.joda.time.LocalDateTime;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Base event implementation.
+ */
+public class AbstractEvent<T extends Enum, S> implements Event<T, S> {
+
+ private final long time;
+ private final T type;
+ private final S subject;
+
+ /**
+ * Creates an event of a given type and for the specified subject and the
+ * current time.
+ *
+ * @param type event type
+ * @param subject event subject
+ */
+ protected AbstractEvent(T type, S subject) {
+ this(type, subject, System.currentTimeMillis());
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject and time.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param time occurrence time
+ */
+ protected AbstractEvent(T type, S subject, long time) {
+ this.type = type;
+ this.subject = subject;
+ this.time = time;
+ }
+
+ @Override
+ public long time() {
+ return time;
+ }
+
+ @Override
+ public T type() {
+ return type;
+ }
+
+ @Override
+ public S subject() {
+ return subject;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("time", new LocalDateTime(time))
+ .add("type", type())
+ .add("subject", subject())
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/AbstractListenerManager.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/AbstractListenerManager.java
new file mode 100644
index 00000000..cbe7421f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/AbstractListenerManager.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+
+/**
+ * Basis for components which need to export listener mechanism.
+ */
+@Component(componentAbstract = true)
+public abstract class AbstractListenerManager<E extends Event, L extends EventListener<E>>
+ implements ListenerService<E, L> {
+
+ protected final ListenerRegistry<E, L> listenerRegistry = new ListenerRegistry<>();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected EventDeliveryService eventDispatcher;
+
+ @Override
+ public void addListener(L listener) {
+ listenerRegistry.addListener(listener);
+ }
+
+ @Override
+ public void removeListener(L listener) {
+ listenerRegistry.removeListener(listener);
+ }
+
+
+ /**
+ * Safely posts the specified event to the local event dispatcher.
+ * If there is no event dispatcher or if the event is null, this method
+ * is a noop.
+ *
+ * @param event event to be posted; may be null
+ */
+ protected void post(E event) {
+ if (event != null && eventDispatcher != null) {
+ eventDispatcher.post(event);
+ }
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/DefaultEventSinkRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/DefaultEventSinkRegistry.java
new file mode 100644
index 00000000..be6ddb61
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/DefaultEventSinkRegistry.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Base implementation of event sink registry.
+ */
+public class DefaultEventSinkRegistry implements EventSinkRegistry {
+
+ private final Map<Class<? extends Event>, EventSink<? extends Event>>
+ sinks = new ConcurrentHashMap<>();
+
+ @Override
+ public <E extends Event> void addSink(Class<E> eventClass, EventSink<E> sink) {
+ checkNotNull(eventClass, "Event class cannot be null");
+ checkNotNull(sink, "Event sink cannot be null");
+ checkArgument(!sinks.containsKey(eventClass),
+ "Event sink already registered for %s", eventClass.getName());
+ sinks.put(eventClass, sink);
+ }
+
+ @Override
+ public <E extends Event> void removeSink(Class<E> eventClass) {
+ checkNotNull(eventClass, "Event class cannot be null");
+ checkArgument(sinks.remove(eventClass) != null,
+ "Event sink not registered for %s", eventClass.getName());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <E extends Event> EventSink<E> getSink(Class<E> eventClass) {
+ checkNotNull(eventClass, "Event class cannot be null");
+ return (EventSink<E>) sinks.get(eventClass);
+ }
+
+ @Override
+ public Set<Class<? extends Event>> getSinks() {
+ return ImmutableSet.copyOf(sinks.keySet());
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/Event.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/Event.java
new file mode 100644
index 00000000..e7cbb60f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/Event.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+/**
+ * Abstraction of an of a time-stamped event pertaining to an arbitrary subject.
+ */
+public interface Event<T extends Enum, S> {
+
+ /**
+ * Returns the timestamp of when the event occurred, given in milliseconds
+ * since the start of epoch.
+ *
+ * @return timestamp in milliseconds
+ */
+ long time();
+
+ /**
+ * Returns the type of the event.
+ *
+ * @return event type
+ */
+ T type();
+
+ /**
+ * Returns the subject of the event.
+ *
+ * @return subject to which this event pertains
+ */
+ S subject();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventDeliveryService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventDeliveryService.java
new file mode 100644
index 00000000..ff268935
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventDeliveryService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+/**
+ * Abstraction of an entity capable of accepting events to be posted and
+ * then dispatching them to the appropriate event sink.
+ */
+public interface EventDeliveryService extends EventDispatcher, EventSinkRegistry {
+
+ /**
+ * Sets the number of millis that an event sink has to process an event.
+ *
+ * @param millis number of millis allowed per sink per event
+ */
+ void setDispatchTimeLimit(long millis);
+
+ /**
+ * Returns the number of millis that an event sink has to process an event.
+ *
+ * @return number of millis allowed per sink per event
+ */
+ long getDispatchTimeLimit();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventDispatcher.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventDispatcher.java
new file mode 100644
index 00000000..daebd8b0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventDispatcher.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+/**
+ * Abstraction of a mechanism capable of accepting and dispatching events to
+ * appropriate event sinks. Where the event sinks are obtained is unspecified.
+ * Similarly, whether the events are accepted and dispatched synchronously
+ * or asynchronously is unspecified as well.
+ */
+public interface EventDispatcher {
+
+ /**
+ * Posts the specified event for dispatching.
+ *
+ * @param event event to be posted
+ */
+ void post(Event event);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventFilter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventFilter.java
new file mode 100644
index 00000000..3b2498f6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventFilter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+/**
+ * Entity capable of filtering events.
+ */
+public interface EventFilter<E extends Event> {
+
+ /**
+ * Indicates whether the specified event is of interest or not.
+ * Default implementation always returns true.
+ *
+ * @param event event to be inspected
+ * @return true if event is relevant; false otherwise
+ */
+ default boolean isRelevant(E event) {
+ return true;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventListener.java
new file mode 100644
index 00000000..e77369fc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventListener.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+/**
+ * Entity capable of receiving events.
+ */
+public interface EventListener<E extends Event> extends EventFilter<E> {
+
+ /**
+ * Reacts to the specified event.
+ *
+ * @param event event to be processed
+ */
+ void event(E event);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventSink.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventSink.java
new file mode 100644
index 00000000..221b3224
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventSink.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+/**
+ * Abstraction of an event sink capable of processing the specified event types.
+ */
+public interface EventSink<E extends Event> {
+
+ /**
+ * Processes the specified event.
+ *
+ * @param event event to be processed
+ */
+ void process(E event);
+
+ /**
+ * Handles notification that event processing time limit has been exceeded.
+ */
+ default void onProcessLimit() {
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventSinkRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventSinkRegistry.java
new file mode 100644
index 00000000..bb054a30
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/EventSinkRegistry.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+import java.util.Set;
+
+/**
+ * Abstraction of an event sink registry capable of tracking sinks based on
+ * their event class.
+ */
+public interface EventSinkRegistry {
+
+ /**
+ * Adds the specified sink for the given event class.
+ *
+ * @param eventClass event class
+ * @param sink event sink
+ * @param <E> type of event
+ */
+ <E extends Event> void addSink(Class<E> eventClass, EventSink<E> sink);
+
+ /**
+ * Removes the sink associated with the given event class.
+ *
+ * @param eventClass event class
+ * @param <E> type of event
+ */
+ <E extends Event> void removeSink(Class<E> eventClass);
+
+ /**
+ * Returns the event sink associated with the specified event class.
+ *
+ * @param eventClass event class
+ * @param <E> type of event
+ * @return event sink or null if none found
+ */
+ <E extends Event> EventSink<E> getSink(Class<E> eventClass);
+
+ /**
+ * Returns the set of all event classes for which sinks are presently
+ * registered.
+ *
+ * @return set of event classes
+ */
+ Set<Class<? extends Event>> getSinks();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/ListenerRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/ListenerRegistry.java
new file mode 100644
index 00000000..ef02af06
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/ListenerRegistry.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+import org.slf4j.Logger;
+
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Base implementation of an event sink and a registry capable of tracking
+ * listeners and dispatching events to them as part of event sink processing.
+ */
+public class ListenerRegistry<E extends Event, L extends EventListener<E>>
+ implements ListenerService<E, L>, EventSink<E> {
+
+ private static final long LIMIT = 1_800; // ms
+
+ private final Logger log = getLogger(getClass());
+
+ private long lastStart;
+ private L lastListener;
+
+ /**
+ * Set of listeners that have registered.
+ */
+ protected final Set<L> listeners = new CopyOnWriteArraySet<>();
+
+ @Override
+ public void addListener(L listener) {
+ checkNotNull(listener, "Listener cannot be null");
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeListener(L listener) {
+ checkNotNull(listener, "Listener cannot be null");
+ if (!listeners.remove(listener)) {
+ log.warn("Listener {} not registered", listener);
+ }
+ }
+
+ @Override
+ public void process(E event) {
+ for (L listener : listeners) {
+ try {
+ lastListener = listener;
+ lastStart = System.currentTimeMillis();
+ if (listener.isRelevant(event)) {
+ listener.event(event);
+ }
+ lastStart = 0;
+ } catch (Exception error) {
+ reportProblem(event, error);
+ }
+ }
+ }
+
+ @Override
+ public void onProcessLimit() {
+ if (lastStart > 0) {
+ long duration = System.currentTimeMillis() - lastStart;
+ if (duration > LIMIT) {
+ log.error("Listener {} exceeded execution time limit: {} ms; ejected",
+ lastListener.getClass().getName(),
+ duration);
+ removeListener(lastListener);
+ }
+ lastStart = 0;
+ }
+ }
+
+ /**
+ * Reports a problem encountered while processing an event.
+ *
+ * @param event event being processed
+ * @param error error encountered while processing
+ */
+ protected void reportProblem(E event, Throwable error) {
+ log.warn("Exception encountered while processing event " + event, error);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/ListenerService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/ListenerService.java
new file mode 100644
index 00000000..a4a36319
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/ListenerService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.event;
+
+/**
+ * Abstraction of a service capable of asynchronously notifying listeners.
+ */
+public interface ListenerService<E extends Event, L extends EventListener<E>> {
+
+ /**
+ * Adds the specified listener.
+ *
+ * @param listener listener to be added
+ */
+ void addListener(L listener);
+
+ /**
+ * Removes the specified listener.
+ *
+ * @param listener listener to be removed
+ */
+ void removeListener(L listener);
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/event/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/event/package-info.java
new file mode 100644
index 00000000..6b10bcf5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/event/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Local event delivery subsystem interfaces &amp; supporting abstractions.
+ */
+package org.onosproject.event;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipAdminService.java
new file mode 100644
index 00000000..a8835fc7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipAdminService.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mastership;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.onosproject.cluster.NodeId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+
+/**
+ * Service for administering the inventory of device masterships.
+ */
+public interface MastershipAdminService {
+
+ /**
+ * Applies the current mastership role for the specified device.
+ *
+ * @param instance controller instance identifier
+ * @param deviceId device identifier
+ * @param role requested role
+ * @return future that is completed when the role is set
+ */
+ CompletableFuture<Void> setRole(NodeId instance, DeviceId deviceId, MastershipRole role);
+
+ /**
+ * Balances the mastership to be shared as evenly as possibly by all
+ * online instances.
+ */
+ void balanceRoles();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipEvent.java
new file mode 100644
index 00000000..35c32e79
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipEvent.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mastership;
+
+import org.joda.time.LocalDateTime;
+import org.onosproject.cluster.RoleInfo;
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.DeviceId;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Describes a device mastership event.
+ */
+public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceId> {
+
+ //Contains master and standby information.
+ RoleInfo roleInfo;
+
+ /**
+ * Type of mastership events.
+ */
+ public enum Type {
+ /**
+ * Signifies that the master for a device has changed.
+ */
+ MASTER_CHANGED,
+
+ /**
+ * Signifies that the list of backup nodes has changed. If
+ * the change in the backups list is accompanied by a change in
+ * master, the event is subsumed by MASTER_CHANGED.
+ */
+ BACKUPS_CHANGED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified device,
+ * role information, and the current time.
+ *
+ * @param type mastership event type
+ * @param device event device subject
+ * @param info mastership role information
+ */
+ public MastershipEvent(Type type, DeviceId device, RoleInfo info) {
+ super(type, device);
+ this.roleInfo = info;
+ }
+
+ /**
+ * Creates an event of a given type and for the specified device, master,
+ * and time.
+ *
+ * @param type mastership event type
+ * @param device event device subject
+ * @param info role information
+ * @param time occurrence time
+ */
+ public MastershipEvent(Type type, DeviceId device, RoleInfo info, long time) {
+ super(type, device, time);
+ this.roleInfo = info;
+ }
+
+ /**
+ * Returns the current role state for the subject.
+ *
+ * @return RoleInfo associated with Device ID subject
+ */
+ public RoleInfo roleInfo() {
+ return roleInfo;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("time", new LocalDateTime(time()))
+ .add("type", type())
+ .add("subject", subject())
+ .add("roleInfo", roleInfo)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipListener.java
new file mode 100644
index 00000000..9c5690e2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mastership;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving device mastership-related events.
+ */
+public interface MastershipListener extends EventListener<MastershipEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipService.java
new file mode 100644
index 00000000..a709f5cf
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipService.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mastership;
+
+import static org.onosproject.net.MastershipRole.MASTER;
+
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+import org.onosproject.cluster.NodeId;
+import org.onosproject.cluster.RoleInfo;
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+
+/**
+ * Service responsible for determining the controller instance mastership of
+ * a device in a clustered environment. This is the central authority for
+ * determining mastership, but is not responsible for actually applying it
+ * to the devices; this falls on the device service.
+ */
+public interface MastershipService
+ extends ListenerService<MastershipEvent, MastershipListener> {
+
+ /**
+ * Returns the role of the local node for the specified device, without
+ * triggering master selection.
+ *
+ * @param deviceId the the identifier of the device
+ * @return role of the current node
+ */
+ MastershipRole getLocalRole(DeviceId deviceId);
+
+ /**
+ * Returns true if the local controller is the Master for the specified deviceId.
+ *
+ * @param deviceId the the identifier of the device
+ * @return true if local node is master; false otherwise
+ */
+ default boolean isLocalMaster(DeviceId deviceId) {
+ return getLocalRole(deviceId) == MASTER;
+ }
+
+ /**
+ * Returns the mastership status of the local controller for a given
+ * device forcing master selection if necessary.
+ *
+ * @param deviceId the the identifier of the device
+ * @return the role of this controller instance
+ */
+ CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId);
+
+ /**
+ * Abandons mastership of the specified device on the local node thus
+ * forcing selection of a new master. If the local node is not a master
+ * for this device, no master selection will occur.
+ *
+ * @param deviceId the identifier of the device
+ * @return future that is completed when relinquish is complete
+ */
+ CompletableFuture<Void> relinquishMastership(DeviceId deviceId);
+
+ /**
+ * Returns the current master for a given device.
+ *
+ * @param deviceId the identifier of the device
+ * @return the ID of the master controller for the device
+ */
+ NodeId getMasterFor(DeviceId deviceId);
+
+ /**
+ * Returns controllers connected to a given device, in order of
+ * preference. The first entry in the list is the current master.
+ *
+ * @param deviceId the identifier of the device
+ * @return a list of controller IDs
+ */
+ RoleInfo getNodesFor(DeviceId deviceId);
+
+ /**
+ * Returns the devices for which a controller is master.
+ *
+ * @param nodeId the ID of the controller
+ * @return a set of device IDs
+ */
+ Set<DeviceId> getDevicesOf(NodeId nodeId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipStore.java
new file mode 100644
index 00000000..81c2d8b6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipStore.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mastership;
+
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+import org.onosproject.cluster.NodeId;
+import org.onosproject.cluster.RoleInfo;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.store.Store;
+
+/**
+ * Manages inventory of mastership roles for devices, across controller
+ * instances; not intended for direct use.
+ */
+public interface MastershipStore extends Store<MastershipEvent, MastershipStoreDelegate> {
+
+ // three things to map: NodeId, DeviceId, MastershipRole
+
+ /**
+ * Requests role of the local node for the specified device.
+ *
+ * @param deviceId device identifier
+ * @return established or newly negotiated mastership role
+ */
+ CompletableFuture<MastershipRole> requestRole(DeviceId deviceId);
+
+ /**
+ * Returns the role of a device for a specific controller instance.
+ *
+ * @param nodeId the instance identifier
+ * @param deviceId the device identifiers
+ * @return the role
+ */
+ MastershipRole getRole(NodeId nodeId, DeviceId deviceId);
+
+ /**
+ * Returns the master for a device.
+ *
+ * @param deviceId the device identifier
+ * @return the instance identifier of the master
+ */
+ NodeId getMaster(DeviceId deviceId);
+
+ /**
+ * Returns the master and backup nodes for a device.
+ *
+ * @param deviceId the device identifier
+ * @return a RoleInfo containing controller IDs
+ */
+ RoleInfo getNodes(DeviceId deviceId);
+
+ /**
+ * Returns the devices that a controller instance is master of.
+ *
+ * @param nodeId the instance identifier
+ * @return a set of device identifiers
+ */
+ Set<DeviceId> getDevices(NodeId nodeId);
+
+
+ /**
+ * Sets a device's role for a specified controller instance.
+ *
+ * @param nodeId controller instance identifier
+ * @param deviceId device identifier
+ * @return a mastership event
+ */
+ CompletableFuture<MastershipEvent> setMaster(NodeId nodeId, DeviceId deviceId);
+
+ /**
+ * Returns the current master and number of past mastership hand-offs
+ * (terms) for a device.
+ *
+ * @param deviceId the device identifier
+ * @return the current master's ID and the term value for device, or null
+ */
+ MastershipTerm getTermFor(DeviceId deviceId);
+
+ /**
+ * Sets a controller instance's mastership role to STANDBY for a device.
+ * If the role is MASTER, another controller instance will be selected
+ * as a candidate master.
+ *
+ * @param nodeId the controller instance identifier
+ * @param deviceId device to revoke mastership role for
+ * @return a mastership event
+ */
+ CompletableFuture<MastershipEvent> setStandby(NodeId nodeId, DeviceId deviceId);
+
+ /**
+ * Allows a controller instance to give up its current role for a device.
+ * If the role is MASTER, another controller instance will be selected
+ * as a candidate master.
+ *
+ * @param nodeId the controller instance identifier
+ * @param deviceId device to revoke mastership role for
+ * @return a mastership event
+ */
+ CompletableFuture<MastershipEvent> relinquishRole(NodeId nodeId, DeviceId deviceId);
+
+ /**
+ * Removes all the roles for the specified controller instance.
+ * If the role was MASTER, another controller instance will be selected
+ * as a candidate master.
+ *
+ * @param nodeId the controller instance identifier
+ */
+ void relinquishAllRole(NodeId nodeId);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipStoreDelegate.java
new file mode 100644
index 00000000..c71f4ed0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mastership;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Mastership store delegate abstraction.
+ */
+public interface MastershipStoreDelegate extends StoreDelegate<MastershipEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipTerm.java b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipTerm.java
new file mode 100644
index 00000000..049d1d2b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipTerm.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mastership;
+
+import java.util.Objects;
+
+import org.onosproject.cluster.NodeId;
+
+import com.google.common.base.MoreObjects;
+
+public final class MastershipTerm {
+
+ private final NodeId master;
+ private final long termNumber;
+
+ private MastershipTerm(NodeId master, long term) {
+ this.master = master;
+ this.termNumber = term;
+ }
+
+ public static MastershipTerm of(NodeId master, long term) {
+ return new MastershipTerm(master, term);
+ }
+
+ public NodeId master() {
+ return master;
+ }
+
+ public long termNumber() {
+ return termNumber;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(master, termNumber);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (other instanceof MastershipTerm) {
+ MastershipTerm that = (MastershipTerm) other;
+ return Objects.equals(this.master, that.master) &&
+ Objects.equals(this.termNumber, that.termNumber);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("master", this.master)
+ .add("termNumber", this.termNumber)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipTermService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipTermService.java
new file mode 100644
index 00000000..1725ee03
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/MastershipTermService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.mastership;
+
+import org.onosproject.net.DeviceId;
+
+// TODO give me a better name
+/**
+ * Service to obtain mastership term information.
+ */
+public interface MastershipTermService {
+
+ // TBD: manage/increment per device mastership change
+ // or increment on any change
+ /**
+ * Returns the term number of mastership change occurred for given device.
+ *
+ * @param deviceId the identifier of the device
+ * @return current master's term.
+ */
+ MastershipTerm getMastershipTerm(DeviceId deviceId);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/package-info.java
new file mode 100644
index 00000000..0040680a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/mastership/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Set of abstractions for dealing with controller mastership related topics.
+ */
+package org.onosproject.mastership;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractAnnotated.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractAnnotated.java
new file mode 100644
index 00000000..e0407e27
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractAnnotated.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.onosproject.net.DefaultAnnotations.EMPTY;
+
+/**
+ * Base abstraction of an annotated entity.
+ */
+public abstract class AbstractAnnotated implements Annotated {
+
+ private final Annotations annotations;
+
+ // For serialization
+ protected AbstractAnnotated() {
+ this.annotations = null;
+ }
+
+ /**
+ * Creates a new entity, annotated with the specified annotations.
+ *
+ * @param annotations optional key/value annotations map
+ */
+ protected AbstractAnnotated(Annotations... annotations) {
+ checkArgument(annotations.length <= 1, "Only one set of annotations is expected");
+ this.annotations = annotations.length == 1 ? annotations[0] : EMPTY;
+ }
+
+ @Override
+ public Annotations annotations() {
+ return annotations;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractDescription.java
new file mode 100644
index 00000000..d81b83cc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractDescription.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Base implementation of an annotated model description.
+ */
+public abstract class AbstractDescription implements Annotated {
+
+ private static final SparseAnnotations EMPTY = DefaultAnnotations.builder().build();
+
+ private final SparseAnnotations annotations;
+
+ // For serialization
+ protected AbstractDescription() {
+ this.annotations = null;
+ }
+
+ /**
+ * Creates a new entity, annotated with the specified annotations.
+ *
+ * @param annotations optional key/value annotations map
+ */
+ protected AbstractDescription(SparseAnnotations... annotations) {
+ checkArgument(annotations.length <= 1, "Only one set of annotations is expected");
+ this.annotations = annotations.length == 1 ? annotations[0] : EMPTY;
+ }
+
+ @Override
+ public SparseAnnotations annotations() {
+ return annotations;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractElement.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractElement.java
new file mode 100644
index 00000000..595e7b9c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractElement.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Base implementation of network elements, i.e. devices or hosts.
+ */
+public abstract class AbstractElement extends AbstractModel implements Element {
+
+ protected final ElementId id;
+
+ // For serialization
+ public AbstractElement() {
+ id = null;
+ }
+
+ /**
+ * Creates a network element attributed to the specified provider.
+ *
+ * @param providerId identity of the provider
+ * @param id element identifier
+ * @param annotations optional key/value annotations
+ */
+ protected AbstractElement(ProviderId providerId, ElementId id,
+ Annotations... annotations) {
+ super(providerId, annotations);
+ this.id = id;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractModel.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractModel.java
new file mode 100644
index 00000000..f3cd5efe
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractModel.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Base implementation of a network model entity.
+ */
+public abstract class AbstractModel extends AbstractAnnotated implements Provided {
+
+ private final ProviderId providerId;
+
+ // For serialization
+ public AbstractModel() {
+ providerId = null;
+ }
+
+ /**
+ * Creates a model entity attributed to the specified provider and
+ * optionally annotated.
+ *
+ * @param providerId identity of the provider
+ * @param annotations optional key/value annotations
+ */
+ protected AbstractModel(ProviderId providerId, Annotations... annotations) {
+ super(annotations);
+ this.providerId = providerId;
+ }
+
+ @Override
+ public ProviderId providerId() {
+ return providerId;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Annotated.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Annotated.java
new file mode 100644
index 00000000..ac4545ac
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Annotated.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Represents an entity that carries arbitrary annotations.
+ */
+public interface Annotated {
+
+ /**
+ * Returns the key/value annotations.
+ *
+ * @return key/value annotations
+ */
+ Annotations annotations();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
new file mode 100644
index 00000000..4949bc40
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Collection of keys for annotation.
+ * <p>
+ * Number of the annotation keys have been deprecated as the use of annotations
+ * is being phased out and instead network configuration subsystem is being
+ * phased-in for majority of model meta-data.
+ * </p>
+ */
+public final class AnnotationKeys {
+
+ // Prohibit instantiation
+ private AnnotationKeys() {}
+
+ /**
+ * Annotation key for instance name.
+ *
+ * @deprecated since Cardinal
+ */
+ @Deprecated
+ public static final String NAME = "name";
+
+ /**
+ * Annotation key for instance type (e.g. host type).
+ *
+ * @deprecated since Cardinal
+ */
+ @Deprecated
+ public static final String TYPE = "type";
+
+ /**
+ * Annotation key for latitude (e.g. latitude of device).
+ *
+ * @deprecated since Cardinal
+ */
+ @Deprecated
+ public static final String LATITUDE = "latitude";
+
+ /**
+ * Annotation key for longitute (e.g. longitude of device).
+ *
+ * @deprecated since Cardinal
+ */
+ @Deprecated
+ public static final String LONGITUDE = "longitude";
+
+ /**
+ * Annotation key for southbound protocol.
+ */
+ public static final String PROTOCOL = "protocol";
+
+ /**
+ * Annotation key for the device driver name.
+ *
+ * @deprecated since Cardinal
+ */
+ @Deprecated
+ public static final String DRIVER = "driver";
+
+ /**
+ * Annotation key for durable links.
+ */
+ public static final String DURABLE = "durable";
+
+ /**
+ * Annotation key for latency.
+ *
+ * @deprecated since Cardinal
+ */
+ @Deprecated
+ public static final String LATENCY = "latency";
+
+ /**
+ * Annotation key for bandwidth.
+ * The value for this key is interpreted as Mbps.
+ *
+ * @deprecated since Cardinal
+ */
+ @Deprecated
+ public static final String BANDWIDTH = "bandwidth";
+
+ /**
+ * Annotation key for the number of optical waves.
+ */
+ public static final String OPTICAL_WAVES = "optical.waves";
+
+ /**
+ * Annotation key for the port name.
+ */
+ public static final String PORT_NAME = "portName";
+
+ /**
+ * Annotation key for the router ID.
+ */
+ public static final String ROUTER_ID = "routerId";
+
+ public static final String STATIC_LAMBDA = "staticLambda";
+
+ public static final String STATIC_PORT = "staticPort";
+
+ /**
+ * Annotation key for device location.
+ */
+ public static final String RACK_ADDRESS = "rackAddress";
+
+ /**
+ * Annotation key for device owner.
+ */
+ public static final String OWNER = "owner";
+
+ /**
+ * Returns the value annotated object for the specified annotation key.
+ * The annotated value is expected to be String that can be parsed as double.
+ * If parsing fails, the returned value will be 1.0.
+ *
+ * @param annotated annotated object whose annotated value is obtained
+ * @param key key of annotation
+ * @return double value of annotated object for the specified key
+ */
+ public static double getAnnotatedValue(Annotated annotated, String key) {
+ double value;
+ try {
+ value = Double.parseDouble(annotated.annotations().value(key));
+ } catch (NumberFormatException e) {
+ value = 1.0;
+ }
+ return value;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Annotations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Annotations.java
new file mode 100644
index 00000000..4ed70601
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Annotations.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.util.Set;
+
+/**
+ * Represents an set of simple key/value string annotations.
+ */
+public interface Annotations {
+
+ /**
+ * Returns the set of keys for available annotations.
+ *
+ * @return annotation keys
+ */
+ Set<String> keys();
+
+ /**
+ * Returns the value of the specified annotation.
+ *
+ * @param key annotation key
+ * @return annotation value
+ */
+ String value(String key);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationsUtil.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationsUtil.java
new file mode 100644
index 00000000..d43a304d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AnnotationsUtil.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Utility for processing annotations.
+ */
+public final class AnnotationsUtil {
+
+ public static boolean isEqual(Annotations lhs, Annotations rhs) {
+ if (lhs == rhs) {
+ return true;
+ }
+ if (lhs == null || rhs == null) {
+ return false;
+ }
+
+ if (!lhs.keys().equals(rhs.keys())) {
+ return false;
+ }
+
+ for (String key : lhs.keys()) {
+ if (!lhs.value(key).equals(rhs.value(key))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // not to be instantiated
+ private AnnotationsUtil() {}
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/ChannelSpacing.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/ChannelSpacing.java
new file mode 100644
index 00000000..4da9d6b3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/ChannelSpacing.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onlab.util.Frequency;
+
+/**
+ * Represents interval frequency between two neighboring wavelengths.
+ */
+public enum ChannelSpacing {
+ CHL_100GHZ(100), // 100 GHz
+ CHL_50GHZ(50), // 50 GHz
+ CHL_25GHZ(25), // 25 GHz
+ CHL_12P5GHZ(12.5), // 12.5 GHz
+ CHL_6P25GHZ(6.5); // 6.25 GHz
+
+ private final Frequency frequency;
+
+ /**
+ * Creates an instance with the specified interval in GHz.
+ *
+ * @param value interval of neighboring wavelengths in GHz.
+ */
+ ChannelSpacing(double value) {
+ this.frequency = Frequency.ofGHz(value);
+ }
+
+ public Frequency frequency() {
+ return frequency;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/ConnectPoint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/ConnectPoint.java
new file mode 100644
index 00000000..0d13f4aa
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/ConnectPoint.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of a network connection point expressed as a pair of the
+ * network element identifier and port number.
+ */
+public class ConnectPoint {
+
+ private final ElementId elementId;
+ private final PortNumber portNumber;
+
+ /**
+ * Creates a new connection point.
+ *
+ * @param elementId network element identifier
+ * @param portNumber port number
+ */
+ public ConnectPoint(ElementId elementId, PortNumber portNumber) {
+ this.elementId = elementId;
+ this.portNumber = portNumber;
+ }
+
+ /**
+ * Returns the network element identifier.
+ *
+ * @return element identifier
+ */
+ public ElementId elementId() {
+ return elementId;
+ }
+
+ /**
+ * Returns the identifier of the infrastructure device if the connection
+ * point belongs to a network element which is indeed an infrastructure
+ * device.
+ *
+ * @return network element identifier as a device identifier
+ * @throws java.lang.IllegalStateException if connection point is not
+ * associated with a device
+ */
+ public DeviceId deviceId() {
+ if (elementId instanceof DeviceId) {
+ return (DeviceId) elementId;
+ }
+ throw new IllegalStateException("Connection point not associated " +
+ "with an infrastructure device");
+ }
+
+ /**
+ * Returns the identifier of the infrastructure device if the connection
+ * point belongs to a network element which is indeed an end-station host.
+ *
+ * @return network element identifier as a host identifier
+ * @throws java.lang.IllegalStateException if connection point is not
+ * associated with a host
+ */
+ public HostId hostId() {
+ if (elementId instanceof HostId) {
+ return (HostId) elementId;
+ }
+ throw new IllegalStateException("Connection point not associated " +
+ "with an end-station host");
+ }
+
+ /**
+ * Returns the identifier of the infrastructure device if the connection
+ * point belongs to a network element which is indeed an ip of pcc
+ * client identifier.
+ *
+ * @return network element identifier as a pcc client identifier
+ * @throws java.lang.IllegalStateException if connection point is not
+ * associated with a pcc client
+ */
+ public IpElementId ipElementId() {
+ if (elementId instanceof IpElementId) {
+ return (IpElementId) elementId;
+ }
+ throw new IllegalStateException("Connection point not associated " +
+ "with an pcc client");
+ }
+
+ /**
+ * Returns the connection port number.
+ *
+ * @return port number
+ */
+ public PortNumber port() {
+ return portNumber;
+ }
+
+ /**
+ * Parse a device connect point from a string.
+ * The connect point should be in the format "deviceUri/portNumber".
+ *
+ * @param string string to parse
+ * @return a ConnectPoint based on the information in the string.
+ */
+ public static ConnectPoint deviceConnectPoint(String string) {
+ checkNotNull(string);
+ String[] splitted = string.split("/");
+ checkArgument(splitted.length == 2,
+ "Connect point must be in \"deviceUri/portNumber\" format");
+
+ return new ConnectPoint(DeviceId.deviceId(splitted[0]),
+ PortNumber.portNumber(splitted[1]));
+ }
+
+ /**
+ * Parse a host connect point from a string.
+ * The connect point should be in the format "hostId/vlanId/portNumber".
+ *
+ * @param string string to parse
+ * @return a ConnectPoint based on the information in the string.
+ */
+ public static ConnectPoint hostConnectPoint(String string) {
+ checkNotNull(string);
+ String[] splitted = string.split("/");
+ checkArgument(splitted.length == 3,
+ "Connect point must be in \"hostId/vlanId/portNumber\" format");
+
+ int lastSlash = string.lastIndexOf("/");
+
+ return new ConnectPoint(HostId.hostId(string.substring(0, lastSlash)),
+ PortNumber.portNumber(string.substring(lastSlash + 1, string.length())));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(elementId, portNumber);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ConnectPoint) {
+ final ConnectPoint other = (ConnectPoint) obj;
+ return Objects.equals(this.elementId, other.elementId) &&
+ Objects.equals(this.portNumber, other.portNumber);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("elementId", elementId)
+ .add("portNumber", portNumber)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java
new file mode 100644
index 00000000..7c97ecdd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import com.google.common.collect.Maps;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Represents a set of simple annotations that can be used to add arbitrary
+ * attributes to various parts of the data model.
+ */
+public final class DefaultAnnotations implements SparseAnnotations {
+
+ public static final SparseAnnotations EMPTY = DefaultAnnotations.builder().build();
+
+ private final Map<String, String> map;
+
+ // For serialization
+ private DefaultAnnotations() {
+ this.map = null;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ DefaultAnnotations that = (DefaultAnnotations) o;
+
+ return Objects.equals(this.map, that.map);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.map);
+ }
+
+ /**
+ * Returns the annotations as a map.
+ *
+ * @return a copy of the contents of the annotations as a map.
+ */
+ public HashMap<String, String> asMap() {
+ return Maps.newHashMap(this.map);
+ }
+
+ /**
+ * Creates a new set of annotations using clone of the specified hash map.
+ *
+ * @param map hash map of key/value pairs
+ */
+ private DefaultAnnotations(Map<String, String> map) {
+ this.map = map;
+ }
+
+ /**
+ * Creates a new annotations builder.
+ *
+ * @return new annotations builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Merges the specified base set of annotations and additional sparse
+ * annotations into new combined annotations. If the supplied sparse
+ * annotations are empty, the original base annotations are returned.
+ * Any keys tagged for removal in the sparse annotations will be omitted
+ * in the resulting merged annotations.
+ *
+ * @param annotations base annotations
+ * @param sparseAnnotations additional sparse annotations
+ * @return combined annotations or the original base annotations if there
+ * are not additional annotations
+ */
+ public static DefaultAnnotations merge(DefaultAnnotations annotations,
+ SparseAnnotations sparseAnnotations) {
+ checkNotNull(annotations, "Annotations cannot be null");
+ if (sparseAnnotations == null || sparseAnnotations.keys().isEmpty()) {
+ return annotations;
+ }
+
+ // Merge the two maps. Yes, this is not very efficient, but the
+ // use-case implies small maps and infrequent merges, so we opt for
+ // simplicity.
+ Map<String, String> merged = copy(annotations.map);
+ for (String key : sparseAnnotations.keys()) {
+ if (sparseAnnotations.isRemoved(key)) {
+ merged.remove(key);
+ } else {
+ merged.put(key, sparseAnnotations.value(key));
+ }
+ }
+ return new DefaultAnnotations(merged);
+ }
+
+ /**
+ * Creates the union of two given SparseAnnotations.
+ * Unlike the {@link #merge(DefaultAnnotations, SparseAnnotations)} method,
+ * result will be {@link SparseAnnotations} instead of {@link Annotations}.
+ *
+ * A key tagged for removal will remain in the output SparseAnnotations,
+ * if the counterpart of the input does not contain the same key.
+ *
+ * @param annotations base annotations
+ * @param sparseAnnotations additional sparse annotations
+ * @return combined annotations or the original base annotations if there
+ * are not additional annotations
+ */
+ public static SparseAnnotations union(SparseAnnotations annotations,
+ SparseAnnotations sparseAnnotations) {
+
+ if (sparseAnnotations == null || sparseAnnotations.keys().isEmpty()) {
+ return annotations;
+ }
+
+ final HashMap<String, String> newMap;
+ if (annotations instanceof DefaultAnnotations) {
+ newMap = copy(((DefaultAnnotations) annotations).map);
+ } else {
+ newMap = new HashMap<>(annotations.keys().size() +
+ sparseAnnotations.keys().size());
+ putAllSparseAnnotations(newMap, annotations);
+ }
+
+ putAllSparseAnnotations(newMap, sparseAnnotations);
+ return new DefaultAnnotations(newMap);
+ }
+
+ // adds the key-values contained in sparseAnnotations to
+ // newMap, if sparseAnnotations had a key tagged for removal,
+ // and corresponding key exist in newMap, entry will be removed.
+ // if corresponding key does not exist, removal tag will be added to
+ // the newMap.
+ private static void putAllSparseAnnotations(
+ final HashMap<String, String> newMap,
+ SparseAnnotations sparseAnnotations) {
+
+ for (String key : sparseAnnotations.keys()) {
+ if (sparseAnnotations.isRemoved(key)) {
+ if (newMap.containsKey(key)) {
+ newMap.remove(key);
+ } else {
+ newMap.put(key, Builder.REMOVED);
+ }
+ } else {
+ String value = sparseAnnotations.value(key);
+ newMap.put(key, value);
+ }
+ }
+ }
+
+ @Override
+ public Set<String> keys() {
+ return Collections.unmodifiableSet(map.keySet());
+ }
+
+ @Override
+ public String value(String key) {
+ String value = map.get(key);
+ return Objects.equals(Builder.REMOVED, value) ? null : value;
+ }
+
+ @Override
+ public boolean isRemoved(String key) {
+ return Objects.equals(Builder.REMOVED, map.get(key));
+ }
+
+ @SuppressWarnings("unchecked")
+ private static HashMap<String, String> copy(Map<String, String> original) {
+ if (original instanceof HashMap) {
+ return (HashMap<String, String>) ((HashMap<?, ?>) original).clone();
+ }
+ throw new IllegalArgumentException("Expecting HashMap instance");
+ }
+
+ @Override
+ public String toString() {
+ return (map == null) ? "null" : map.toString();
+ }
+
+ /**
+ * Facility for gradually building model annotations.
+ */
+ public static final class Builder {
+
+ private static final String REMOVED = "~rEmOvEd~";
+ private final Map<String, String> builder = new HashMap<>();
+
+ // Private construction is forbidden.
+ private Builder() {
+ }
+
+ /**
+ * Adds the specified annotation. Any previous value associated with
+ * the given annotation key will be overwritten.
+ *
+ * @param key annotation key
+ * @param value annotation value
+ * @return self
+ */
+ public Builder set(String key, String value) {
+ builder.put(key, value);
+ return this;
+ }
+
+ /**
+ * Adds the specified annotation. Any previous value associated with
+ * the given annotation key will be tagged for removal.
+ *
+ * @param key annotation key
+ * @return self
+ */
+ public Builder remove(String key) {
+ builder.put(key, REMOVED);
+ return this;
+ }
+
+ /**
+ * Returns immutable annotations built from the accrued key/values pairs.
+ *
+ * @return annotations
+ */
+ public DefaultAnnotations build() {
+ return new DefaultAnnotations(copy(builder));
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultDevice.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultDevice.java
new file mode 100644
index 00000000..f3f0fe74
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultDevice.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onosproject.net.provider.ProviderId;
+import org.onlab.packet.ChassisId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default infrastructure device model implementation.
+ */
+public class DefaultDevice extends AbstractElement implements Device {
+
+ private final Type type;
+ private final String manufacturer;
+ private final String serialNumber;
+ private final String hwVersion;
+ private final String swVersion;
+ private final ChassisId chassisId;
+
+ // For serialization
+ private DefaultDevice() {
+ this.type = null;
+ this.manufacturer = null;
+ this.hwVersion = null;
+ this.swVersion = null;
+ this.serialNumber = null;
+ this.chassisId = null;
+ }
+
+ /**
+ * Creates a network element attributed to the specified provider.
+ *
+ * @param providerId identity of the provider
+ * @param id device identifier
+ * @param type device type
+ * @param manufacturer device manufacturer
+ * @param hwVersion device HW version
+ * @param swVersion device SW version
+ * @param serialNumber device serial number
+ * @param chassisId chassis id
+ * @param annotations optional key/value annotations
+ */
+ public DefaultDevice(ProviderId providerId, DeviceId id, Type type,
+ String manufacturer, String hwVersion, String swVersion,
+ String serialNumber, ChassisId chassisId,
+ Annotations... annotations) {
+ super(providerId, id, annotations);
+ this.type = type;
+ this.manufacturer = manufacturer;
+ this.hwVersion = hwVersion;
+ this.swVersion = swVersion;
+ this.serialNumber = serialNumber;
+ this.chassisId = chassisId;
+ }
+
+ @Override
+ public DeviceId id() {
+ return (DeviceId) id;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public String manufacturer() {
+ return manufacturer;
+ }
+
+ @Override
+ public String hwVersion() {
+ return hwVersion;
+ }
+
+ @Override
+ public String swVersion() {
+ return swVersion;
+ }
+
+ @Override
+ public String serialNumber() {
+ return serialNumber;
+ }
+
+ @Override
+ public ChassisId chassisId() {
+ return chassisId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, type, manufacturer, hwVersion, swVersion, serialNumber);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultDevice) {
+ final DefaultDevice other = (DefaultDevice) obj;
+ return Objects.equals(this.id, other.id) &&
+ Objects.equals(this.type, other.type) &&
+ Objects.equals(this.manufacturer, other.manufacturer) &&
+ Objects.equals(this.hwVersion, other.hwVersion) &&
+ Objects.equals(this.swVersion, other.swVersion) &&
+ Objects.equals(this.serialNumber, other.serialNumber);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("id", id)
+ .add("type", type)
+ .add("manufacturer", manufacturer)
+ .add("hwVersion", hwVersion)
+ .add("swVersion", swVersion)
+ .add("serialNumber", serialNumber)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultEdgeLink.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultEdgeLink.java
new file mode 100644
index 00000000..67ceef7a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultEdgeLink.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onosproject.net.provider.ProviderId;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default edge link model implementation.
+ */
+public class DefaultEdgeLink extends DefaultLink implements EdgeLink {
+
+ private final HostId hostId;
+ private final HostLocation hostLocation;
+
+ /**
+ * Creates an edge link using the supplied information.
+ *
+ * @param providerId provider identity
+ * @param hostPoint host-side connection point
+ * @param hostLocation location where host attaches to the network
+ * @param isIngress true to indicate host-to-network direction; false
+ * for network-to-host direction
+ * @param annotations optional key/value annotations
+ */
+ public DefaultEdgeLink(ProviderId providerId, ConnectPoint hostPoint,
+ HostLocation hostLocation, boolean isIngress,
+ Annotations... annotations) {
+ super(providerId, isIngress ? hostPoint : hostLocation,
+ isIngress ? hostLocation : hostPoint, Type.EDGE, annotations);
+ checkArgument(hostPoint.elementId() instanceof HostId,
+ "Host point does not refer to a host ID");
+ this.hostId = (HostId) hostPoint.elementId();
+ this.hostLocation = hostLocation;
+ }
+
+ @Override
+ public HostId hostId() {
+ return hostId;
+ }
+
+ @Override
+ public HostLocation hostLocation() {
+ return hostLocation;
+ }
+
+ /**
+ * Creates a phantom edge link, to an unspecified end-station. This link
+ * does not represent any actually discovered link stored in the system.
+ *
+ * @param edgePort network edge port
+ * @param isIngress true to indicate host-to-network direction; false
+ * for network-to-host direction
+ * @return new phantom edge link
+ */
+ public static DefaultEdgeLink createEdgeLink(ConnectPoint edgePort,
+ boolean isIngress) {
+ checkNotNull(edgePort, "Edge port cannot be null");
+ HostLocation location = (edgePort instanceof HostLocation) ?
+ (HostLocation) edgePort : new HostLocation(edgePort, 0);
+ return new DefaultEdgeLink(ProviderId.NONE,
+ new ConnectPoint(HostId.NONE, PortNumber.P0),
+ location, isIngress);
+ }
+
+ /**
+ * Creates a an edge link, to the specified end-station.
+ *
+ * @param host host
+ * @param isIngress true to indicate host-to-network direction; false
+ * for network-to-host direction
+ * @return new phantom edge link
+ */
+ public static DefaultEdgeLink createEdgeLink(Host host, boolean isIngress) {
+ checkNotNull(host, "Host cannot be null");
+ return new DefaultEdgeLink(ProviderId.NONE,
+ new ConnectPoint(host.id(), PortNumber.P0),
+ host.location(), isIngress);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultHost.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultHost.java
new file mode 100644
index 00000000..2877701e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultHost.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onosproject.net.provider.ProviderId;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * A basic implementation of a Host.
+ */
+public class DefaultHost extends AbstractElement implements Host {
+
+ private final MacAddress mac;
+ private final VlanId vlan;
+ private final HostLocation location;
+ private final Set<IpAddress> ips;
+
+ /**
+ * Creates an end-station host using the supplied information.
+ *
+ * @param providerId provider identity
+ * @param id host identifier
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @param location host location
+ * @param ips host IP addresses
+ * @param annotations optional key/value annotations
+ */
+ public DefaultHost(ProviderId providerId, HostId id, MacAddress mac,
+ VlanId vlan, HostLocation location, Set<IpAddress> ips,
+ Annotations... annotations) {
+ super(providerId, id, annotations);
+ this.mac = mac;
+ this.vlan = vlan;
+ this.location = location;
+ this.ips = new HashSet<>(ips);
+ }
+
+ @Override
+ public HostId id() {
+ return (HostId) id;
+ }
+
+ @Override
+ public MacAddress mac() {
+ return mac;
+ }
+
+ @Override
+ public Set<IpAddress> ipAddresses() {
+ return Collections.unmodifiableSet(ips);
+ }
+
+ @Override
+ public HostLocation location() {
+ return location;
+ }
+
+ @Override
+ public VlanId vlan() {
+ return vlan;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, mac, vlan, location);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultHost) {
+ final DefaultHost other = (DefaultHost) obj;
+ return Objects.equals(this.id, other.id) &&
+ Objects.equals(this.mac, other.mac) &&
+ Objects.equals(this.vlan, other.vlan) &&
+ Objects.equals(this.location, other.location);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("id", id)
+ .add("mac", mac)
+ .add("vlan", vlan)
+ .add("location", location)
+ .add("ipAddresses", ips)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultLink.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultLink.java
new file mode 100644
index 00000000..4d1ca6de
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultLink.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.onosproject.net.Link.State.ACTIVE;
+
+/**
+ * Default infrastructure link model implementation.
+ */
+public class DefaultLink extends AbstractModel implements Link {
+
+ private final ConnectPoint src;
+ private final ConnectPoint dst;
+ private final Type type;
+ private final State state;
+ private final boolean isDurable;
+
+ /**
+ * Creates an active infrastructure link using the supplied information.
+ *
+ * @param providerId provider identity
+ * @param src link source
+ * @param dst link destination
+ * @param type link type
+ * @param annotations optional key/value annotations
+ */
+ public DefaultLink(ProviderId providerId, ConnectPoint src, ConnectPoint dst,
+ Type type, Annotations... annotations) {
+ this(providerId, src, dst, type, ACTIVE, false, annotations);
+ }
+
+ /**
+ * Creates an infrastructure link using the supplied information.
+ * Links marked as durable will remain in the inventory when a vanish
+ * message is received and instead will be marked as inactive.
+ *
+ * @param providerId provider identity
+ * @param src link source
+ * @param dst link destination
+ * @param type link type
+ * @param state link state
+ * @param isDurable indicates if the link is to be considered durable
+ * @param annotations optional key/value annotations
+ */
+ public DefaultLink(ProviderId providerId, ConnectPoint src, ConnectPoint dst,
+ Type type, State state,
+ boolean isDurable, Annotations... annotations) {
+ super(providerId, annotations);
+ this.src = src;
+ this.dst = dst;
+ this.type = type;
+ this.state = state;
+ this.isDurable = isDurable;
+ }
+
+ @Override
+ public ConnectPoint src() {
+ return src;
+ }
+
+ @Override
+ public ConnectPoint dst() {
+ return dst;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public State state() {
+ return state;
+ }
+
+ @Override
+ public boolean isDurable() {
+ return isDurable;
+ }
+
+ // Note: Durability & state are purposefully omitted form equality & hashCode.
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(src, dst, type);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultLink) {
+ final DefaultLink other = (DefaultLink) obj;
+ return Objects.equals(this.src, other.src) &&
+ Objects.equals(this.dst, other.dst) &&
+ Objects.equals(this.type, other.type);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("src", src)
+ .add("dst", dst)
+ .add("type", type)
+ .add("state", state)
+ .add("durable", isDurable)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPath.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPath.java
new file mode 100644
index 00000000..a4789cac
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPath.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of a network path.
+ */
+public class DefaultPath extends DefaultLink implements Path {
+
+ private final List<Link> links;
+ private final double cost;
+
+ /**
+ * Creates a path from the specified source and destination using the
+ * supplied list of links.
+ *
+ * @param providerId provider identity
+ * @param links contiguous links that comprise the path
+ * @param cost unit-less path cost
+ * @param annotations optional key/value annotations
+ */
+ public DefaultPath(ProviderId providerId, List<Link> links, double cost,
+ Annotations... annotations) {
+ super(providerId, source(links), destination(links), Type.INDIRECT, annotations);
+ this.links = ImmutableList.copyOf(links);
+ this.cost = cost;
+ }
+
+ @Override
+ public List<Link> links() {
+ return links;
+ }
+
+ @Override
+ public double cost() {
+ return cost;
+ }
+
+ // Returns the source of the first link.
+ private static ConnectPoint source(List<Link> links) {
+ checkNotNull(links, "List of path links cannot be null");
+ checkArgument(!links.isEmpty(), "List of path links cannot be empty");
+ return links.get(0).src();
+ }
+
+ // Returns the destination of the last link.
+ private static ConnectPoint destination(List<Link> links) {
+ checkNotNull(links, "List of path links cannot be null");
+ checkArgument(!links.isEmpty(), "List of path links cannot be empty");
+ return links.get(links.size() - 1).dst();
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("src", src())
+ .add("dst", dst())
+ .add("type", type())
+ .add("state", state())
+ .add("durable", isDurable())
+ .add("links", links)
+ .add("cost", cost)
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(links);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultPath) {
+ final DefaultPath other = (DefaultPath) obj;
+ return Objects.equals(this.links, other.links);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPort.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPort.java
new file mode 100644
index 00000000..a6b8441a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPort.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default port implementation.
+ */
+public class DefaultPort extends AbstractAnnotated implements Port {
+
+ /** Default port speed in Mbps. */
+ public static final long DEFAULT_SPEED = 1_000;
+
+ private final Element element;
+ private final PortNumber number;
+ private final boolean isEnabled;
+ private final Type type;
+ private final long portSpeed;
+
+ /**
+ * Creates a network element attributed to the specified provider.
+ *
+ * @param element parent network element
+ * @param number port number
+ * @param isEnabled indicator whether the port is up and active
+ * @param annotations optional key/value annotations
+ */
+ public DefaultPort(Element element, PortNumber number, boolean isEnabled,
+ Annotations... annotations) {
+ this(element, number, isEnabled, Type.COPPER, DEFAULT_SPEED, annotations);
+ }
+
+ /**
+ * Creates a network element attributed to the specified provider.
+ *
+ * @param element parent network element
+ * @param number port number
+ * @param isEnabled indicator whether the port is up and active
+ * @param type port type
+ * @param portSpeed port speed in Mbs
+ * @param annotations optional key/value annotations
+ */
+ public DefaultPort(Element element, PortNumber number, boolean isEnabled,
+ Type type, long portSpeed, Annotations... annotations) {
+ super(annotations);
+ this.element = element;
+ this.number = number;
+ this.isEnabled = isEnabled;
+ this.type = type;
+ this.portSpeed = portSpeed;
+ }
+
+ @Override
+ public Element element() {
+ return element;
+ }
+
+ @Override
+ public PortNumber number() {
+ return number;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return isEnabled;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public long portSpeed() {
+ return portSpeed;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(number, isEnabled, type, portSpeed, annotations());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultPort) {
+ final DefaultPort other = (DefaultPort) obj;
+ return Objects.equals(this.element.id(), other.element.id()) &&
+ Objects.equals(this.number, other.number) &&
+ Objects.equals(this.isEnabled, other.isEnabled) &&
+ Objects.equals(this.type, other.type) &&
+ Objects.equals(this.portSpeed, other.portSpeed) &&
+ Objects.equals(this.annotations(), other.annotations());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("element", element.id())
+ .add("number", number)
+ .add("isEnabled", isEnabled)
+ .add("type", type)
+ .add("portSpeed", portSpeed)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Description.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Description.java
new file mode 100644
index 00000000..c01af549
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Description.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Base abstraction of a piece of information about network elements.
+ */
+public interface Description extends Annotated {
+
+ @Override
+ SparseAnnotations annotations();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Device.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Device.java
new file mode 100644
index 00000000..d9001825
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Device.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onlab.packet.ChassisId;
+
+/**
+ * Representation of a network infrastructure device.
+ */
+public interface Device extends Element {
+
+ /**
+ * Coarse classification of the type of the infrastructure device.
+ */
+ public enum Type {
+ SWITCH, ROUTER, ROADM, OTN, ROADM_OTN, FIREWALL, BALANCER, IPS, IDS, CONTROLLER,
+ VIRTUAL, FIBER_SWITCH, MICROWAVE, OTHER
+ }
+
+ /**
+ * Returns the device identifier.
+ *
+ * @return device id
+ */
+ @Override
+ DeviceId id();
+
+ /**
+ * Returns the type of the infrastructure device.
+ *
+ * @return type of the device
+ */
+ Type type();
+
+ /**
+ * Returns the device manufacturer name.
+ *
+ * @return manufacturer name
+ */
+ String manufacturer();
+
+ /**
+ * Returns the device hardware version.
+ *
+ * @return hardware version
+ */
+ String hwVersion();
+
+ /**
+ * Returns the device software version.
+ *
+ * @return software version
+ */
+ String swVersion();
+
+ /**
+ * Returns the device serial number.
+ *
+ * @return serial number
+ */
+ String serialNumber();
+
+ /**
+ * Returns the device chassis id.
+ *
+ * @return chassis id
+ */
+ ChassisId chassisId();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DeviceId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DeviceId.java
new file mode 100644
index 00000000..5331342e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DeviceId.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.net.URI;
+import java.util.Objects;
+
+/**
+ * Immutable representation of a device identity.
+ */
+public final class DeviceId extends ElementId {
+
+ /**
+ * Represents either no device, or an unspecified device.
+ */
+ public static final DeviceId NONE = deviceId("none:none");
+
+ private final URI uri;
+ private final String str;
+
+ // Public construction is prohibited
+ private DeviceId(URI uri) {
+ this.uri = uri;
+ this.str = uri.toString().toLowerCase();
+ }
+
+
+ // Default constructor for serialization
+ protected DeviceId() {
+ this.uri = null;
+ this.str = null;
+ }
+
+ /**
+ * Creates a device id using the supplied URI.
+ *
+ * @param uri device URI
+ * @return DeviceId
+ */
+ public static DeviceId deviceId(URI uri) {
+ return new DeviceId(uri);
+ }
+
+ /**
+ * Creates a device id using the supplied URI string.
+ *
+ * @param string device URI string
+ * @return DeviceId
+ */
+ public static DeviceId deviceId(String string) {
+ return deviceId(URI.create(string));
+ }
+
+ /**
+ * Returns the backing URI.
+ *
+ * @return backing URI
+ */
+ public URI uri() {
+ return uri;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(str);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DeviceId) {
+ final DeviceId that = (DeviceId) obj;
+ return this.getClass() == that.getClass() &&
+ Objects.equals(this.str, that.str);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return str;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/EdgeLink.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/EdgeLink.java
new file mode 100644
index 00000000..73b916b2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/EdgeLink.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Abstraction of a link between an end-station host and the network
+ * infrastructure.
+ */
+public interface EdgeLink extends Link {
+
+ /**
+ * Returns the host identification.
+ *
+ * @return host identifier
+ */
+ HostId hostId();
+
+ /**
+ * Returns the connection point where the host attaches to the
+ * network infrastructure.
+ *
+ * @return host location point
+ */
+ HostLocation hostLocation();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Element.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Element.java
new file mode 100644
index 00000000..6cdab9e4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Element.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Base abstraction of a network element, i.e. an infrastructure device or an end-station host.
+ */
+public interface Element extends Annotated, Provided {
+
+ /**
+ * Returns the network element identifier.
+ *
+ * @return element identifier
+ */
+ ElementId id();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/ElementId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/ElementId.java
new file mode 100644
index 00000000..87defb26
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/ElementId.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Immutable representation of a network element identity.
+ */
+public abstract class ElementId implements NetworkResource {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/GridType.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/GridType.java
new file mode 100644
index 00000000..8e9bc5b9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/GridType.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Represents type of wavelength grid.
+ *
+ * <p>
+ * See Open Networking Foundation "Optical Transport Protocol Extensions Version 1.0".
+ * </p>
+ */
+public enum GridType {
+ DWDM, // Dense Wavelength Division Multiplexing
+ CWDM, // Coarse WDM
+ FLEX // Flex Grid
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Host.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Host.java
new file mode 100644
index 00000000..646f2283
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Host.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+
+import java.util.Set;
+
+/**
+ * Abstraction of an end-station host on the network, essentially a NIC.
+ */
+public interface Host extends Element {
+
+ /**
+ * Host identification.
+ *
+ * @return host id
+ */
+ @Override
+ HostId id();
+
+ /**
+ * Returns the host MAC address.
+ *
+ * @return mac address
+ */
+ MacAddress mac();
+
+ /**
+ * Returns the VLAN ID tied to this host.
+ *
+ * @return VLAN ID value
+ */
+ VlanId vlan();
+
+ /**
+ * Returns set of IP addresses currently bound to the host MAC address.
+ *
+ * @return set of IP addresses; empty if no IP address is bound
+ */
+ Set<IpAddress> ipAddresses();
+
+ /**
+ * Returns the most recent host location where the host attaches to the
+ * network edge.
+ *
+ * @return host location
+ */
+ HostLocation location();
+
+ // TODO: explore capturing list of recent locations to aid in mobility
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/HostId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/HostId.java
new file mode 100644
index 00000000..3e0d2b24
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/HostId.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Immutable representation of a host identity.
+ */
+public final class HostId extends ElementId {
+
+ /**
+ * Represents either no host, or an unspecified host; used for creating
+ * open ingress/egress edge links.
+ */
+ public static final HostId NONE = new HostId(MacAddress.ZERO, VlanId.NONE);
+
+ private static final int MAC_LENGTH = 17;
+ private static final int MIN_ID_LENGTH = 19;
+
+ private final MacAddress mac;
+ private final VlanId vlanId;
+
+ // Public construction is prohibited
+ private HostId(MacAddress mac, VlanId vlanId) {
+ this.mac = mac;
+ this.vlanId = vlanId;
+ }
+
+ // Default constructor for serialization
+ private HostId() {
+ this.mac = null;
+ this.vlanId = null;
+ }
+
+ /**
+ * Returns the host MAC address.
+ *
+ * @return MAC address
+ */
+ public MacAddress mac() {
+ return mac;
+ }
+
+ /**
+ * Returns the host vlan Id.
+ *
+ * @return vlan Id
+ */
+ public VlanId vlanId() {
+ return vlanId;
+ }
+
+ /**
+ * Creates a device id using the supplied ID string.
+ *
+ * @param string device URI string
+ * @return host identifier
+ */
+ public static HostId hostId(String string) {
+ checkArgument(string.length() >= MIN_ID_LENGTH,
+ "Host ID must be at least %s characters", MIN_ID_LENGTH);
+ MacAddress mac = MacAddress.valueOf(string.substring(0, MAC_LENGTH));
+ VlanId vlanId = VlanId.vlanId(Short.parseShort(string.substring(MAC_LENGTH + 1)));
+ return new HostId(mac, vlanId);
+ }
+
+ /**
+ * Creates a device id using the supplied MAC &amp; VLAN ID.
+ *
+ * @param mac mac address
+ * @param vlanId vlan identifier
+ * @return host identifier
+ */
+ public static HostId hostId(MacAddress mac, VlanId vlanId) {
+ return new HostId(mac, vlanId);
+ }
+
+ /**
+ * Creates a device id using the supplied MAC and default VLAN.
+ *
+ * @param mac mac address
+ * @return host identifier
+ */
+ public static HostId hostId(MacAddress mac) {
+ return hostId(mac, VlanId.vlanId(VlanId.UNTAGGED));
+ }
+
+ public String toString() {
+ return mac + "/" + vlanId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mac, vlanId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof HostId) {
+ final HostId other = (HostId) obj;
+ return Objects.equals(this.mac, other.mac) &&
+ Objects.equals(this.vlanId, other.vlanId);
+ }
+ return false;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/HostLocation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/HostLocation.java
new file mode 100644
index 00000000..b0553a2b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/HostLocation.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import static org.onosproject.net.PortNumber.P0;
+
+/**
+ * Representation of a network edge location where an end-station host is
+ * connected.
+ */
+public class HostLocation extends ConnectPoint {
+
+ /**
+ * Represents a no location or an unknown location.
+ */
+ public static final HostLocation NONE = new HostLocation(DeviceId.NONE, P0, 0L);
+
+ // Note that time is explicitly excluded from the notion of equality.
+ private final long time;
+
+ /**
+ * Creates a new host location using the supplied device &amp; port.
+ *
+ * @param deviceId device identity
+ * @param portNumber device port number
+ * @param time time when detected, in millis since start of epoch
+ */
+ public HostLocation(DeviceId deviceId, PortNumber portNumber, long time) {
+ super(deviceId, portNumber);
+ this.time = time;
+ }
+
+ /**
+ * Creates a new host location derived from the supplied connection point.
+ *
+ * @param connectPoint connection point
+ * @param time time when detected, in millis since start of epoch
+ */
+ public HostLocation(ConnectPoint connectPoint, long time) {
+ super(connectPoint.deviceId(), connectPoint.port());
+ this.time = time;
+ }
+
+ /**
+ * Returns the time when the location was established, given in
+ * milliseconds since start of epoch.
+ *
+ * @return time in milliseconds since start of epoch
+ */
+ public long time() {
+ return time;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/IndexedLambda.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/IndexedLambda.java
new file mode 100644
index 00000000..6b5fa652
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/IndexedLambda.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Implementation of Lambda simply designated by an index number of wavelength.
+ */
+public class IndexedLambda implements Lambda {
+
+ private final long index;
+
+ /**
+ * Creates an instance representing the wavelength specified by the given index number.
+ * It is recommended to use {@link Lambda#indexedLambda(long)} unless you want to use the
+ * concrete type, IndexedLambda, directly.
+ *
+ * @param index index number of wavelength
+ */
+ public IndexedLambda(long index) {
+ this.index = index;
+ }
+
+ /**
+ * Returns the index number of lambda.
+ *
+ * @return the index number of lambda
+ */
+ public long index() {
+ return index;
+ }
+
+ @Override
+ public int hashCode() {
+ return Long.hashCode(index);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof IndexedLambda)) {
+ return false;
+ }
+
+ final IndexedLambda that = (IndexedLambda) obj;
+ return this.index == that.index;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("lambda", index)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/IpElementId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/IpElementId.java
new file mode 100644
index 00000000..9e19b624
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/IpElementId.java
@@ -0,0 +1,61 @@
+package org.onosproject.net;
+
+import java.util.Objects;
+import org.onlab.packet.IpAddress;
+import com.google.common.base.MoreObjects;
+
+/**
+ * Represent for a Element ID using ip address.
+ */
+public final class IpElementId extends ElementId {
+
+ private final IpAddress ipAddress;
+
+ /**
+ * Public construction is prohibited.
+ * @param ipAddress ip address
+ */
+ private IpElementId(IpAddress ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ /**
+ * Create a IP Element ID.
+ * @param ipAddress IP address
+ * @return IpElementId
+ */
+ public static IpElementId ipElement(IpAddress ipAddress) {
+ return new IpElementId(ipAddress);
+ }
+
+ /**
+ * Returns the ip address.
+ *
+ * @return ipAddress
+ */
+ public IpAddress ipAddress() {
+ return ipAddress;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ipAddress);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IpElementId) {
+ final IpElementId other = (IpElementId) obj;
+ return Objects.equals(this.ipAddress, other.ipAddress);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("ipAddress", ipAddress).toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Lambda.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Lambda.java
new file mode 100644
index 00000000..47d0d5f0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Lambda.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Abstraction of wavelength. Currently, this is just a marker interface
+ */
+public interface Lambda {
+ /**
+ * Create an Lambda instance with the specified wavelength index number.
+ *
+ * @param lambda index number
+ * @return an instance
+ */
+ static Lambda indexedLambda(long lambda) {
+ return new IndexedLambda(lambda);
+ }
+
+ /**
+ * Creates a Lambda instance with the specified arguments.
+ *
+ * @param gridType grid type
+ * @param channelSpacing channel spacing
+ * @param spacingMultiplier channel spacing multiplier
+ * @param slotGranularity slot width granularity
+ * @return new lambda with specified arguments
+ */
+ static Lambda ochSignal(GridType gridType, ChannelSpacing channelSpacing,
+ int spacingMultiplier, int slotGranularity) {
+ return new OchSignal(gridType, channelSpacing, spacingMultiplier, slotGranularity);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Link.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Link.java
new file mode 100644
index 00000000..7541f751
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Link.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Abstraction of a network infrastructure link.
+ */
+public interface Link extends Annotated, Provided, NetworkResource {
+
+ /**
+ * Coarse representation of the link type.
+ */
+ enum Type {
+ /**
+ * Signifies that this is a direct single-segment link.
+ */
+ DIRECT,
+
+ /**
+ * Signifies that this link is potentially comprised from multiple
+ * underlying segments or hops, and as such should be used to tag
+ * links traversing optical paths, tunnels or intervening 'dark'
+ * switches.
+ */
+ INDIRECT,
+
+ /**
+ * Signifies that this link is an edge, i.e. host link.
+ */
+ EDGE,
+
+ /**
+ * Signifies that this link represents a logical link backed by
+ * some form of a tunnel, e.g., GRE, MPLS, ODUk, OCH.
+ */
+ TUNNEL,
+
+ /**
+ * Signifies that this link is realized by fiber (either single channel or WDM).
+ */
+ OPTICAL,
+
+ /**
+ * Signifies that this link is a virtual link or a pseudo-wire.
+ */
+ VIRTUAL
+ }
+
+ /**
+ * Representation of the link state, which applies primarily only to
+ * configured durable links, i.e. those that need to remain present,
+ * but instead be marked as inactive.
+ */
+ enum State {
+ /**
+ * Signifies that a link is currently active.
+ */
+ ACTIVE,
+
+ /**
+ * Signifies that a link is currently active.
+ */
+ INACTIVE
+ }
+
+ /**
+ * Returns the link source connection point.
+ *
+ * @return link source connection point
+ */
+ ConnectPoint src();
+
+ /**
+ * Returns the link destination connection point.
+ *
+ * @return link destination connection point
+ */
+ ConnectPoint dst();
+
+ /**
+ * Returns the link type.
+ *
+ * @return link type
+ */
+ Type type();
+
+ /**
+ * Returns the link state.
+ *
+ * @return link state
+ */
+ State state();
+
+ /**
+ * Indicates if the link is to be considered durable.
+ *
+ * @return true if the link is durable
+ */
+ boolean isDurable();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/LinkKey.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/LinkKey.java
new file mode 100644
index 00000000..9cb66492
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/LinkKey.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+// TODO Consider renaming.
+// it's an identifier for a Link, but it's not ElementId, so not using LinkId.
+
+/**
+ * Immutable representation of a link identity.
+ */
+public final class LinkKey {
+
+ private final ConnectPoint src;
+ private final ConnectPoint dst;
+
+ /**
+ * Returns source connection point.
+ *
+ * @return source connection point
+ */
+ public ConnectPoint src() {
+ return src;
+ }
+
+ /**
+ * Returns destination connection point.
+ *
+ * @return destination connection point
+ */
+ public ConnectPoint dst() {
+ return dst;
+ }
+
+ /**
+ * Creates a link identifier with source and destination connection point.
+ *
+ * @param src source connection point
+ * @param dst destination connection point
+ */
+ private LinkKey(ConnectPoint src, ConnectPoint dst) {
+ this.src = checkNotNull(src);
+ this.dst = checkNotNull(dst);
+ }
+
+ /**
+ * Creates a link identifier with source and destination connection point.
+ *
+ * @param src source connection point
+ * @param dst destination connection point
+ * @return a link identifier
+ */
+ public static LinkKey linkKey(ConnectPoint src, ConnectPoint dst) {
+ return new LinkKey(src, dst);
+ }
+
+ /**
+ * Creates a link identifier for the specified link.
+ *
+ * @param link link descriptor
+ * @return a link identifier
+ */
+ public static LinkKey linkKey(Link link) {
+ return new LinkKey(link.src(), link.dst());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(src, dst);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof LinkKey) {
+ final LinkKey other = (LinkKey) obj;
+ return Objects.equals(this.src, other.src) &&
+ Objects.equals(this.dst, other.dst);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("src", src)
+ .add("dst", dst)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/MastershipRole.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/MastershipRole.java
new file mode 100644
index 00000000..78f65864
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/MastershipRole.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Representation of a relationship role of a controller instance to a device
+ * or a region of network environment.
+ */
+public enum MastershipRole {
+
+ /**
+ * Represents a relationship where the controller instance is the master
+ * to a device or a region of network environment.
+ */
+ MASTER,
+
+ /**
+ * Represents a relationship where the controller instance is the standby,
+ * i.e. potential master to a device or a region of network environment.
+ */
+ STANDBY,
+
+ /**
+ * Represents that the controller instance is not eligible to be the master
+ * to a device or a region of network environment.
+ */
+ NONE
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/MutableAnnotations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/MutableAnnotations.java
new file mode 100644
index 00000000..9b7f328e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/MutableAnnotations.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Represents an mutable set of simple key/value string annotations.
+ */
+public interface MutableAnnotations extends Annotations {
+
+ /**
+ * Returns the value of the specified annotation.
+ *
+ * @param key annotation key
+ * @param value annotation value
+ * @return self
+ */
+ MutableAnnotations set(String key, String value);
+
+ /**
+ * Clears the specified keys or the all keys if none were specified.
+ *
+ * @param keys keys to be cleared
+ * @return self
+ */
+ MutableAnnotations clear(String... keys);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/NetTools.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NetTools.java
new file mode 100644
index 00000000..fc561884
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NetTools.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Networking domain tools.
+ */
+public final class NetTools {
+
+ private NetTools() {
+ }
+
+ /**
+ * Converts DPIDs of the form xx:xx:xx:xx:xx:xx:xx to OpenFlow provider
+ * device URIs. The is helpful for converting DPIDs coming from configuration
+ * or REST to URIs that the core understands.
+ *
+ * @param dpid the DPID string to convert
+ * @return the URI string for this device
+ */
+ public static String dpidToUri(String dpid) {
+ return "of:" + dpid.replace(":", "");
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/NetworkResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NetworkResource.java
new file mode 100644
index 00000000..502208a0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/NetworkResource.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Representation of a network resource, e.g. a link, lambda, MPLS tag.
+ */
+public interface NetworkResource {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchPort.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchPort.java
new file mode 100644
index 00000000..eb956f2a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchPort.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Implementation of OCh port (Optical Channel).
+ * Also referred to as a line side port (L-port) or narrow band port.
+ * See ITU G.709 "Interfaces for the Optical Transport Network (OTN)"
+ */
+public class OchPort extends DefaultPort {
+
+ private final OduSignalType signalType;
+ private final boolean isTunable;
+ private final OchSignal lambda;
+
+ /**
+ * Creates an OCh port in the specified network element.
+ *
+ * @param element parent network element
+ * @param number port number
+ * @param isEnabled port enabled state
+ * @param signalType ODU signal type
+ * @param isTunable tunable wavelength capability
+ * @param lambda OCh signal
+ * @param annotations optional key/value annotations
+ */
+ public OchPort(Element element, PortNumber number, boolean isEnabled, OduSignalType signalType,
+ boolean isTunable, OchSignal lambda, Annotations... annotations) {
+ super(element, number, isEnabled, Type.OCH, 0, annotations);
+ this.signalType = signalType;
+ this.isTunable = isTunable;
+ this.lambda = checkNotNull(lambda);
+ }
+
+ /**
+ * Returns ODU signal type.
+ *
+ * @return ODU signal type
+ */
+ public OduSignalType signalType() {
+ return signalType;
+ }
+
+ /**
+ * Returns true if port is wavelength tunable.
+ *
+ * @return tunable wavelength capability
+ */
+ public boolean isTunable() {
+ return isTunable;
+ }
+
+ /**
+ * Returns OCh signal.
+ *
+ * @return OCh signal
+ */
+ public OchSignal lambda() {
+ return lambda;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(number(), isEnabled(), type(), signalType, isTunable, lambda, annotations());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof OchPort) {
+ final OchPort other = (OchPort) obj;
+ return Objects.equals(this.element().id(), other.element().id()) &&
+ Objects.equals(this.number(), other.number()) &&
+ Objects.equals(this.isEnabled(), other.isEnabled()) &&
+ Objects.equals(this.signalType, other.signalType) &&
+ Objects.equals(this.isTunable, other.isTunable) &&
+ Objects.equals(this.lambda, other.lambda) &&
+ Objects.equals(this.annotations(), other.annotations());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("element", element().id())
+ .add("number", number())
+ .add("isEnabled", isEnabled())
+ .add("type", type())
+ .add("signalType", signalType)
+ .add("isTunable", isTunable)
+ .add("lambda", lambda)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignal.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignal.java
new file mode 100644
index 00000000..5a5af34a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignal.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.util.Frequency;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Implementation of Lambda representing OCh (Optical Channel) Signal.
+ *
+ * <p>
+ * See ITU G.709 "Interfaces for the Optical Transport Network (OTN)".
+ * </p>
+ */
+public class OchSignal implements Lambda {
+
+ public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1);
+ public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5);
+ private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM;
+ private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
+
+
+ private final GridType gridType;
+ private final ChannelSpacing channelSpacing;
+ // Frequency = 193.1 THz + spacingMultiplier * channelSpacing
+ private final int spacingMultiplier;
+ // Slot width = slotGranularity * 12.5 GHz
+ private final int slotGranularity;
+
+ /**
+ * Creates an instance with the specified arguments.
+ * It it recommended to use {@link Lambda#ochSignal(GridType, ChannelSpacing, int, int)}
+ * unless you want to use the concrete type, OchSignal, directly.
+ *
+ * @param gridType grid type
+ * @param channelSpacing channel spacing
+ * @param spacingMultiplier channel spacing multiplier
+ * @param slotGranularity slot width granularity
+ */
+ public OchSignal(GridType gridType, ChannelSpacing channelSpacing,
+ int spacingMultiplier, int slotGranularity) {
+ this.gridType = checkNotNull(gridType);
+ this.channelSpacing = checkNotNull(channelSpacing);
+ // Negative values are permitted for spacingMultiplier
+ this.spacingMultiplier = spacingMultiplier;
+ checkArgument(slotGranularity > 0, "slotGranularity must be larger than 0, received %s", slotGranularity);
+ this.slotGranularity = slotGranularity;
+ }
+
+ /**
+ * Create OCh signal from channel number.
+ *
+ * @param channel channel number
+ * @param maxFrequency maximum frequency
+ * @param grid grid spacing frequency
+ */
+ public OchSignal(int channel, Frequency maxFrequency, Frequency grid) {
+ // Calculate center frequency
+ Frequency centerFrequency = maxFrequency.subtract(grid.multiply(channel - 1));
+
+ this.gridType = DEFAULT_OCH_GRIDTYPE;
+ this.channelSpacing = DEFAULT_CHANNEL_SPACING;
+ this.spacingMultiplier = (int) (centerFrequency.subtract(OchSignal.CENTER_FREQUENCY).asHz() / grid.asHz());
+ this.slotGranularity = (int) Math.round((double) grid.asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz());
+ }
+
+ public OchSignal(Frequency centerFrequency, ChannelSpacing channelSpacing, int slotGranularity) {
+ this.gridType = DEFAULT_OCH_GRIDTYPE;
+ this.channelSpacing = channelSpacing;
+ this.spacingMultiplier = (int) Math.round((double) centerFrequency.
+ subtract(OchSignal.CENTER_FREQUENCY).asHz() / channelSpacing().frequency().asHz());
+ this.slotGranularity = slotGranularity;
+ }
+
+ /**
+ * Returns grid type.
+ *
+ * @return grid type
+ */
+ public GridType gridType() {
+ return gridType;
+ }
+
+ /**
+ * Returns channel spacing.
+ *
+ * @return channel spacing
+ */
+ public ChannelSpacing channelSpacing() {
+ return channelSpacing;
+ }
+
+ /**
+ * Returns spacing multiplier.
+ *
+ * @return spacing multiplier
+ */
+ public int spacingMultiplier() {
+ return spacingMultiplier;
+ }
+
+ /**
+ * Returns slow width granularity.
+ *
+ * @return slow width granularity
+ */
+ public int slotGranularity() {
+ return slotGranularity;
+ }
+
+ /**
+ * Returns central frequency in MHz.
+ *
+ * @return frequency in MHz
+ */
+ public Frequency centralFrequency() {
+ return CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier));
+ }
+
+ /**
+ * Returns slot width.
+ *
+ * @return slot width
+ */
+ public Frequency slotWidth() {
+ return FLEX_GRID_SLOT.multiply(slotGranularity);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(gridType, channelSpacing, spacingMultiplier, slotGranularity);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof OchSignal)) {
+ return false;
+ }
+ final OchSignal other = (OchSignal) obj;
+ return Objects.equals(this.gridType, other.gridType)
+ && Objects.equals(this.channelSpacing, other.channelSpacing)
+ && Objects.equals(this.spacingMultiplier, other.spacingMultiplier)
+ && Objects.equals(this.slotGranularity, other.slotGranularity);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("gridType", gridType)
+ .add("channelSpacing", channelSpacing)
+ .add("spacingMultiplier", spacingMultiplier)
+ .add("slotGranularity", slotGranularity)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignalType.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignalType.java
new file mode 100644
index 00000000..9caf3f34
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OchSignalType.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Represents OCh (Optical Channel) signal type defined in
+ * Open Networking Foundation "Optical Transport Protocol Extensions Version 1.0".
+ */
+public enum OchSignalType {
+ /**
+ * Represents fixed grid.
+ */
+ FIXED_GRID,
+
+ /**
+ * Represents flex grid.
+ */
+ FLEX_GRID
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduCltPort.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduCltPort.java
new file mode 100644
index 00000000..e5602f36
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduCltPort.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of ODU client port (Optical channel Data Unit).
+ * Also referred to as a T-port or wide band port.
+ * See ITU G.709 "Interfaces for the Optical Transport Network (OTN)"
+ */
+
+public class OduCltPort extends DefaultPort {
+
+ public enum SignalType {
+ CLT_1GBE,
+ CLT_10GBE,
+ CLT_40GBE,
+ CLT_100GBE
+ }
+
+ private final SignalType signalType;
+
+
+ /**
+ * Creates an ODU client port in the specified network element.
+ *
+ * @param element parent network element
+ * @param number port number
+ * @param isEnabled port enabled state
+ * @param signalType ODU client signal type
+ * @param annotations optional key/value annotations
+ */
+ public OduCltPort(Element element, PortNumber number, boolean isEnabled,
+ SignalType signalType, Annotations... annotations) {
+ super(element, number, isEnabled, Type.ODUCLT, 0, annotations);
+ this.signalType = signalType;
+ }
+
+ /**
+ * Returns ODU client signal type.
+ *
+ * @return ODU client signal type
+ */
+ public SignalType signalType() {
+ return signalType;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(number(), isEnabled(), type(), signalType, annotations());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof OduCltPort) {
+ final OduCltPort other = (OduCltPort) obj;
+ return Objects.equals(this.element().id(), other.element().id()) &&
+ Objects.equals(this.number(), other.number()) &&
+ Objects.equals(this.isEnabled(), other.isEnabled()) &&
+ Objects.equals(this.signalType, other.signalType) &&
+ Objects.equals(this.annotations(), other.annotations());
+ }
+ return false;
+ }
+
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("element", element().id())
+ .add("number", number())
+ .add("isEnabled", isEnabled())
+ .add("type", type())
+ .add("signalType", signalType)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduSignalType.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduSignalType.java
new file mode 100644
index 00000000..014c893b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OduSignalType.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+/**
+ * Represents ODU (Optical channel Data Unit) signal type.
+ *
+ * <p>
+ * See ITU G.709 "Interfaces for the Optical Transport Network (OTN)" and
+ * Open Networking Foundation "Optical Transport Protocol Extensions Version 1.0".
+ * </p>
+ */
+public enum OduSignalType {
+ ODU0,
+ ODU1,
+ ODU2,
+ ODU2e,
+ ODU3,
+ ODU4
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/OmsPort.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OmsPort.java
new file mode 100644
index 00000000..753834b5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/OmsPort.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onlab.util.Frequency;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of OMS port (Optical Multiplexing Section).
+ * Also referred to as a WDM port or W-port.
+ * See ITU G.709 "Interfaces for the Optical Transport Network (OTN)"
+ *
+ * Assumes we only support fixed grid for now.
+ */
+public class OmsPort extends DefaultPort {
+
+ private final Frequency minFrequency; // Minimum frequency
+ private final Frequency maxFrequency; // Maximum frequency
+ private final Frequency grid; // Grid spacing frequency
+
+
+ /**
+ * Creates an OMS port in the specified network element.
+ *
+ * @param element parent network element
+ * @param number port number
+ * @param isEnabled port enabled state
+ * @param minFrequency minimum frequency
+ * @param maxFrequency maximum frequency
+ * @param grid grid spacing frequency
+ * @param annotations optional key/value annotations
+ */
+ public OmsPort(Element element, PortNumber number, boolean isEnabled,
+ Frequency minFrequency, Frequency maxFrequency, Frequency grid, Annotations... annotations) {
+ super(element, number, isEnabled, Type.OMS, 0, annotations);
+ this.minFrequency = minFrequency;
+ this.maxFrequency = maxFrequency;
+ this.grid = grid;
+ }
+
+ /**
+ * Returns the total number of channels on the port.
+ *
+ * @return total number of channels
+ */
+ public short totalChannels() {
+ Frequency diff = maxFrequency.subtract(minFrequency);
+ return (short) (diff.asHz() / (grid.asHz() + 1));
+ }
+
+ /**
+ * Returns the minimum frequency.
+ *
+ * @return minimum frequency
+ */
+ public Frequency minFrequency() {
+ return minFrequency;
+ }
+
+ /**
+ * Returns the maximum frequency.
+ *
+ * @return maximum frequency
+ */
+ public Frequency maxFrequency() {
+ return maxFrequency;
+ }
+
+ /**
+ * Returns the grid spacing frequency.
+ *
+ * @return grid spacing frequency
+ */
+ public Frequency grid() {
+ return grid;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(number(), isEnabled(), type(),
+ minFrequency, maxFrequency, grid, annotations());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof OmsPort) {
+ final OmsPort other = (OmsPort) obj;
+ return Objects.equals(this.element().id(), other.element().id()) &&
+ Objects.equals(this.number(), other.number()) &&
+ Objects.equals(this.isEnabled(), other.isEnabled()) &&
+ Objects.equals(this.minFrequency, other.minFrequency) &&
+ Objects.equals(this.maxFrequency, other.maxFrequency) &&
+ Objects.equals(this.grid, other.grid) &&
+ Objects.equals(this.annotations(), other.annotations());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("element", element().id())
+ .add("number", number())
+ .add("isEnabled", isEnabled())
+ .add("type", type())
+ .add("minFrequency", minFrequency)
+ .add("maxFrequency", maxFrequency)
+ .add("grid", grid)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Path.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Path.java
new file mode 100644
index 00000000..c9c20c4c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Path.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.util.List;
+
+/**
+ * Representation of a contiguous directed path in a network. Path comprises
+ * of a sequence of links, where adjacent links must share the same device,
+ * meaning that destination of the source of one link must coincide with the
+ * destination of the previous link.
+ */
+public interface Path extends Link {
+
+ /**
+ * Returns sequence of links comprising the path.
+ *
+ * @return list of links
+ */
+ List<Link> links();
+
+ /**
+ * Returns the path cost as a unit-less value.
+ *
+ * @return unit-less path cost
+ */
+ double cost();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Port.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Port.java
new file mode 100644
index 00000000..d70b1e17
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Port.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+
+/**
+ * Abstraction of a network port.
+ */
+public interface Port extends Annotated {
+
+ /** Represents coarse port type classification. */
+ enum Type {
+ /**
+ * Signifies copper-based connectivity.
+ */
+ COPPER,
+
+ /**
+ * Signifies optical fiber-based connectivity.
+ */
+ FIBER,
+
+ /**
+ * Signifies optical fiber-based packet port.
+ */
+ PACKET,
+
+ /**
+ * Signifies optical fiber-based optical tributary port (called T-port).
+ * The signal from the client side will be formed into a ITU G.709 (OTN) frame.
+ */
+ ODUCLT,
+
+ /**
+ * Signifies optical fiber-based Line-side port (called L-port).
+ */
+ OCH,
+
+ /**
+ * Signifies optical fiber-based WDM port (called W-port).
+ * Optical Multiplexing Section (See ITU G.709).
+ */
+ OMS,
+
+ /**
+ * Signifies virtual port.
+ */
+ VIRTUAL
+ }
+
+ /**
+ * Returns the parent network element to which this port belongs.
+ *
+ * @return parent network element
+ */
+ Element element();
+
+ /**
+ * Returns the port number.
+ *
+ * @return port number
+ */
+ PortNumber number();
+
+ /**
+ * Indicates whether or not the port is currently up and active.
+ *
+ * @return true if the port is operational
+ */
+ boolean isEnabled();
+
+ /**
+ * Returns the port type.
+ *
+ * @return port type
+ */
+ Type type();
+
+ /**
+ * Returns the current port speed in Mbps.
+ *
+ * @return current port speed
+ */
+ long portSpeed();
+
+ // TODO: more attributes?
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/PortNumber.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/PortNumber.java
new file mode 100644
index 00000000..03e6dba9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/PortNumber.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import com.google.common.primitives.UnsignedLongs;
+
+/**
+ * Representation of a port number.
+ */
+public final class PortNumber {
+
+ public static final PortNumber P0 = portNumber(0);
+
+ // TODO: revisit the max and the logical port value assignments
+
+ private static final long MAX_NUMBER = (2L * Integer.MAX_VALUE) + 1;
+
+
+ static final long IN_PORT_NUMBER = -8L;
+ static final long TABLE_NUMBER = -7L;
+ static final long NORMAL_NUMBER = -6L;
+ static final long FLOOD_NUMBER = -5L;
+ static final long ALL_NUMBER = -4L;
+ static final long LOCAL_NUMBER = -2L;
+ static final long CONTROLLER_NUMBER = -3L;
+
+ public static final PortNumber IN_PORT = new PortNumber(IN_PORT_NUMBER);
+ public static final PortNumber TABLE = new PortNumber(TABLE_NUMBER);
+ public static final PortNumber NORMAL = new PortNumber(NORMAL_NUMBER);
+ public static final PortNumber FLOOD = new PortNumber(FLOOD_NUMBER);
+ public static final PortNumber ALL = new PortNumber(ALL_NUMBER);
+ public static final PortNumber LOCAL = new PortNumber(LOCAL_NUMBER);
+ public static final PortNumber CONTROLLER = new PortNumber(CONTROLLER_NUMBER);
+
+ private final long number;
+ private final String name;
+ private final boolean hasName;
+
+ // Public creation is prohibited
+ private PortNumber(long number) {
+ this.number = number;
+ this.name = UnsignedLongs.toString(number);
+ this.hasName = false;
+ }
+
+ private PortNumber(long number, String name) {
+ this.number = number;
+ this.name = name;
+ this.hasName = true;
+ }
+
+ /**
+ * Returns the port number representing the specified long value.
+ *
+ * @param number port number as long value
+ * @return port number
+ */
+ public static PortNumber portNumber(long number) {
+ return new PortNumber(number);
+ }
+
+ /**
+ * Returns the port number representing the specified string value.
+ *
+ * @param string port number as string value
+ * @return port number
+ */
+ public static PortNumber portNumber(String string) {
+ return new PortNumber(UnsignedLongs.decode(string));
+ }
+
+ /**
+ * Returns the port number representing the specified long value and name.
+ *
+ * @param number port number as long value
+ * @param name port name as string value
+ * @return port number
+ */
+ public static PortNumber portNumber(long number, String name) {
+ return new PortNumber(number, name);
+ }
+
+ /**
+ * Indicates whether or not this port number is a reserved logical one or
+ * whether it corresponds to a normal physical port of a device or NIC.
+ *
+ * @return true if logical port number
+ */
+ public boolean isLogical() {
+ if (hasName) {
+ return false;
+ } else {
+ return (number < 0 || number > MAX_NUMBER);
+ }
+ }
+
+ /**
+ * Returns the backing long value.
+ *
+ * @return port number as long
+ */
+ public long toLong() {
+ return number;
+ }
+
+ /**
+ * Returns the backing string value.
+ *
+ * @return port name as string value
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Indicates whether this port number was created with a port name,
+ * or only with a number.
+ *
+ * @return true if port was created with name
+ */
+ public boolean hasName() {
+ return hasName;
+ }
+
+ private String decodeLogicalPort() {
+ if (number == CONTROLLER_NUMBER) {
+ return "CONTROLLER";
+ } else if (number == LOCAL_NUMBER) {
+ return "LOCAL";
+ } else if (number == ALL_NUMBER) {
+ return "ALL";
+ } else if (number == FLOOD_NUMBER) {
+ return "FLOOD";
+ } else if (number == NORMAL_NUMBER) {
+ return "NORMAL";
+ } else if (number == TABLE_NUMBER) {
+ return "TABLE";
+ } else if (number == IN_PORT_NUMBER) {
+ return "IN_PORT";
+ }
+ return "UNKNOWN";
+ }
+
+ @Override
+ public String toString() {
+ if (!isLogical()) {
+ return name;
+ } else {
+ return decodeLogicalPort();
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Long.hashCode(number);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof PortNumber) {
+ final PortNumber other = (PortNumber) obj;
+ return this.number == other.number;
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/Provided.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Provided.java
new file mode 100644
index 00000000..daf85e75
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/Provided.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Abstraction of an entity supplied by a provider.
+ */
+public interface Provided {
+
+ /**
+ * Returns the identifier of the provider which supplied the entity.
+ *
+ * @return provider identification
+ */
+ ProviderId providerId();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/SparseAnnotations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/SparseAnnotations.java
new file mode 100644
index 00000000..97961b3a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/SparseAnnotations.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.util.Set;
+
+/**
+ * Represents an set of sparse key/value string annotations capable of carrying
+ * annotation keys tagged for removal.
+ */
+public interface SparseAnnotations extends Annotations {
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Note that this set includes keys for any attributes tagged for removal.
+ * </p>
+ */
+ @Override
+ Set<String> keys();
+
+ /**
+ * Indicates whether the specified key has been tagged as removed. This is
+ * used for merging sparse annotation sets.
+ *
+ * @param key annotation key
+ * @return true if the previous annotation has been tagged for removal
+ */
+ boolean isRemoved(String key);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
new file mode 100644
index 00000000..7f157e95
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+/**
+ * Behaviour for handling various drivers for bridge configurations.
+ */
+public interface BridgeConfig extends HandlerBehaviour {
+
+ /**
+ * Add a bridge.
+ *
+ * @param bridgeName bridge name
+ */
+ void addBridge(BridgeName bridgeName);
+
+ /**
+ * Remove a bridge.
+ *
+ * @param bridgeName bridge name
+ */
+ void deleteBridge(BridgeName bridgeName);
+
+ /**
+ * Remove a bridge.
+ *
+ * @return bridge collection
+ */
+ Collection<BridgeDescription> getBridges();
+
+ /**
+ * Add a logical/virtual port.
+ *
+ * @param port port number
+ */
+ void addPort(PortDescription port);
+
+ /**
+ * Delete a logical/virtual port.
+ *
+ * @param port port number
+ */
+ void deletePort(PortDescription port);
+
+ /**
+ * Delete a logical/virtual port.
+ *
+ * @return collection of port
+ */
+ Collection<PortDescription> getPorts();
+
+ /**
+ * Get a collection of port.
+ *
+ * @return portNumbers set of PortNumber
+ */
+ Set<PortNumber> getPortNumbers();
+
+ /**
+ * Get logical/virtual ports by ifaceIds.
+ *
+ * @param ifaceIds the ifaceid that needed
+ * @return list of PortNumber
+ */
+ List<PortNumber> getLocalPorts(Iterable<String> ifaceIds);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeDescription.java
new file mode 100644
index 00000000..3c1d5542
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeDescription.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import org.onosproject.net.Description;
+import org.onosproject.net.DeviceId;
+
+/**
+ * The abstraction of bridge in OVSDB protocol.
+ */
+public interface BridgeDescription extends Description {
+
+ /**
+ * Returns bridge name.
+ *
+ * @return bridge name
+ */
+ BridgeName bridgeName();
+
+ /**
+ * Returns controller identifier that this bridge belongs to.
+ *
+ * @return controller identifier
+ */
+ DeviceId cotrollerDeviceId();
+
+ /**
+ * Returns bridge identifier .
+ *
+ * @return bridge identifier
+ */
+ DeviceId deviceId();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeName.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeName.java
new file mode 100644
index 00000000..3f782954
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeName.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Represents for a bridge name.
+ */
+public final class BridgeName {
+
+ private final String name;
+
+ // Public construction is prohibited
+ private BridgeName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Creates a bridge name using the supplied string.
+ *
+ * @param name bridge name
+ * @return BridgeName
+ */
+ public static BridgeName bridgeName(String name) {
+ return new BridgeName(name);
+ }
+
+ /**
+ * Returns the bridge name string.
+ *
+ * @return name string
+ */
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof BridgeName) {
+ final BridgeName that = (BridgeName) obj;
+ return this.getClass() == that.getClass() &&
+ Objects.equals(this.name, that.name);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("name", name)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ControllerConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ControllerConfig.java
new file mode 100644
index 00000000..bb8a788b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ControllerConfig.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import java.util.List;
+
+/**
+ * Device behaviour to obtain and set controllers at the device.
+ */
+public interface ControllerConfig {
+
+ //TODO: add other controller parameters as needed.
+
+ /**
+ * Obtain the list of controller which are currently configured.
+ * @return a list for controller descriptions
+ */
+ List<ControllerInfo> getControllers();
+
+ /**
+ * Set a list of controllers on a device.
+ * @param controllers a list of controller descriptions
+ */
+ void setControllers(List<ControllerInfo> controllers);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ControllerInfo.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ControllerInfo.java
new file mode 100644
index 00000000..9ff808a9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ControllerInfo.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import org.onlab.packet.IpAddress;
+
+/**
+ * Represents information for a device to connect to a controller.
+ */
+public class ControllerInfo {
+
+ public final IpAddress ip;
+ public final int tcpPort;
+
+ /**
+ * Information for contacting the controller.
+ *
+ * @param ip the ip address
+ * @param tcpPort the tcp port
+ */
+ public ControllerInfo(IpAddress ip, int tcpPort) {
+ this.ip = ip;
+ this.tcpPort = tcpPort;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultBridgeDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultBridgeDescription.java
new file mode 100644
index 00000000..6a6f670f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultBridgeDescription.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import java.util.Objects;
+
+import org.onosproject.net.AbstractDescription;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.SparseAnnotations;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * The default implementation of bridge.
+ */
+public final class DefaultBridgeDescription extends AbstractDescription
+ implements BridgeDescription {
+
+ private final BridgeName name;
+ private final DeviceId deviceId;
+ private final DeviceId controllerId;
+
+ public DefaultBridgeDescription(BridgeName name, DeviceId controllerId,
+ DeviceId deviceId,
+ SparseAnnotations... annotations) {
+ super(annotations);
+ this.name = name;
+ this.deviceId = deviceId;
+ this.controllerId = controllerId;
+ }
+
+ @Override
+ public BridgeName bridgeName() {
+ return name;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public DeviceId cotrollerDeviceId() {
+ return controllerId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, deviceId, controllerId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultBridgeDescription) {
+ final DefaultBridgeDescription that = (DefaultBridgeDescription) obj;
+ return this.getClass() == that.getClass()
+ && Objects.equals(this.name, that.name)
+ && Objects.equals(this.deviceId, that.deviceId)
+ && Objects.equals(this.controllerId, that.controllerId);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("name", name)
+ .add("deviceId", deviceId).add("controllerId", controllerId)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultNextGroup.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultNextGroup.java
new file mode 100644
index 00000000..ef1f9de7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultNextGroup.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+/**
+ * Default implementation of a next group.
+ */
+public class DefaultNextGroup implements NextGroup {
+
+ private final byte[] data;
+
+ public DefaultNextGroup(byte[] data) {
+ this.data = data;
+ }
+
+ @Override
+ public byte[] data() {
+ return data;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultTunnelDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultTunnelDescription.java
new file mode 100644
index 00000000..7554a3cb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/DefaultTunnelDescription.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import org.onosproject.net.AbstractDescription;
+import org.onosproject.net.SparseAnnotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+
+/**
+ * Default implementation of immutable tunnel description entity.
+ */
+@Beta
+public class DefaultTunnelDescription extends AbstractDescription
+ implements TunnelDescription {
+
+ private final TunnelEndPoint src;
+ private final TunnelEndPoint dst;
+ private final Type type;
+ // which a tunnel match up
+ // tunnel producer
+ private final TunnelName tunnelName; // name of a tunnel
+
+ /**
+ * Creates a tunnel description using the supplied information.
+ *
+ * @param src TunnelPoint source
+ * @param dst TunnelPoint destination
+ * @param type tunnel type
+ * @param tunnelName tunnel name
+ * @param annotations optional key/value annotations
+ */
+ public DefaultTunnelDescription(TunnelEndPoint src,
+ TunnelEndPoint dst, Type type,
+ TunnelName tunnelName,
+ SparseAnnotations... annotations) {
+ super(annotations);
+ this.src = src;
+ this.dst = dst;
+ this.type = type;
+ this.tunnelName = tunnelName;
+ }
+
+ @Override
+ public TunnelEndPoint src() {
+ return src;
+ }
+
+ @Override
+ public TunnelEndPoint dst() {
+ return dst;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public TunnelName tunnelName() {
+ return tunnelName;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("src", src())
+ .add("dst", dst())
+ .add("type", type())
+ .add("tunnelName", tunnelName())
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/IpTunnelEndPoint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/IpTunnelEndPoint.java
new file mode 100644
index 00000000..83ad4756
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/IpTunnelEndPoint.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour;
+
+import java.util.Objects;
+
+import com.google.common.annotations.Beta;
+import org.onlab.packet.IpAddress;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Represent for a tunnel point using ip address.
+ */
+@Beta
+public final class IpTunnelEndPoint implements TunnelEndPoint {
+
+ private final IpAddress ip;
+
+ /**
+ * Public construction is prohibited.
+ * @param ip ip address
+ */
+ private IpTunnelEndPoint(IpAddress ip) {
+ this.ip = ip;
+ }
+
+ /**
+ * Create a IP tunnel end point.
+ * @param ip IP address
+ * @return IpTunnelEndPoint
+ */
+ public static IpTunnelEndPoint ipTunnelPoint(IpAddress ip) {
+ return new IpTunnelEndPoint(ip);
+ }
+
+ /**
+ * Returns IP address.
+ * @return IP address
+ */
+ public IpAddress ip() {
+ return ip;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ip);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IpTunnelEndPoint) {
+ final IpTunnelEndPoint other = (IpTunnelEndPoint) obj;
+ return Objects.equals(this.ip, other.ip);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("ip", ip).toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/MplsQuery.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/MplsQuery.java
new file mode 100644
index 00000000..0e9f466d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/MplsQuery.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+/**
+ * A HandlerBehaviour to check the capability of MPLS.
+ */
+@Beta
+public interface MplsQuery extends HandlerBehaviour {
+
+ /**
+ * Indicates if MPLS can be used at the port.
+
+ * @param port port to be checked for the capability
+ * @return true if MPLS can be used at the port, false otherwise.
+ */
+ boolean isEnabled(PortNumber port);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/NextGroup.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/NextGroup.java
new file mode 100644
index 00000000..b5a3891c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/NextGroup.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+/**
+ * Opaque data type for carrying group-like information.
+ * Only relevant to a pipeliner driver.
+ */
+public interface NextGroup {
+
+ /**
+ * Serialized form of the next group.
+ * @return a byte array.
+ */
+ byte[] data();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/Pipeliner.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/Pipeliner.java
new file mode 100644
index 00000000..dcfc5883
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/Pipeliner.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+
+/**
+ * Behaviour for handling various pipelines.
+ */
+public interface Pipeliner extends HandlerBehaviour {
+
+ /**
+ * Initializes the driver with context required for its operation.
+ *
+ * @param deviceId the deviceId
+ * @param context processing context
+ */
+ void init(DeviceId deviceId, PipelinerContext context);
+
+ /**
+ * Installs the filtering rules onto the device.
+ *
+ * @param filterObjective a filtering objective
+ */
+ void filter(FilteringObjective filterObjective);
+
+ /**
+ * Installs the forwarding rules onto the device.
+ *
+ * @param forwardObjective a forwarding objective
+ */
+ void forward(ForwardingObjective forwardObjective);
+
+ /**
+ * Installs the next hop elements into the device.
+ *
+ * @param nextObjective a next objectives
+ */
+ void next(NextObjective nextObjective);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PipelinerContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PipelinerContext.java
new file mode 100644
index 00000000..d0ca42b1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PipelinerContext.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.net.flowobjective.FlowObjectiveStore;
+
+/**
+ * Processing context and supporting services for the pipeline behaviour.
+ */
+public interface PipelinerContext {
+
+ /**
+ * Returns the service directory which can be used to obtain references
+ * to various supporting services.
+ *
+ * @return service directory
+ */
+ ServiceDirectory directory();
+
+ /**
+ * Returns the Objective Store where data can be stored and retrieved.
+ * @return the flow objective store
+ */
+ FlowObjectiveStore store();
+
+ // TODO: add means to store and access shared state
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PortAdmin.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PortAdmin.java
new file mode 100644
index 00000000..141e27dc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PortAdmin.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+/**
+ * Means to administratively enable/disable a logical port at the device.
+ */
+public interface PortAdmin extends HandlerBehaviour {
+
+ /**
+ * Enable/disable administratively a port.
+ *
+ * @param port a port description containing the desired port state
+ */
+ void enable(PortDescription port);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PortConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PortConfig.java
new file mode 100644
index 00000000..83dd99d8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/PortConfig.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import com.google.common.primitives.UnsignedInteger;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+/**
+ * Means to configure a logical port at the device.
+ */
+public interface PortConfig extends HandlerBehaviour {
+
+ /**
+ * Apply QoS configuration on a device.
+ * @param port a port description
+ * @param queueId an unsigned integer
+ */
+ void applyQoS(PortDescription port, UnsignedInteger queueId);
+
+ /**
+ * Remove a QoS configuration.
+ * @param port a port description
+ */
+ void removeQoS(PortDescription port);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/QueueConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/QueueConfig.java
new file mode 100644
index 00000000..22f3ecb7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/QueueConfig.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import com.google.common.primitives.UnsignedInteger;
+
+import java.util.Set;
+
+/**
+ * Means to alter a device's dataplane queues.
+ */
+public interface QueueConfig {
+
+ /**
+ * Obtain all queues configured on a device.
+ *
+ * @return a list of queue descriptions
+ */
+ Set<QueueInfo> getQueues();
+
+ /**
+ * Obtain a specific queue given a queue id.
+ *
+ * @param queueId an unsigned integer representing a queue id
+ * @return a queue description
+ */
+ QueueInfo getQueue(UnsignedInteger queueId);
+
+ /**
+ * Add a queue to a device.
+ *
+ * @param queue a queue description
+ */
+ void addQueue(QueueInfo queue);
+
+ /**
+ * Remove a queue from a device.
+ *
+ * @param queueId an unsigned integer
+ */
+ void removeQueue(UnsignedInteger queueId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/QueueInfo.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/QueueInfo.java
new file mode 100644
index 00000000..25852b36
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/QueueInfo.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import com.google.common.primitives.UnsignedInteger;
+
+/**
+ * Represents a dataplane queue.
+ */
+public class QueueInfo {
+
+ public enum Type {
+ /**
+ * Supports burst and priority as well as min and max rates.
+ */
+ FULL,
+
+ /**
+ * Only support min and max rates.
+ */
+ MINMAX
+ }
+
+ private final UnsignedInteger queueId;
+ private final Type type;
+ private final long minRate;
+ private final long maxRate;
+ private final long burst;
+ private final long priority;
+
+ public QueueInfo(UnsignedInteger queueId, Type type, long minRate,
+ long maxRate, long burst, long priority) {
+ this.queueId = queueId;
+ this.type = type;
+ this.minRate = minRate;
+ this.maxRate = maxRate;
+ this.burst = burst;
+ this.priority = priority;
+ }
+
+ //TODO builder
+ // public static QueueInfoBuilder builder() {}
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
new file mode 100644
index 00000000..7e79a57e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import java.util.Collection;
+
+import org.onosproject.net.driver.HandlerBehaviour;
+
+/**
+ * Behaviour for handling various drivers for tunnel configuration.
+ */
+public interface TunnelConfig extends HandlerBehaviour {
+
+ /**
+ * Creates a tunnel on this device.
+ *
+ * @param tunnel tunnel descriptor
+ */
+ void createTunnel(TunnelDescription tunnel);
+
+ /**
+ * Removes a tunnel on this device.
+ *
+ * @param tunnel tunnel descriptor
+ */
+ void removeTunnel(TunnelDescription tunnel);
+
+ /**
+ * Updates a tunnel on this device.
+ *
+ * @param tunnel tunnel descriptor
+ */
+ void updateTunnel(TunnelDescription tunnel);
+
+ /**
+ * Returns tunnels created on this device.
+ *
+ * @return collection of tunnels
+ */
+ Collection<TunnelDescription> getTunnels();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelDescription.java
new file mode 100755
index 00000000..b2fb6996
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelDescription.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import org.onosproject.net.Annotated;
+import org.onosproject.net.Description;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Describes a tunnel.
+ */
+@Beta
+public interface TunnelDescription extends Description, Annotated {
+
+ /**
+ * Tunnel technology type.
+ */
+ enum Type {
+ /**
+ * Signifies that this is a MPLS tunnel.
+ */
+ MPLS,
+ /**
+ * Signifies that this is a L2 tunnel.
+ */
+ VLAN,
+ /**
+ * Signifies that this is a DC L2 extension tunnel.
+ */
+ VXLAN,
+ /**
+ * Signifies that this is a L3 tunnel.
+ */
+ GRE,
+ /**
+ * Signifies that this is a L1 OTN tunnel.
+ */
+ ODUK,
+ /**
+ * Signifies that this is a L0 OCH tunnel.
+ */
+ OCH
+ }
+
+ /**
+ * Returns the connection point source.
+ *
+ * @return tunnel source ConnectionPoint
+ */
+ TunnelEndPoint src();
+
+ /**
+ * Returns the connection point destination.
+ *
+ * @return tunnel destination
+ */
+ TunnelEndPoint dst();
+
+ /**
+ * Returns the tunnel type.
+ *
+ * @return tunnel type
+ */
+ Type type();
+
+ /**
+ * Return the name of a tunnel.
+ *
+ * @return Tunnel Name
+ */
+ TunnelName tunnelName();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java
new file mode 100644
index 00000000..c354c38d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents for source end point or destination end point of a tunnel. Maybe a tunnel
+ * based on ConnectPoint, IpAddress, MacAddress and so on is built.
+ */
+@Beta
+public interface TunnelEndPoint {
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelName.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelName.java
new file mode 100644
index 00000000..9be26549
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelName.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Objects;
+
+/**
+ * Represents for a unique tunnel name. TunnelId is generated by ONOS while
+ * TunnelName is given by producer. The consumer can borrow tunnels with
+ * TunnelId or TunnelName.
+ */
+@Beta
+public final class TunnelName {
+ private final String str;
+
+ // Default constructor for serialization
+ private TunnelName(String tunnelName) {
+ this.str = tunnelName;
+ }
+
+
+ /**
+ * Creates a tunnel name using the supplied URI string.
+ *
+ * @param tunnelName tunnel name string
+ * @return tunnel name object
+ */
+ public static TunnelName tunnelName(String tunnelName) {
+ return new TunnelName(tunnelName);
+ }
+
+ /**
+ * The string of tunnel name.
+ *
+ * @return the string of tunnel name
+ */
+ public String value() {
+ return str;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(str);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof TunnelName) {
+ final TunnelName that = (TunnelName) obj;
+ return this.getClass() == that.getClass()
+ && Objects.equals(this.str, that.str);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return str;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/VlanQuery.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/VlanQuery.java
new file mode 100644
index 00000000..a1057c90
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/VlanQuery.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.behaviour;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+/**
+ * A HandlerBehaviour to check the capability of VLAN.
+ */
+@Beta
+public interface VlanQuery extends HandlerBehaviour {
+
+ /**
+ * Indicates if VLAN can be used at the port.
+ *
+ * @param port port to be checked for the capability
+ * @return true if VLAN can be used at the port, false otherwise.
+ */
+ boolean isEnabled(PortNumber port);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/package-info.java
new file mode 100644
index 00000000..f0a9a5e5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Abstractions of various device configuration or device adaptation behaviours;
+ * counterpart to the device driver subsystem.
+ */
+package org.onosproject.net.behaviour; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/Config.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/Config.java
new file mode 100644
index 00000000..5cdc0c12
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/Config.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Lists;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Function;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Base abstraction of a configuration facade for a specific subject. Derived
+ * classes should keep all state in the specified JSON tree as that is the
+ * only state that will be distributed or persisted; this class is merely
+ * a facade for interacting with a particular facet of configuration on a
+ * given subject.
+ *
+ * @param <S> type of subject
+ */
+@Beta
+public abstract class Config<S> {
+
+ protected S subject;
+ protected String key;
+
+ protected JsonNode node;
+ protected ObjectNode object;
+ protected ArrayNode array;
+ protected ObjectMapper mapper;
+
+ protected ConfigApplyDelegate delegate;
+
+ /**
+ * Initializes the configuration behaviour with necessary context.
+ *
+ * @param subject configuration subject
+ * @param key configuration key
+ * @param node JSON node where configuration data is stored
+ * @param mapper JSON object mapper
+ * @param delegate delegate context
+ */
+ public void init(S subject, String key, JsonNode node, ObjectMapper mapper,
+ ConfigApplyDelegate delegate) {
+ this.subject = checkNotNull(subject);
+ this.key = key;
+ this.node = checkNotNull(node);
+ this.object = node instanceof ObjectNode ? (ObjectNode) node : null;
+ this.array = node instanceof ArrayNode ? (ArrayNode) node : null;
+ this.mapper = checkNotNull(mapper);
+ this.delegate = checkNotNull(delegate);
+ }
+
+ /**
+ * Returns the specific subject to which this configuration pertains.
+ *
+ * @return configuration subject
+ */
+ public S subject() {
+ return subject;
+ }
+
+ /**
+ * Returns the configuration key. This is primarily aimed for use in
+ * composite JSON trees in external representations and has no bearing on
+ * the internal behaviours.
+ *
+ * @return configuration key
+ */
+ public String key() {
+ return key;
+ }
+
+ /**
+ * Returns the JSON node that contains the configuration data.
+ *
+ * @return JSON node backing the configuration
+ */
+ public JsonNode node() {
+ return node;
+ }
+
+ /**
+ * Applies any configuration changes made via this configuration.
+ */
+ public void apply() {
+ delegate.onApply(this);
+ }
+
+
+ // Miscellaneous helpers for interacting with JSON
+
+ /**
+ * Gets the specified property as a string.
+ *
+ * @param name property name
+ * @param defaultValue default value if property not set
+ * @return property value or default value
+ */
+ protected String get(String name, String defaultValue) {
+ return object.path(name).asText(defaultValue);
+ }
+
+ /**
+ * Sets the specified property as a string or clears it if null value given.
+ *
+ * @param name property name
+ * @param value new value or null to clear the property
+ * @return self
+ */
+ protected Config<S> setOrClear(String name, String value) {
+ if (value != null) {
+ object.put(name, value);
+ } else {
+ object.remove(name);
+ }
+ return this;
+ }
+
+ /**
+ * Gets the specified property as a boolean.
+ *
+ * @param name property name
+ * @param defaultValue default value if property not set
+ * @return property value or default value
+ */
+ protected boolean get(String name, boolean defaultValue) {
+ return object.path(name).asBoolean(defaultValue);
+ }
+
+ /**
+ * Sets the specified property as a boolean or clears it if null value given.
+ *
+ * @param name property name
+ * @param value new value or null to clear the property
+ * @return self
+ */
+ protected Config<S> setOrClear(String name, Boolean value) {
+ if (value != null) {
+ object.put(name, value.booleanValue());
+ } else {
+ object.remove(name);
+ }
+ return this;
+ }
+
+ /**
+ * Gets the specified property as an integer.
+ *
+ * @param name property name
+ * @param defaultValue default value if property not set
+ * @return property value or default value
+ */
+ protected int get(String name, int defaultValue) {
+ return object.path(name).asInt(defaultValue);
+ }
+
+ /**
+ * Sets the specified property as an integer or clears it if null value given.
+ *
+ * @param name property name
+ * @param value new value or null to clear the property
+ * @return self
+ */
+ protected Config<S> setOrClear(String name, Integer value) {
+ if (value != null) {
+ object.put(name, value.intValue());
+ } else {
+ object.remove(name);
+ }
+ return this;
+ }
+
+ /**
+ * Gets the specified property as a long.
+ *
+ * @param name property name
+ * @param defaultValue default value if property not set
+ * @return property value or default value
+ */
+ protected long get(String name, long defaultValue) {
+ return object.path(name).asLong(defaultValue);
+ }
+
+ /**
+ * Sets the specified property as a long or clears it if null value given.
+ *
+ * @param name property name
+ * @param value new value or null to clear the property
+ * @return self
+ */
+ protected Config<S> setOrClear(String name, Long value) {
+ if (value != null) {
+ object.put(name, value.longValue());
+ } else {
+ object.remove(name);
+ }
+ return this;
+ }
+
+ /**
+ * Gets the specified property as a double.
+ *
+ * @param name property name
+ * @param defaultValue default value if property not set
+ * @return property value or default value
+ */
+ protected double get(String name, double defaultValue) {
+ return object.path(name).asDouble(defaultValue);
+ }
+
+ /**
+ * Sets the specified property as a double or clears it if null value given.
+ *
+ * @param name property name
+ * @param value new value or null to clear the property
+ * @return self
+ */
+ protected Config<S> setOrClear(String name, Double value) {
+ if (value != null) {
+ object.put(name, value.doubleValue());
+ } else {
+ object.remove(name);
+ }
+ return this;
+ }
+
+ /**
+ * Gets the specified property as an enum.
+ *
+ * @param name property name
+ * @param defaultValue default value if property not set
+ * @param enumClass the enum class
+ * @param <E> type of enum
+ * @return property value or default value
+ */
+ protected <E extends Enum<E>> E get(String name, E defaultValue, Class<E> enumClass) {
+ return Enum.valueOf(enumClass, object.path(name).asText(defaultValue.toString()));
+ }
+
+ /**
+ * Sets the specified property as a double or clears it if null value given.
+ *
+ * @param name property name
+ * @param value new value or null to clear the property
+ * @param <E> type of enum
+ * @return self
+ */
+ protected <E extends Enum> Config<S> setOrClear(String name, E value) {
+ if (value != null) {
+ object.put(name, value.toString());
+ } else {
+ object.remove(name);
+ }
+ return this;
+ }
+
+ /**
+ * Gets the specified array property as a list of items.
+ *
+ * @param name property name
+ * @param function mapper from string to item
+ * @param <T> type of item
+ * @return list of items
+ */
+ protected <T> List<T> getList(String name, Function<String, T> function) {
+ List<T> list = Lists.newArrayList();
+ ArrayNode arrayNode = (ArrayNode) object.path(name);
+ arrayNode.forEach(i -> list.add(function.apply(i.asText())));
+ return list;
+ }
+
+ /**
+ * Sets the specified property as an array of items in a given collection or
+ * clears it if null is given.
+ *
+ * @param name propertyName
+ * @param collection collection of items
+ * @param <T> type of items
+ * @return self
+ */
+ protected <T> Config<S> setOrClear(String name, Collection<T> collection) {
+ if (collection == null) {
+ object.remove(name);
+ } else {
+ ArrayNode arrayNode = mapper.createArrayNode();
+ collection.forEach(i -> arrayNode.add(i.toString()));
+ object.set(name, arrayNode);
+ }
+ return this;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigApplyDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigApplyDelegate.java
new file mode 100644
index 00000000..1160a097
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigApplyDelegate.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Delegate for notification when configuration changes have been applied.
+ */
+@Beta
+public interface ConfigApplyDelegate {
+
+ /**
+ * Processes changes applied to the specified configuration.
+ *
+ * @param config changed configuration
+ */
+ void onApply(Config config);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigFactory.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigFactory.java
new file mode 100644
index 00000000..25a34025
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigFactory.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Base abstract factory for creating configurations for the specified subject type.
+ *
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ */
+@Beta
+public abstract class ConfigFactory<S, C extends Config<S>> {
+
+ private final SubjectFactory<S> subjectFactory;
+ private final Class<C> configClass;
+ private final String configKey;
+ private final boolean isList;
+
+ /**
+ * Creates a new configuration factory for the specified class of subjects
+ * capable of generating the configurations of the specified class. The
+ * subject and configuration class keys are used merely as keys for use in
+ * composite JSON trees.
+ *
+ * @param subjectFactory subject factory
+ * @param configClass configuration class
+ * @param configKey configuration class key
+ */
+ protected ConfigFactory(SubjectFactory<S> subjectFactory,
+ Class<C> configClass, String configKey) {
+ this(subjectFactory, configClass, configKey, false);
+ }
+
+ /**
+ * Creates a new configuration factory for the specified class of subjects
+ * capable of generating the configurations of the specified class. The
+ * subject and configuration class keys are used merely as keys for use in
+ * composite JSON trees.
+ * <p>
+ * Note that configurations backed by JSON array are not easily extensible
+ * at the top-level as they are inherently limited to holding an ordered
+ * list of items.
+ * </p>
+ *
+ * @param subjectFactory subject factory
+ * @param configClass configuration class
+ * @param configKey configuration class key
+ * @param isList true to indicate backing by JSON array
+ */
+ protected ConfigFactory(SubjectFactory<S> subjectFactory,
+ Class<C> configClass, String configKey,
+ boolean isList) {
+ this.subjectFactory = subjectFactory;
+ this.configClass = configClass;
+ this.configKey = configKey;
+ this.isList = isList;
+ }
+
+ /**
+ * Returns the class of the subject to which this factory applies.
+ *
+ * @return subject type
+ */
+ public SubjectFactory<S> subjectFactory() {
+ return subjectFactory;
+ }
+
+ /**
+ * Returns the class of the configuration which this factory generates.
+ *
+ * @return configuration type
+ */
+ public Class<C> configClass() {
+ return configClass;
+ }
+
+ /**
+ * Returns the unique key (within subject class) of this configuration.
+ * This is primarily aimed for use in composite JSON trees in external
+ * representations and has no bearing on the internal behaviours.
+ *
+ * @return configuration key
+ */
+ public String configKey() {
+ return configKey;
+ }
+
+ /**
+ * Creates a new but uninitialized configuration. Framework will initialize
+ * the configuration via {@link Config#init} method.
+ *
+ * @return new uninitialized configuration
+ */
+ public abstract C createConfig();
+
+ /**
+ * Indicates whether the configuration is a list and should be backed by
+ * a JSON array rather than JSON object.
+ *
+ * @return true if backed by JSON array
+ */
+ public boolean isList() {
+ return isList;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigOperator.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigOperator.java
new file mode 100644
index 00000000..505e8b3b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/ConfigOperator.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+/**
+ * An interface signifying a class that implements network configuration
+ * information from multiple sources. There is a natural ordering to the
+ * precedence of information, depending on its source:
+ * <ol>
+ * <li>Intents (from applications), which override</li>
+ * <li>Configs (from the network configuration subsystem), which override</li>
+ * <li>Descriptions (from southbound)</li>
+ * </ol>
+ * i.e., for a field representing the same attribute, the value from a Config
+ * entity will be used over that from the Description.
+ */
+public interface ConfigOperator {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigEvent.java
new file mode 100644
index 00000000..ee9ceadf
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigEvent.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes network configuration event.
+ */
+public class NetworkConfigEvent extends AbstractEvent<NetworkConfigEvent.Type, Object> {
+
+ private final Class configClass;
+
+ /**
+ * Type of network configuration events.
+ */
+ public enum Type {
+ /**
+ * Signifies that a network configuration was registered.
+ */
+ CONFIG_REGISTERED,
+
+ /**
+ * Signifies that a network configuration was unregistered.
+ */
+ CONFIG_UNREGISTERED,
+
+ /**
+ * Signifies that network configuration was added.
+ */
+ CONFIG_ADDED,
+
+ /**
+ * Signifies that network configuration was updated.
+ */
+ CONFIG_UPDATED,
+
+ /**
+ * Signifies that network configuration was removed.
+ */
+ CONFIG_REMOVED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject and the
+ * current time.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param configClass configuration class
+ */
+ public NetworkConfigEvent(Type type, Object subject, Class configClass) {
+ super(type, subject);
+ this.configClass = configClass;
+ }
+
+ /**
+ * Creates an event of a given type and for the specified subject and time.
+ *
+ * @param type device event type
+ * @param subject event subject
+ * @param configClass configuration class
+ * @param time occurrence time
+ */
+ public NetworkConfigEvent(Type type, Object subject, Class configClass, long time) {
+ super(type, subject, time);
+ this.configClass = configClass;
+ }
+
+ /**
+ * Returns the class of configuration that has been changed.
+ *
+ * @return configuration class
+ */
+ public Class configClass() {
+ return configClass;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigListener.java
new file mode 100644
index 00000000..73177755
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving network configuration related events.
+ */
+public interface NetworkConfigListener extends EventListener<NetworkConfigEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigRegistry.java
new file mode 100644
index 00000000..b4937d74
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigRegistry.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Set;
+
+/**
+ * Service for tracking network configuration factories. It is the basis for
+ * extensibility to allow various core subsystems or apps to register their
+ * own configuration factories that permit use to inject additional meta
+ * information about how various parts of the network should be viewed and
+ * treated.
+ */
+@Beta
+public interface NetworkConfigRegistry extends NetworkConfigService {
+
+ /**
+ * Registers the specified configuration factory.
+ *
+ * @param configFactory configuration factory
+ */
+ void registerConfigFactory(ConfigFactory configFactory);
+
+ /**
+ * Unregisters the specified configuration factory.
+ *
+ * @param configFactory configuration factory
+ */
+ void unregisterConfigFactory(ConfigFactory configFactory);
+
+ /**
+ * Returns set of all registered configuration factories.
+ *
+ * @return set of config factories
+ */
+ Set<ConfigFactory> getConfigFactories();
+
+ /**
+ * Returns set of all configuration factories registered for the specified
+ * class of subject.
+ *
+ * @param subjectClass subject class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return set of config factories
+ */
+ <S, C extends Config<S>> Set<ConfigFactory<S, C>> getConfigFactories(Class<S> subjectClass);
+
+ /**
+ * Returns the configuration factory that produces the specified class of
+ * configurations.
+ *
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return config factory
+ */
+ <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigService.java
new file mode 100644
index 00000000..c1eed980
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigService.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.annotations.Beta;
+import org.onosproject.event.ListenerService;
+
+import java.util.Set;
+
+/**
+ * Service for tracking network configurations which specify how the discovered
+ * network information should be interpreted and how the core or applications
+ * should act on or configure the network.
+ */
+@Beta
+public interface NetworkConfigService
+ extends ListenerService<NetworkConfigEvent, NetworkConfigListener> {
+
+ /**
+ * Returns the set of subject classes for which configuration may be
+ * available.
+ *
+ * @return set of subject classes
+ */
+ Set<Class> getSubjectClasses();
+
+ /**
+ * Returns the subject factory with the specified key.
+ *
+ * @param subjectKey subject class key
+ * @return subject class
+ */
+ SubjectFactory getSubjectFactory(String subjectKey);
+
+ /**
+ * Returns the subject factory for the specified class.
+ *
+ * @param subjectClass subject class
+ * @return subject class key
+ */
+ SubjectFactory getSubjectFactory(Class subjectClass);
+
+ /**
+ * Returns the configuration class with the specified key.
+ *
+ * @param subjectKey subject class key
+ * @param configKey subject class name
+ * @return subject class
+ */
+ Class<? extends Config> getConfigClass(String subjectKey, String configKey);
+
+ /**
+ * Returns the set of subjects for which some configuration is available.
+ *
+ * @param subjectClass subject class
+ * @param <S> type of subject
+ * @return set of configured subjects
+ */
+ <S> Set<S> getSubjects(Class<S> subjectClass);
+
+ /**
+ * Returns the set of subjects for which the specified configuration is
+ * available.
+ *
+ * @param subjectClass subject class
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return set of configured subjects
+ */
+ <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass);
+
+ /**
+ * Returns all configurations for the specified subject.
+ *
+ * @param subject configuration subject
+ * @param <S> type of subject
+ * @return set of configurations
+ */
+ <S> Set<? extends Config<S>> getConfigs(S subject);
+
+ /**
+ * Returns the configuration for the specified subject and configuration
+ * class if one is available; null otherwise.
+ *
+ * @param subject configuration subject
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return configuration or null if one is not available
+ */
+ <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass);
+
+ /**
+ * Creates a new configuration for the specified subject and configuration
+ * class. If one already exists, it is simply returned.
+ *
+ * @param subject configuration subject
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return configuration or null if one is not available
+ */
+ <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass);
+
+ /**
+ * Applies configuration for the specified subject and configuration
+ * class using the raw JSON object. If configuration already exists, it
+ * will be updated.
+ *
+ * @param subject configuration subject
+ * @param configClass configuration class
+ * @param json raw JSON node containing the configuration data
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return configuration or null if one is not available
+ */
+ <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass,
+ JsonNode json);
+
+ /**
+ * Clears any configuration for the specified subject and configuration
+ * class. If one does not exist, this call has no effect.
+ *
+ * @param subject configuration subject
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ */
+ <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStore.java
new file mode 100644
index 00000000..9dd66e8d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStore.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.onosproject.store.Store;
+
+import java.util.Set;
+
+/**
+ * Mechanism for distributing and storing network configuration information.
+ */
+public interface NetworkConfigStore extends Store<NetworkConfigEvent, NetworkConfigStoreDelegate> {
+
+ /**
+ * Adds a new configuration factory.
+ *
+ * @param configFactory configuration factory to add
+ */
+ void addConfigFactory(ConfigFactory configFactory);
+
+ /**
+ * Removes a configuration factory.
+ *
+ * @param configFactory configuration factory to remove
+ */
+ void removeConfigFactory(ConfigFactory configFactory);
+
+ /**
+ * Returns the configuration factory for the specified configuration class.
+ *
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return configuration factory or null
+ */
+ <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass);
+
+ /**
+ * Returns set of subjects of the specified class, which have some
+ * network configuration associated with them.
+ *
+ * @param subjectClass subject class
+ * @param <S> type of subject
+ * @return set of subject
+ */
+ <S> Set<S> getSubjects(Class<S> subjectClass);
+
+ /**
+ * Returns set of subjects of the specified class, which have the
+ * specified class of network configuration associated with them.
+ *
+ * @param subjectClass subject class
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return set of subject
+ */
+ <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass);
+
+ /**
+ * Returns set of configuration classes available for the specified subject.
+ *
+ * @param subject configuration subject
+ * @param <S> type of subject
+ * @return set of configuration classes
+ */
+ <S> Set<Class<? extends Config<S>>> getConfigClasses(S subject);
+
+ /**
+ * Get the configuration of the given class and for the specified subject.
+ *
+ * @param subject configuration subject
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return configuration object
+ */
+ <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass);
+
+ /**
+ * Creates a new configuration of the given class for the specified subject.
+ *
+ * @param subject configuration subject
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return configuration object
+ */
+ <S, C extends Config<S>> C createConfig(S subject, Class<C> configClass);
+
+ /**
+ * Applies configuration for the specified subject and configuration
+ * class using the raw JSON object. If configuration already exists, it
+ * will be updated.
+ *
+ * @param subject configuration subject
+ * @param configClass configuration class
+ * @param json raw JSON node containing the configuration data
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ * @return configuration object
+ */
+ <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass,
+ JsonNode json);
+
+ /**
+ * Clears the configuration of the given class for the specified subject.
+ *
+ * @param subject configuration subject
+ * @param configClass configuration class
+ * @param <S> type of subject
+ * @param <C> type of configuration
+ */
+ <S, C extends Config<S>> void clearConfig(S subject, Class<C> configClass);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStoreDelegate.java
new file mode 100644
index 00000000..15d3d3e8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Network configuration store delegate abstraction.
+ */
+public interface NetworkConfigStoreDelegate extends StoreDelegate<NetworkConfigEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/SubjectFactory.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/SubjectFactory.java
new file mode 100644
index 00000000..cd2db344
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/SubjectFactory.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config;
+
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Base abstract factory for creating configuration subjects from their
+ * string key image.
+ *
+ * @param <S> subject class
+ */
+@Beta
+public abstract class SubjectFactory<S> {
+
+ private final Class<S> subjectClass;
+ private final String subjectKey;
+
+ /**
+ * Creates a new configuration factory for the specified class of subjects
+ * capable of generating the configurations of the specified class. The
+ * subject and configuration class keys are used merely as keys for use in
+ * composite JSON trees.
+ *
+ * @param subjectClass subject class
+ * @param subjectKey subject class key
+ */
+ protected SubjectFactory(Class<S> subjectClass, String subjectKey) {
+ this.subjectClass = subjectClass;
+ this.subjectKey = subjectKey;
+ }
+
+ /**
+ * Returns the class of the subject to which this factory applies.
+ *
+ * @return subject type
+ */
+ public Class<S> subjectClass() {
+ return subjectClass;
+ }
+
+ /**
+ * Returns the unique key of this configuration subject class.
+ * This is primarily aimed for use in composite JSON trees in external
+ * representations and has no bearing on the internal behaviours.
+ *
+ * @return configuration key
+ */
+ public String subjectKey() {
+ return subjectKey;
+ }
+
+ /**
+ * Creates a configuration subject from its key image.
+ *
+ * @param subjectKey subject class key
+ * @return configuration subject
+ */
+ public abstract S createSubject(String subjectKey);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/AllowedEntityConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/AllowedEntityConfig.java
new file mode 100644
index 00000000..6e6663c4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/AllowedEntityConfig.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config.basics;
+
+import org.onosproject.net.config.Config;
+
+/**
+ * Base abstraction for network entities for which admission into control
+ * domain can be selectively configured, e.g. devices, end-stations, links
+ */
+public abstract class AllowedEntityConfig<S> extends Config<S> {
+
+ private static final String ALLOWED = "allowed";
+
+ /**
+ * Indicates whether the element is allowed for admission into the control
+ * domain.
+ *
+ * @return true if element is allowed
+ */
+ public boolean isAllowed() {
+ return get(ALLOWED, true);
+ }
+
+ /**
+ * Specifies whether the element is to be allowed for admission into the
+ * control domain.
+ *
+ * @param isAllowed true to allow; false to forbid; null to clear
+ * @return self
+ */
+ public AllowedEntityConfig isAllowed(Boolean isAllowed) {
+ return (AllowedEntityConfig) setOrClear(ALLOWED, isAllowed);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java
new file mode 100644
index 00000000..fd8bfa3e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config.basics;
+
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Basic configuration for network infrastructure devices.
+ */
+public class BasicDeviceConfig extends BasicElementConfig<DeviceId> {
+
+ public static final String TYPE = "type";
+ public static final String DRIVER = "driver";
+
+ /**
+ * Returns the device type.
+ *
+ * @return device type override
+ */
+ public Device.Type type() {
+ return get(TYPE, Device.Type.SWITCH, Device.Type.class);
+ }
+
+ /**
+ * Sets the device type.
+ *
+ * @param type device type override
+ * @return self
+ */
+ public BasicDeviceConfig type(Device.Type type) {
+ return (BasicDeviceConfig) setOrClear(TYPE, type);
+ }
+
+ /**
+ * Returns the device driver name.
+ *
+ * @return driver name of null if not set
+ */
+ public String driver() {
+ return get(DRIVER, subject.toString());
+ }
+
+ /**
+ * Sets the driver name.
+ *
+ * @param driverName new driver name; null to clear
+ * @return self
+ */
+ public BasicElementConfig driver(String driverName) {
+ return (BasicElementConfig) setOrClear(DRIVER, driverName);
+ }
+
+ // TODO: device port meta-data to be configured via BasicPortsConfig
+ // TODO: device credentials/keys
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
new file mode 100644
index 00000000..7b3248c9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config.basics;
+
+/**
+ * Basic configuration for network elements, e.g. devices, hosts. Such elements
+ * can have a friendly name, geo-coordinates, logical rack coordinates and
+ * an owner entity.
+ */
+public abstract class BasicElementConfig<S> extends AllowedEntityConfig<S> {
+
+ public static final String NAME = "name";
+
+ public static final String LATITUDE = "latitude";
+ public static final String LONGITUDE = "longitude";
+
+ public static final String RACK_ADDRESS = "rackAddress";
+ public static final String OWNER = "owner";
+
+ protected static final double DEFAULT_COORD = -1.0;
+
+ /**
+ * Returns friendly label for the element.
+ *
+ * @return friendly label or element id itself if not set
+ */
+ public String name() {
+ return get(NAME, subject.toString());
+ }
+
+ /**
+ * Sets friendly label for the element.
+ *
+ * @param name new friendly label; null to clear
+ * @return self
+ */
+ public BasicElementConfig name(String name) {
+ return (BasicElementConfig) setOrClear(NAME, name);
+ }
+
+ /**
+ * Returns element latitude.
+ *
+ * @return element latitude; -1 if not set
+ */
+ public double latitude() {
+ return get(LATITUDE, DEFAULT_COORD);
+ }
+
+ /**
+ * Sets the element latitude.
+ *
+ * @param latitude new latitude; null to clear
+ * @return self
+ */
+ public BasicElementConfig latitude(Double latitude) {
+ return (BasicElementConfig) setOrClear(LATITUDE, latitude);
+ }
+
+ /**
+ * Returns element latitude.
+ *
+ * @return element latitude; -1 if not set
+ */
+ public double longitude() {
+ return get(LONGITUDE, DEFAULT_COORD);
+ }
+
+ /**
+ * Sets the element longitude.
+ *
+ * @param longitude new longitude; null to clear
+ * @return self
+ */
+ public BasicElementConfig longitude(Double longitude) {
+ return (BasicElementConfig) setOrClear(LONGITUDE, longitude);
+ }
+
+ /**
+ * Returns the element rack address.
+ *
+ * @return rack address; null if not set
+ */
+ public String rackAddress() {
+ return get(RACK_ADDRESS, null);
+ }
+
+ /**
+ * Sets element rack address.
+ *
+ * @param address new rack address; null to clear
+ * @return self
+ */
+ public BasicElementConfig rackAddress(String address) {
+ return (BasicElementConfig) setOrClear(RACK_ADDRESS, address);
+ }
+
+ /**
+ * Returns owner of the element.
+ *
+ * @return owner or null if not set
+ */
+ public String owner() {
+ return get(OWNER, null);
+ }
+
+ /**
+ * Sets the owner of the element.
+ *
+ * @param owner new owner; null to clear
+ * @return self
+ */
+ public BasicElementConfig owner(String owner) {
+ return (BasicElementConfig) setOrClear(OWNER, owner);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java
new file mode 100644
index 00000000..2fe2b2c0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicHostConfig.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config.basics;
+
+import org.onosproject.net.HostId;
+
+/**
+ * Basic configuration for network end-station hosts.
+ */
+public class BasicHostConfig extends BasicElementConfig<HostId> {
+
+ // TODO: determine what aspects of configuration to add for hosts
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
new file mode 100644
index 00000000..b6068ee7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config.basics;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+
+import java.time.Duration;
+
+/**
+ * Basic configuration for network infrastructure link.
+ */
+public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> {
+
+ public static final String TYPE = "type";
+ public static final String LATENCY = "latency";
+ public static final String BANDWIDTH = "bandwidth";
+
+ /**
+ * Returns the link type.
+ *
+ * @return link type override
+ */
+ public Link.Type type() {
+ return get(TYPE, Link.Type.DIRECT, Link.Type.class);
+ }
+
+ /**
+ * Sets the link type.
+ *
+ * @param type link type override
+ * @return self
+ */
+ public BasicLinkConfig type(Link.Type type) {
+ return (BasicLinkConfig) setOrClear(TYPE, type);
+ }
+
+ /**
+ * Returns link latency in terms of nanos.
+ *
+ * @return link latency; -1 if not set
+ */
+ public Duration latency() {
+ return Duration.ofNanos(get(LATENCY, -1));
+ }
+
+ /**
+ * Sets the link latency.
+ *
+ * @param latency new latency; null to clear
+ * @return self
+ */
+ public BasicLinkConfig latency(Duration latency) {
+ Long nanos = latency == null ? null : latency.toNanos();
+ return (BasicLinkConfig) setOrClear(LATENCY, nanos);
+ }
+
+ /**
+ * Returns link bandwidth in terms of Mbps.
+ *
+ * @return link bandwidth; -1 if not set
+ */
+ public long bandwidth() {
+ return get(BANDWIDTH, -1);
+ }
+
+ /**
+ * Sets the link bandwidth.
+ *
+ * @param bandwidth new bandwidth; null to clear
+ * @return self
+ */
+ public BasicLinkConfig bandwidth(Long bandwidth) {
+ return (BasicLinkConfig) setOrClear(BANDWIDTH, bandwidth);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java
new file mode 100644
index 00000000..b06c4228
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/OpticalPortConfig.java
@@ -0,0 +1,175 @@
+package org.onosproject.net.config.basics;
+
+import java.util.Optional;
+
+import org.onosproject.net.config.Config;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Port;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+
+/**
+ * Configurations for an optical port on a device.
+ */
+public class OpticalPortConfig extends Config<ConnectPoint> {
+ // optical type {OMS, OCH, ODUClt, fiber}
+ public static final String TYPE = "type";
+
+ // port name. "name" is the alphanumeric name of the port, but "port" refers
+ // to the port number used as a name string (i.e., for ports without
+ // alphanumeric names).
+ public static final String NAME = "name";
+ public static final String PORT = "port";
+ public static final String STATIC_PORT = "staticPort";
+ public static final String STATIC_LAMBDA = "staticLambda";
+
+ // **Linc-OE : remove if it's not needed after all.**
+ public static final String SPEED = "speed";
+
+ /**
+ * Returns the Enum value representing the type of port.
+ *
+ * @return the port type, or null if invalid or unset
+ */
+ public Port.Type type() {
+ JsonNode type = object.path(TYPE);
+ if (type.isMissingNode()) {
+ return null;
+ }
+ return Port.Type.valueOf(type.asText());
+ }
+
+ /**
+ * Returns the port name associated with this port configuration. The Name
+ * is an alphanumeric string.
+ *
+ * @return the name of this port, else, an empty string
+ */
+ public String name() {
+ return getStringValue(NAME);
+ }
+
+ /**
+ * Returns a stringified representation of the port number, configured in
+ * some port types without an alphanumeric name as the port name.
+ *
+ * @return A string representation of the port number
+ */
+ public String numberName() {
+ return getStringValue(PORT);
+ }
+
+ /**
+ * Returns the string-representation of name of the output port. This is
+ * usually an OMS port for an OCH input ports, or an OCH port for ODU input
+ * ports.
+ *
+ * @return the name of this port, else, an empty string
+ */
+ public String staticPort() {
+ return getStringValue(STATIC_PORT);
+ }
+
+ private String getStringValue(String field) {
+ JsonNode name = object.path(field);
+ return name.isMissingNode() ? "" : name.asText();
+ }
+
+ /**
+ * Returns the output lambda configured for this port. The lambda value is
+ * expressed as a frequency value. If the port type doesn't have a notion of
+ * lambdas, this returns an empty Optional.
+ *
+ * @return an Optional that may contain a frequency value.
+ */
+ public Optional<Long> staticLambda() {
+ JsonNode sl = object.path(STATIC_LAMBDA);
+ if (sl.isMissingNode()) {
+ return Optional.empty();
+ }
+ return Optional.of(sl.asLong());
+ }
+
+ /**
+ * Returns the port speed configured for this port. If the port doesn't have
+ * a notion of speed, this returns an empty Optional.
+ *
+ * @return a port speed value whose default is 0.
+ */
+ public Optional<Integer> speed() {
+ JsonNode s = object.path(SPEED);
+ if (s.isMissingNode()) {
+ return Optional.empty();
+ }
+ return Optional.of(s.asInt());
+ }
+
+ /**
+ * Sets the port type, or updates it if it's already set. A null argument removes
+ * this field.
+ *
+ * @param type the port type
+ * @return this OpticalPortConfig instance
+ */
+ public OpticalPortConfig portType(Port.Type type) {
+ // if unspecified, ideally fall back on FIBER or PACKET.
+ String pt = (type == null) ? null : type.toString();
+ return (OpticalPortConfig) setOrClear(TYPE, pt);
+ }
+
+ /**
+ * Sets the port name, or updates it if already set. A null argument removes
+ * this field.
+ *
+ * @param name the port's name
+ * @return this OpticalPortConfig instance
+ */
+ public OpticalPortConfig portName(String name) {
+ return (OpticalPortConfig) setOrClear(NAME, name);
+ }
+
+ /**
+ * Sets the port name from port number, or updates it if already set. A null
+ * argument removes this field.
+ *
+ * @param name the port number, to be used as name
+ * @return this OpticalPortConfig instance
+ */
+ public OpticalPortConfig portNumberName(Long name) {
+ return (OpticalPortConfig) setOrClear(PORT, name);
+ }
+
+ /**
+ * Sets the output port name, or updates it if already set. A null argument
+ * removes this field.
+ *
+ * @param name the output port's name
+ * @return this OpticalPortConfig instance
+ */
+ public OpticalPortConfig staticPort(String name) {
+ return (OpticalPortConfig) setOrClear(STATIC_PORT, name);
+ }
+
+ /**
+ * Sets the output lambda index, or updates it if already set. A null argument
+ * removes this field.
+ *
+ * @param index the output lambda
+ * @return this OpticalPortConfig instance
+ */
+ public OpticalPortConfig staticLambda(Long index) {
+ return (OpticalPortConfig) setOrClear(STATIC_LAMBDA, index);
+ }
+
+ /**
+ * Sets the port speed, or updates it if already set. A null argument
+ * removes this field.
+ *
+ * @param bw the port bandwidth
+ * @return this OpticalPortConfig instance
+ */
+ public OpticalPortConfig speed(Integer bw) {
+ return (OpticalPortConfig) setOrClear(SPEED, bw);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/SubjectFactories.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/SubjectFactories.java
new file mode 100644
index 00000000..884f2e20
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/SubjectFactories.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.config.basics;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.LinkKey;
+import org.onosproject.net.config.SubjectFactory;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Set of subject factories for potential configuration subjects.
+ */
+public final class SubjectFactories {
+
+ // Construction forbidden
+ private SubjectFactories() {
+ }
+
+ // Required for resolving application identifiers
+ private static CoreService coreService;
+
+ public static final SubjectFactory<ApplicationId> APP_SUBJECT_FACTORY =
+ new SubjectFactory<ApplicationId>(ApplicationId.class, "apps") {
+ @Override
+ public ApplicationId createSubject(String key) {
+ return coreService.registerApplication(key);
+ }
+ };
+
+ public static final SubjectFactory<DeviceId> DEVICE_SUBJECT_FACTORY =
+ new SubjectFactory<DeviceId>(DeviceId.class, "devices") {
+ @Override
+ public DeviceId createSubject(String key) {
+ return DeviceId.deviceId(key);
+ }
+ };
+
+ public static final SubjectFactory<ConnectPoint> CONNECT_POINT_SUBJECT_FACTORY =
+ new SubjectFactory<ConnectPoint>(ConnectPoint.class, "ports") {
+ @Override
+ public ConnectPoint createSubject(String key) {
+ return ConnectPoint.deviceConnectPoint(key);
+ }
+ };
+
+ public static final SubjectFactory<HostId> HOST_SUBJECT_FACTORY =
+ new SubjectFactory<HostId>(HostId.class, "hosts") {
+ @Override
+ public HostId createSubject(String key) {
+ return HostId.hostId(key);
+ }
+ };
+
+ public static final SubjectFactory<LinkKey> LINK_SUBJECT_FACTORY =
+ new SubjectFactory<LinkKey>(LinkKey.class, "links") {
+ @Override
+ public LinkKey createSubject(String key) {
+ String[] cps = key.split("-");
+ checkArgument(cps.length == 2, "Incorrect link key format: %s", key);
+ return LinkKey.linkKey(ConnectPoint.deviceConnectPoint(cps[0]),
+ ConnectPoint.deviceConnectPoint(cps[1]));
+ }
+ };
+
+ /**
+ * Provides reference to the core service, which is required for
+ * application subject factory.
+ *
+ * @param service core service reference
+ */
+ public static void setCoreService(CoreService service) {
+ coreService = service;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/package-info.java
new file mode 100644
index 00000000..4d0f27e9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/basics/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Various basic builtin network configurations.
+ */
+package org.onosproject.net.config.basics; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/package-info.java
new file mode 100644
index 00000000..f300717a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Subsystem for tracking network environment configuration.
+ */
+package org.onosproject.net.config;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java
new file mode 100644
index 00000000..3a8c8c1f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.AbstractDescription;
+import org.onosproject.net.SparseAnnotations;
+import org.onlab.packet.ChassisId;
+
+import java.net.URI;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.Device.Type;
+
+/**
+ * Default implementation of immutable device description entity.
+ */
+public class DefaultDeviceDescription extends AbstractDescription
+ implements DeviceDescription {
+ private final URI uri;
+ private final Type type;
+ private final String manufacturer;
+ private final String hwVersion;
+ private final String swVersion;
+ private final String serialNumber;
+ private final ChassisId chassisId;
+
+ /**
+ * Creates a device description using the supplied information.
+ *
+ * @param uri device URI
+ * @param type device type
+ * @param manufacturer device manufacturer
+ * @param hwVersion device HW version
+ * @param swVersion device SW version
+ * @param serialNumber device serial number
+ * @param chassis chassis id
+ * @param annotations optional key/value annotations map
+ */
+ public DefaultDeviceDescription(URI uri, Type type, String manufacturer,
+ String hwVersion, String swVersion,
+ String serialNumber, ChassisId chassis,
+ SparseAnnotations... annotations) {
+ super(annotations);
+ this.uri = checkNotNull(uri, "Device URI cannot be null");
+ this.type = checkNotNull(type, "Device type cannot be null");
+ this.manufacturer = manufacturer;
+ this.hwVersion = hwVersion;
+ this.swVersion = swVersion;
+ this.serialNumber = serialNumber;
+ this.chassisId = chassis;
+ }
+
+ /**
+ * Creates a device description using the supplied information.
+ * @param base DeviceDescription to basic information
+ * @param annotations Annotations to use.
+ */
+ public DefaultDeviceDescription(DeviceDescription base,
+ SparseAnnotations... annotations) {
+ this(base.deviceURI(), base.type(), base.manufacturer(),
+ base.hwVersion(), base.swVersion(), base.serialNumber(),
+ base.chassisId(), annotations);
+ }
+
+ /**
+ * Creates a device description using the supplied information.
+ * @param base DeviceDescription to basic information (except for type)
+ * @param type device type
+ * @param annotations Annotations to use.
+ */
+ public DefaultDeviceDescription(DeviceDescription base, Type type, SparseAnnotations... annotations) {
+ this(base.deviceURI(), type, base.manufacturer(),
+ base.hwVersion(), base.swVersion(), base.serialNumber(),
+ base.chassisId(), annotations);
+ }
+
+ @Override
+ public URI deviceURI() {
+ return uri;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public String manufacturer() {
+ return manufacturer;
+ }
+
+ @Override
+ public String hwVersion() {
+ return hwVersion;
+ }
+
+ @Override
+ public String swVersion() {
+ return swVersion;
+ }
+
+ @Override
+ public String serialNumber() {
+ return serialNumber;
+ }
+
+ @Override
+ public ChassisId chassisId() {
+ return chassisId;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("uri", uri).add("type", type).add("mfr", manufacturer)
+ .add("hw", hwVersion).add("sw", swVersion)
+ .add("serial", serialNumber)
+ .toString();
+ }
+
+ // default constructor for serialization
+ private DefaultDeviceDescription() {
+ this.uri = null;
+ this.type = null;
+ this.manufacturer = null;
+ this.hwVersion = null;
+ this.swVersion = null;
+ this.serialNumber = null;
+ this.chassisId = null;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortDescription.java
new file mode 100644
index 00000000..572d201c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortDescription.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.AbstractDescription;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+
+import static org.onosproject.net.Port.Type;
+
+/**
+ * Default implementation of immutable port description.
+ */
+public class DefaultPortDescription extends AbstractDescription
+ implements PortDescription {
+
+ private static final long DEFAULT_SPEED = 1_000;
+
+ private final PortNumber number;
+ private final boolean isEnabled;
+ private final Type type;
+ private final long portSpeed;
+
+ /**
+ * Creates a port description using the supplied information.
+ *
+ * @param number port number
+ * @param isEnabled port enabled state
+ * @param annotations optional key/value annotations map
+ */
+ public DefaultPortDescription(PortNumber number, boolean isEnabled,
+ SparseAnnotations... annotations) {
+ this(number, isEnabled, Type.COPPER, DEFAULT_SPEED, annotations);
+ }
+
+ /**
+ * Creates a port description using the supplied information.
+ *
+ * @param number port number
+ * @param isEnabled port enabled state
+ * @param type port type
+ * @param portSpeed port speed in Mbps
+ * @param annotations optional key/value annotations map
+ */
+ public DefaultPortDescription(PortNumber number, boolean isEnabled,
+ Type type, long portSpeed,
+ SparseAnnotations...annotations) {
+ super(annotations);
+ this.number = number;
+ this.isEnabled = isEnabled;
+ this.type = type;
+ this.portSpeed = portSpeed;
+ }
+
+ // Default constructor for serialization
+ private DefaultPortDescription() {
+ this.number = null;
+ this.isEnabled = false;
+ this.portSpeed = DEFAULT_SPEED;
+ this.type = Type.COPPER;
+ }
+
+ /**
+ * Creates a port description using the supplied information.
+ *
+ * @param base PortDescription to get basic information from
+ * @param annotations optional key/value annotations map
+ */
+ public DefaultPortDescription(PortDescription base,
+ SparseAnnotations annotations) {
+ this(base.portNumber(), base.isEnabled(), base.type(), base.portSpeed(),
+ annotations);
+ }
+
+ @Override
+ public PortNumber portNumber() {
+ return number;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return isEnabled;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public long portSpeed() {
+ return portSpeed;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("number", number)
+ .add("isEnabled", isEnabled)
+ .add("type", type)
+ .add("portSpeed", portSpeed)
+ .add("annotations", annotations())
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortStatistics.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortStatistics.java
new file mode 100644
index 00000000..540a945f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortStatistics.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.DeviceId;
+
+/**
+ * Default implementation of immutable port statistics.
+ */
+public final class DefaultPortStatistics implements PortStatistics {
+
+ private final DeviceId deviceId;
+ private final int port;
+ private final long packetsReceived;
+ private final long packetsSent;
+ private final long bytesReceived;
+ private final long bytesSent;
+ private final long packetsRxDropped;
+ private final long packetsTxDropped;
+ private final long packetsRxErrors;
+ private final long packetsTxErrors;
+ private final long durationSec;
+ private final long durationNano;
+
+ private DefaultPortStatistics(DeviceId deviceId,
+ int port,
+ long packetsReceived,
+ long packetsSent,
+ long bytesReceived,
+ long bytesSent,
+ long packetsRxDropped,
+ long packetsTxDropped,
+ long packetsRxErrors,
+ long packetsTxErrors,
+ long durationSec,
+ long durationNano) {
+ this.deviceId = deviceId;
+ this.port = port;
+ this.packetsReceived = packetsReceived;
+ this.packetsSent = packetsSent;
+ this.bytesReceived = bytesReceived;
+ this.bytesSent = bytesSent;
+ this.packetsRxDropped = packetsRxDropped;
+ this.packetsTxDropped = packetsTxDropped;
+ this.packetsRxErrors = packetsRxErrors;
+ this.packetsTxErrors = packetsTxErrors;
+ this.durationSec = durationSec;
+ this.durationNano = durationNano;
+ }
+
+ // Constructor for serializer
+ private DefaultPortStatistics() {
+ this.deviceId = null;
+ this.port = 0;
+ this.packetsReceived = 0;
+ this.packetsSent = 0;
+ this.bytesReceived = 0;
+ this.bytesSent = 0;
+ this.packetsRxDropped = 0;
+ this.packetsTxDropped = 0;
+ this.packetsRxErrors = 0;
+ this.packetsTxErrors = 0;
+ this.durationSec = 0;
+ this.durationNano = 0;
+ }
+
+ /**
+ * Creates a builder for DefaultPortStatistics object.
+ *
+ * @return builder object for DefaultPortStatistics object
+ */
+ public static DefaultPortStatistics.Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public int port() {
+ return this.port;
+ }
+
+ @Override
+ public long packetsReceived() {
+ return this.packetsReceived;
+ }
+
+ @Override
+ public long packetsSent() {
+ return this.packetsSent;
+ }
+
+ @Override
+ public long bytesReceived() {
+ return this.bytesReceived;
+ }
+
+ @Override
+ public long bytesSent() {
+ return this.bytesSent;
+ }
+
+ @Override
+ public long packetsRxDropped() {
+ return this.packetsRxDropped;
+ }
+
+ @Override
+ public long packetsTxDropped() {
+ return this.packetsTxDropped;
+ }
+
+ @Override
+ public long packetsRxErrors() {
+ return this.packetsRxErrors;
+ }
+
+ @Override
+ public long packetsTxErrors() {
+ return this.packetsTxErrors;
+ }
+
+ @Override
+ public long durationSec() {
+ return this.durationSec;
+ }
+
+ @Override
+ public long durationNano() {
+ return this.durationNano;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("device: " + deviceId + ", ");
+
+ sb.append("port: " + this.port + ", ");
+ sb.append("pktRx: " + this.packetsReceived + ", ");
+ sb.append("pktTx: " + this.packetsSent + ", ");
+ sb.append("byteRx: " + this.bytesReceived + ", ");
+ sb.append("byteTx: " + this.bytesSent + ", ");
+ sb.append("pktRxErr: " + this.packetsRxErrors + ", ");
+ sb.append("pktTxErr: " + this.packetsTxErrors + ", ");
+ sb.append("pktRxDrp: " + this.packetsRxDropped + ", ");
+ sb.append("pktTxDrp: " + this.packetsTxDropped);
+
+ return sb.toString();
+ }
+
+ public static final class Builder {
+
+ DeviceId deviceId;
+ int port;
+ long packetsReceived;
+ long packetsSent;
+ long bytesReceived;
+ long bytesSent;
+ long packetsRxDropped;
+ long packetsTxDropped;
+ long packetsRxErrors;
+ long packetsTxErrors;
+ long durationSec;
+ long durationNano;
+
+ private Builder() {
+
+ }
+
+ /**
+ * Sets port number.
+ *
+ * @param port port number
+ * @return builder object
+ */
+ public Builder setPort(int port) {
+ this.port = port;
+
+ return this;
+ }
+
+ /**
+ * Sets the device identifier.
+ *
+ * @param deviceId device identifier
+ * @return builder object
+ */
+ public Builder setDeviceId(DeviceId deviceId) {
+ this.deviceId = deviceId;
+
+ return this;
+ }
+
+ /**
+ * Sets the number of packet received.
+ *
+ * @param packets number of packets received
+ * @return builder object
+ */
+ public Builder setPacketsReceived(long packets) {
+ packetsReceived = packets;
+
+ return this;
+ }
+
+ /**
+ * Sets the number of packets sent.
+ *
+ * @param packets number of packets sent
+ * @return builder object
+ */
+ public Builder setPacketsSent(long packets) {
+ packetsSent = packets;
+
+ return this;
+ }
+
+ /**
+ * Sets the number of received bytes.
+ *
+ * @param bytes number of received bytes.
+ * @return builder object
+ */
+ public Builder setBytesReceived(long bytes) {
+ bytesReceived = bytes;
+
+ return this;
+ }
+
+ /**
+ * Sets the number of sent bytes.
+ *
+ * @param bytes number of sent bytes
+ * @return builder object
+ */
+ public Builder setBytesSent(long bytes) {
+ bytesSent = bytes;
+
+ return this;
+ }
+
+ /**
+ * Sets the number of packets dropped by RX.
+ *
+ * @param packets number of packets dropped by RX
+ * @return builder object
+ */
+ public Builder setPacketsRxDropped(long packets) {
+ packetsRxDropped = packets;
+
+ return this;
+ }
+
+ /**
+ * Sets the number of packets dropped by TX.
+ *
+ * @param packets number of packets
+ * @return builder object
+ */
+ public Builder setPacketsTxDropped(long packets) {
+ packetsTxDropped = packets;
+
+ return this;
+ }
+
+ /**
+ * Sets the number of receive errors.
+ *
+ * @param packets number of receive errors
+ * @return builder object
+ */
+ public Builder setPacketsRxErrors(long packets) {
+ packetsRxErrors = packets;
+
+ return this;
+ }
+
+ /**
+ * Sets the number of transmit errors.
+ *
+ * @param packets number of transmit errors
+ * @return builder object
+ */
+ public Builder setPacketsTxErrors(long packets) {
+ packetsTxErrors = packets;
+
+ return this;
+ }
+
+ /**
+ * Sets the time port has been alive in seconds.
+ *
+ * @param sec time port has been alive in seconds
+ * @return builder object
+ */
+ public Builder setDurationSec(long sec) {
+ durationSec = sec;
+
+ return this;
+ }
+
+ /**
+ * Sets the time port has been alive in nano seconds.
+ *
+ * @param nano time port has been alive in nano seconds
+ * @return builder object
+ */
+ public Builder setDurationNano(long nano) {
+ durationNano = nano;
+
+ return this;
+ }
+
+ /**
+ * Creates a PortStatistics object.
+ *
+ * @return DefaultPortStatistics object
+ */
+ public DefaultPortStatistics build() {
+ return new DefaultPortStatistics(
+ deviceId,
+ port,
+ packetsReceived,
+ packetsSent,
+ bytesReceived,
+ bytesSent,
+ packetsRxDropped,
+ packetsTxDropped,
+ packetsRxErrors,
+ packetsTxErrors,
+ durationSec,
+ durationNano);
+ }
+
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceAdminService.java
new file mode 100644
index 00000000..500b6359
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceAdminService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.DeviceId;
+
+/**
+ * Service for administering the inventory of infrastructure devices.
+ */
+public interface DeviceAdminService extends DeviceService {
+
+ /**
+ * Removes the device with the specified identifier.
+ *
+ * @param deviceId device identifier
+ */
+ void removeDevice(DeviceId deviceId);
+
+ // TODO: add ability to administratively suspend/resume device
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceClockService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceClockService.java
new file mode 100644
index 00000000..5391999a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceClockService.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.Timestamp;
+
+/**
+ * Interface for a logical clock service that vends per device timestamps.
+ */
+public interface DeviceClockService {
+
+ /**
+ * Checks if this service can issue Timestamp for specified device.
+ *
+ * @param deviceId device identifier.
+ * @return true if timestamp can be issued for specified device
+ */
+ boolean isTimestampAvailable(DeviceId deviceId);
+
+ /**
+ * Returns a new timestamp for the specified deviceId.
+ *
+ * @param deviceId device identifier.
+ * @return timestamp.
+ */
+ Timestamp getTimestamp(DeviceId deviceId);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceDescription.java
new file mode 100644
index 00000000..64b84b5a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceDescription.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.Description;
+import org.onosproject.net.Device;
+import org.onlab.packet.ChassisId;
+
+import java.net.URI;
+
+/**
+ * Carrier of immutable information about a device.
+ */
+public interface DeviceDescription extends Description {
+
+ /**
+ * Protocol/provider specific URI that can be used to encode the identity
+ * information required to communicate with the device externally, e.g.
+ * datapath ID.
+ *
+ * @return provider specific URI for the device
+ */
+ URI deviceURI();
+
+ /**
+ * Returns the type of the infrastructure device.
+ *
+ * @return type of the device
+ */
+ Device.Type type();
+
+ /**
+ * Returns the device manufacturer name.
+ *
+ * @return manufacturer name
+ */
+ String manufacturer();
+
+ /**
+ * Returns the device hardware version.
+ *
+ * @return hardware version
+ */
+ String hwVersion();
+
+ /**
+ * Returns the device software version.
+ *
+ * @return software version
+ */
+ String swVersion();
+
+ /**
+ * Returns the device serial number.
+ *
+ * @return serial number
+ */
+ String serialNumber();
+
+ /**
+ * Returns a device chassis id.
+ *
+ * @return chassis id
+ */
+ ChassisId chassisId();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceEvent.java
new file mode 100644
index 00000000..18ab046f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceEvent.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.joda.time.LocalDateTime;
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.Device;
+import org.onosproject.net.Port;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Describes infrastructure device event.
+ */
+public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> {
+
+ private final Port port;
+
+ /**
+ * Type of device events.
+ */
+ public enum Type {
+ /**
+ * Signifies that a new device has been detected.
+ */
+ DEVICE_ADDED,
+
+ /**
+ * Signifies that some device attributes have changed; excludes
+ * availability changes.
+ */
+ DEVICE_UPDATED,
+
+ /**
+ * Signifies that a device has been removed.
+ */
+ DEVICE_REMOVED,
+
+ /**
+ * Signifies that a device has been administratively suspended.
+ */
+ DEVICE_SUSPENDED,
+
+ /**
+ * Signifies that a device has come online or has gone offline.
+ */
+ DEVICE_AVAILABILITY_CHANGED,
+
+ /**
+ * Signifies that a port has been added.
+ */
+ PORT_ADDED,
+
+ /**
+ * Signifies that a port has been updated.
+ */
+ PORT_UPDATED,
+
+ /**
+ * Signifies that a port has been removed.
+ */
+ PORT_REMOVED,
+
+ /**
+ * Signifies that port statistics has been updated.
+ */
+ PORT_STATS_UPDATED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified device and the
+ * current time.
+ *
+ * @param type device event type
+ * @param device event device subject
+ */
+ public DeviceEvent(Type type, Device device) {
+ this(type, device, null);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified device, port
+ * and the current time.
+ *
+ * @param type device event type
+ * @param device event device subject
+ * @param port optional port subject
+ */
+ public DeviceEvent(Type type, Device device, Port port) {
+ super(type, device);
+ this.port = port;
+ }
+
+ /**
+ * Creates an event of a given type and for the specified device and time.
+ *
+ * @param type device event type
+ * @param device event device subject
+ * @param port optional port subject
+ * @param time occurrence time
+ */
+ public DeviceEvent(Type type, Device device, Port port, long time) {
+ super(type, device, time);
+ this.port = port;
+ }
+
+ /**
+ * Returns the port subject.
+ *
+ * @return port subject or null if the event is not port specific.
+ */
+ public Port port() {
+ return port;
+ }
+
+ @Override
+ public String toString() {
+ if (port == null) {
+ return super.toString();
+ }
+ return toStringHelper(this)
+ .add("time", new LocalDateTime(time()))
+ .add("type", type())
+ .add("subject", subject())
+ .add("port", port)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceListener.java
new file mode 100644
index 00000000..c9809b81
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving infrastructure device related events.
+ */
+public interface DeviceListener extends EventListener<DeviceEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProvider.java
new file mode 100644
index 00000000..d8adbb0e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProvider.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Abstraction of a device information provider.
+ */
+public interface DeviceProvider extends Provider {
+
+ // TODO: consider how dirty the triggerProbe gets; if it costs too much, let's drop it
+
+ /**
+ * Triggers an asynchronous probe of the specified device, intended to
+ * determine whether the device is present or not. An indirect result of this
+ * should be invocation of
+ * {@link org.onosproject.net.device.DeviceProviderService#deviceConnected} )} or
+ * {@link org.onosproject.net.device.DeviceProviderService#deviceDisconnected}
+ * at some later point in time.
+ *
+ * @param deviceId ID of device to be probed
+ */
+ void triggerProbe(DeviceId deviceId);
+
+ /**
+ * Notifies the provider of a mastership role change for the specified
+ * device as decided by the core.
+ *
+ * @param deviceId device identifier
+ * @param newRole newly determined mastership role
+ */
+ void roleChanged(DeviceId deviceId, MastershipRole newRole);
+
+ /**
+ * Checks the reachability (connectivity) of a device from this provider.
+ *
+ * @param deviceId device identifier
+ * @return true if reachable, false otherwise
+ */
+ boolean isReachable(DeviceId deviceId);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProviderRegistry.java
new file mode 100644
index 00000000..a7ab7e36
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction of a device provider registry.
+ */
+public interface DeviceProviderRegistry
+ extends ProviderRegistry<DeviceProvider, DeviceProviderService> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProviderService.java
new file mode 100644
index 00000000..e266df09
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceProviderService.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.provider.ProviderService;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Service through which device providers can inject device information into
+ * the core.
+ */
+public interface DeviceProviderService extends ProviderService<DeviceProvider> {
+
+ // TODO: define suspend and remove actions on the mezzanine administrative API
+
+ /**
+ * Signals the core that a device has connected or has been detected somehow.
+ *
+ * @param deviceId device identifier
+ * @param deviceDescription information about network device
+ */
+ void deviceConnected(DeviceId deviceId, DeviceDescription deviceDescription);
+
+ /**
+ * Signals the core that a device has disconnected or is no longer reachable.
+ *
+ * @param deviceId identity of the device to be removed
+ */
+ void deviceDisconnected(DeviceId deviceId);
+
+ /**
+ * Sends information about all ports of a device. It is up to the core to
+ * determine what has changed.
+ *
+ * @param deviceId identity of the device
+ * @param portDescriptions list of device ports
+ */
+ void updatePorts(DeviceId deviceId, List<PortDescription> portDescriptions);
+
+ /**
+ * Used to notify the core about port status change of a single port.
+ *
+ * @param deviceId identity of the device
+ * @param portDescription description of the port that changed
+ */
+ void portStatusChanged(DeviceId deviceId, PortDescription portDescription);
+
+ /**
+ * Notifies the core about the result of a RoleRequest sent to a device.
+ *
+ * @param deviceId identity of the device
+ * @param requested mastership role that was requested by the node
+ * @param response mastership role the switch accepted
+ */
+ void receivedRoleReply(DeviceId deviceId, MastershipRole requested, MastershipRole response);
+
+ /**
+ * Sends statistics about all ports of a device.
+ *
+ * @param deviceId identity of the device
+ * @param portStatistics list of device port statistics
+ */
+ void updatePortStatistics(DeviceId deviceId, Collection<PortStatistics> portStatistics);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceService.java
new file mode 100644
index 00000000..f4671fb4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceService.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+
+import java.util.List;
+
+/**
+ * Service for interacting with the inventory of infrastructure devices.
+ */
+public interface DeviceService
+ extends ListenerService<DeviceEvent, DeviceListener> {
+
+ /**
+ * Returns the number of infrastructure devices known to the system.
+ *
+ * @return number of infrastructure devices
+ */
+ int getDeviceCount();
+
+ /**
+ * Returns a collection of the currently known infrastructure
+ * devices.
+ *
+ * @return collection of devices
+ */
+ Iterable<Device> getDevices();
+
+ /**
+ * Returns a collection of the currently known infrastructure
+ * devices by device type.
+ *
+ * @param type device type
+ * @return collection of devices
+ */
+ Iterable<Device> getDevices(Device.Type type);
+
+ /**
+ * Returns an iterable collection of all devices
+ * currently available to the system.
+ *
+ * @return device collection
+ */
+ Iterable<Device> getAvailableDevices();
+
+ /**
+ * Returns an iterable collection of all devices currently available to the system by device type.
+ *
+ * @param type device type
+ * @return device collection
+ */
+ Iterable<Device> getAvailableDevices(Device.Type type);
+
+ /**
+ * Returns the device with the specified identifier.
+ *
+ * @param deviceId device identifier
+ * @return device or null if one with the given identifier is not known
+ */
+ Device getDevice(DeviceId deviceId);
+
+ /**
+ * Returns the current mastership role for the specified device.
+ *
+ * @param deviceId device identifier
+ * @return designated mastership role
+ */
+ //XXX do we want this method here when MastershipService already does?
+ MastershipRole getRole(DeviceId deviceId);
+
+
+ /**
+ * Returns the list of ports associated with the device.
+ *
+ * @param deviceId device identifier
+ * @return list of ports
+ */
+ List<Port> getPorts(DeviceId deviceId);
+
+ /**
+ * Returns the list of port statistics associated with the device.
+ *
+ * @param deviceId device identifier
+ * @return list of port statistics
+ */
+ List<PortStatistics> getPortStatistics(DeviceId deviceId);
+
+ /**
+ * Returns the list of port delta statistics associated with the device.
+ *
+ * @param deviceId device identifier
+ * @return list of port statistics
+ */
+ List<PortStatistics> getPortDeltaStatistics(DeviceId deviceId);
+
+ /**
+ * Returns the port with the specified number and hosted by the given device.
+ *
+ * @param deviceId device identifier
+ * @param portNumber port number
+ * @return device port
+ */
+ Port getPort(DeviceId deviceId, PortNumber portNumber);
+
+ /**
+ * Indicates whether or not the device is presently online and available.
+ *
+ * @param deviceId device identifier
+ * @return true if the device is available
+ */
+ boolean isAvailable(DeviceId deviceId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceStore.java
new file mode 100644
index 00000000..851b9709
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceStore.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.store.Store;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Manages inventory of infrastructure devices; not intended for direct use.
+ */
+public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
+
+ /**
+ * Returns the number of devices known to the system.
+ *
+ * @return number of devices
+ */
+ int getDeviceCount();
+
+ /**
+ * Returns an iterable collection of all devices known to the system.
+ *
+ * @return device collection
+ */
+ Iterable<Device> getDevices();
+
+ /**
+ * Returns an iterable collection of all devices currently available to the system.
+ *
+ * @return device collection
+ */
+ Iterable<Device> getAvailableDevices();
+
+
+
+ /**
+ * Returns the device with the specified identifier.
+ *
+ * @param deviceId device identifier
+ * @return device
+ */
+ Device getDevice(DeviceId deviceId);
+
+ /**
+ * Creates a new infrastructure device, or updates an existing one using
+ * the supplied device description.
+ *
+ * @param providerId provider identifier
+ * @param deviceId device identifier
+ * @param deviceDescription device description
+ * @return ready to send event describing what occurred; null if no change
+ */
+ DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId,
+ DeviceDescription deviceDescription);
+
+ // TODO: We may need to enforce that ancillary cannot interfere this state
+ /**
+ * Removes the specified infrastructure device.
+ *
+ * @param deviceId device identifier
+ * @return ready to send event describing what occurred; null if no change
+ */
+ DeviceEvent markOffline(DeviceId deviceId);
+
+ /**
+ * Updates the ports of the specified infrastructure device using the given
+ * list of port descriptions. The list is assumed to be comprehensive.
+ *
+ * @param providerId provider identifier
+ * @param deviceId device identifier
+ * @param portDescriptions list of port descriptions
+ * @return ready to send events describing what occurred; empty list if no change
+ */
+ List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
+ List<PortDescription> portDescriptions);
+
+ /**
+ * Updates the port status of the specified infrastructure device using the
+ * given port description.
+ *
+ * @param providerId provider identifier
+ * @param deviceId device identifier
+ * @param portDescription port description
+ * @return ready to send event describing what occurred; null if no change
+ */
+ DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
+ PortDescription portDescription);
+
+ /**
+ * Returns the list of ports that belong to the specified device.
+ *
+ * @param deviceId device identifier
+ * @return list of device ports
+ */
+ List<Port> getPorts(DeviceId deviceId);
+
+ /**
+ * Updates the port statistics of the specified device using the give port
+ * statistics.
+ *
+ * @param providerId provider identifier
+ * @param deviceId device identifier
+ * @param portStats list of port statistics
+ * @return ready to send event describing what occurred;
+ */
+ DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId,
+ Collection<PortStatistics> portStats);
+
+ /**
+ * Returns the list of port statistics of the specified device.
+ *
+ * @param deviceId device identifier
+ * @return list of port statistics of all ports of the device
+ */
+ List<PortStatistics> getPortStatistics(DeviceId deviceId);
+
+ /**
+ * Returns the list of delta port statistics of the specified device.
+ *
+ * @param deviceId device identifier
+ * @return list of delta port statistics of all ports of the device
+ */
+ List<PortStatistics> getPortDeltaStatistics(DeviceId deviceId);
+
+ /**
+ * Returns the specified device port.
+ *
+ * @param deviceId device identifier
+ * @param portNumber port number
+ * @return device port
+ */
+ Port getPort(DeviceId deviceId, PortNumber portNumber);
+
+ /**
+ * Indicates whether the specified device is available/online.
+ *
+ * @param deviceId device identifier
+ * @return true if device is available
+ */
+ boolean isAvailable(DeviceId deviceId);
+
+ /**
+ * Administratively removes the specified device from the store.
+ *
+ * @param deviceId device to be removed
+ * @return null if no such device, or was forwarded to remove master
+ */
+ DeviceEvent removeDevice(DeviceId deviceId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceStoreDelegate.java
new file mode 100644
index 00000000..1a4fc67d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Infrastructure device store delegate abstraction.
+ */
+public interface DeviceStoreDelegate extends StoreDelegate<DeviceEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OchPortDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OchPortDescription.java
new file mode 100644
index 00000000..c3a7f415
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OchPortDescription.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalType;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of immutable OCh port description.
+ */
+public class OchPortDescription extends DefaultPortDescription {
+
+ private final OduSignalType signalType;
+ private final boolean isTunable;
+ private final OchSignal lambda;
+
+ /**
+ * Creates OCH port description based on the supplied information.
+ *
+ * @param number port number
+ * @param isEnabled port enabled state
+ * @param signalType ODU signal type
+ * @param isTunable tunable wavelength capability
+ * @param lambda OCh signal
+ * @param annotations optional key/value annotations map
+ */
+ public OchPortDescription(PortNumber number, boolean isEnabled, OduSignalType signalType,
+ boolean isTunable, OchSignal lambda, SparseAnnotations... annotations) {
+ super(number, isEnabled, Port.Type.OCH, 0, annotations);
+ this.signalType = signalType;
+ this.isTunable = isTunable;
+ this.lambda = checkNotNull(lambda);
+ }
+
+ /**
+ * Creates OCH port description based on the supplied information.
+ *
+ * @param base PortDescription to get basic information from
+ * @param signalType ODU signal type
+ * @param isTunable tunable wavelength capability
+ * @param lambda OCh signal
+ * @param annotations optional key/value annotations map
+ */
+ public OchPortDescription(PortDescription base, OduSignalType signalType, boolean isTunable,
+ OchSignal lambda, SparseAnnotations annotations) {
+ super(base, annotations);
+ this.signalType = signalType;
+ this.isTunable = isTunable;
+ this.lambda = checkNotNull(lambda);
+ }
+
+ /**
+ * Returns ODU signal type.
+ *
+ * @return ODU signal type
+ */
+ public OduSignalType signalType() {
+ return signalType;
+ }
+
+ /**
+ * Returns true if port is wavelength tunable.
+ *
+ * @return tunable wavelength capability
+ */
+ public boolean isTunable() {
+ return isTunable;
+ }
+
+ /**
+ * Returns OCh signal.
+ *
+ * @return OCh signal
+ */
+ public OchSignal lambda() {
+ return lambda;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("number", portNumber())
+ .add("isEnabled", isEnabled())
+ .add("type", type())
+ .add("signalType", signalType)
+ .add("isTunable", isTunable)
+ .add("lambda", lambda)
+ .add("annotations", annotations())
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OduCltPortDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OduCltPortDescription.java
new file mode 100644
index 00000000..eee7de2d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OduCltPortDescription.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.OduCltPort;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+
+/**
+ * Default implementation of immutable ODU client port description.
+ */
+public class OduCltPortDescription extends DefaultPortDescription {
+
+ private final OduCltPort.SignalType signalType;
+
+ /**
+ * Creates ODU client port description based on the supplied information.
+ *
+ * @param number port number
+ * @param isEnabled port enabled state
+ * @param signalType ODU client signal type
+ * @param annotations optional key/value annotations map
+ */
+ public OduCltPortDescription(PortNumber number, boolean isEnabled, OduCltPort.SignalType signalType,
+ SparseAnnotations... annotations) {
+ super(number, isEnabled, Port.Type.ODUCLT, 0, annotations);
+ this.signalType = signalType;
+ }
+
+ /**
+ * Creates ODU client port description based on the supplied information.
+ *
+ * @param base PortDescription to get basic information from
+ * @param signalType ODU client signal type
+ * @param annotations optional key/value annotations map
+ */
+ public OduCltPortDescription(PortDescription base, OduCltPort.SignalType signalType,
+ SparseAnnotations annotations) {
+ super(base, annotations);
+ this.signalType = signalType;
+ }
+
+ /**
+ * Returns ODU client signal type.
+ *
+ * @return ODU client signal type
+ */
+ public OduCltPort.SignalType signalType() {
+ return signalType;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("number", portNumber())
+ .add("isEnabled", isEnabled())
+ .add("type", type())
+ .add("signalType", signalType)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OmsPortDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OmsPortDescription.java
new file mode 100644
index 00000000..131314a3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/OmsPortDescription.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.util.Frequency;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+
+/**
+ * Default implementation of immutable OMS port description.
+ */
+public class OmsPortDescription extends DefaultPortDescription {
+
+ private final Frequency minFrequency;
+ private final Frequency maxFrequency;
+ private final Frequency grid;
+
+ /**
+ * Creates OMS port description based on the supplied information.
+ *
+ * @param number port number
+ * @param isEnabled port enabled state
+ * @param minFrequency minimum frequency
+ * @param maxFrequency maximum frequency
+ * @param grid grid spacing frequency
+ * @param annotations optional key/value annotations map
+ */
+ public OmsPortDescription(PortNumber number, boolean isEnabled, Frequency minFrequency, Frequency maxFrequency,
+ Frequency grid, SparseAnnotations... annotations) {
+ super(number, isEnabled, Port.Type.OMS, 0, annotations);
+ this.minFrequency = minFrequency;
+ this.maxFrequency = maxFrequency;
+ this.grid = grid;
+ }
+
+ /**
+ * Creates OMS port description based on the supplied information.
+ *
+ * @param base PortDescription to get basic information from
+ * @param minFrequency minimum frequency
+ * @param maxFrequency maximum frequency
+ * @param grid grid spacing frequency
+ * @param annotations optional key/value annotations map
+ */
+ public OmsPortDescription(PortDescription base, Frequency minFrequency, Frequency maxFrequency,
+ Frequency grid, SparseAnnotations annotations) {
+ super(base, annotations);
+ this.minFrequency = minFrequency;
+ this.maxFrequency = maxFrequency;
+ this.grid = grid;
+ }
+
+ /**
+ * Returns minimum frequency.
+ *
+ * @return minimum frequency
+ */
+ public Frequency minFrequency() {
+ return minFrequency;
+ }
+
+ /**
+ * Returns maximum frequency.
+ *
+ * @return maximum frequency
+ */
+ public Frequency maxFrequency() {
+ return maxFrequency;
+ }
+
+ /**
+ * Returns grid spacing frequency.
+ *
+ * @return grid spacing frequency
+ */
+ public Frequency grid() {
+ return grid;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("number", portNumber())
+ .add("isEnabled", isEnabled())
+ .add("type", type())
+ .add("minFrequency", minFrequency)
+ .add("maxFrequency", maxFrequency)
+ .add("grid", grid)
+ .add("annotations", annotations())
+ .toString();
+ }
+
+}
+
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/PortDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/PortDescription.java
new file mode 100644
index 00000000..3ed3efce
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/PortDescription.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import org.onosproject.net.Description;
+import org.onosproject.net.PortNumber;
+
+import static org.onosproject.net.Port.Type;
+
+/**
+ * Information about a port.
+ */
+public interface PortDescription extends Description {
+
+ /**
+ * Returns the port number.
+ *
+ * @return port number
+ */
+ PortNumber portNumber();
+
+ /**
+ * Indicates whether or not the port is up and active.
+ *
+ * @return true if the port is active and has carrier signal
+ */
+ boolean isEnabled();
+
+ /**
+ * Returns the port type.
+ *
+ * @return port type
+ */
+ Type type();
+
+ /**
+ * Returns the current port speed in Mbps.
+ *
+ * @return current port speed
+ */
+ long portSpeed();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/PortStatistics.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/PortStatistics.java
new file mode 100644
index 00000000..201bd7b6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/PortStatistics.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+/**
+ * Statistics of a port.
+ */
+public interface PortStatistics {
+
+ /**
+ * Returns the port number.
+ *
+ * @return port number
+ */
+ int port();
+
+ /**
+ * Returns the number of packets received.
+ *
+ * @return the number of packets received
+ */
+ long packetsReceived();
+
+ /**
+ * Returns the number of packets sent.
+ *
+ * @return the number of packets sent
+ */
+ long packetsSent();
+
+ /**
+ * Returns the bytes received.
+ *
+ * @return the bytes received
+ */
+ long bytesReceived();
+
+ /**
+ * Returns the bytes sent.
+ *
+ * @return the bytes sent
+ */
+ long bytesSent();
+
+ /**
+ * Returns the number of packets dropped by RX.
+ *
+ * @return the number of packets dropped by RX
+ */
+ long packetsRxDropped();
+
+ /**
+ * Returns the number of packets dropped by TX.
+ *
+ * @return the number of packets dropped by TX
+ */
+ long packetsTxDropped();
+
+ /**
+ * Returns the number of transmit errors.
+ *
+ * @return the number of transmit errors
+ */
+ long packetsRxErrors();
+
+ /**
+ * Returns the number of receive errors.
+ *
+ * @return the number of receive error
+ */
+ long packetsTxErrors();
+
+ /**
+ * Returns the time port has been alive in seconds.
+ *
+ * @return the time port has been alive in seconds
+ */
+ long durationSec();
+
+ /**
+ * Returns the time port has been alive in nano seconds.
+ *
+ * @return the time port has been alive in nano seconds
+ */
+ long durationNano();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/package-info.java
new file mode 100644
index 00000000..4ee64dcf
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Infrastructure device model &amp; related services API definitions.
+ */
+package org.onosproject.net.device;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/AbstractBehaviour.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/AbstractBehaviour.java
new file mode 100644
index 00000000..784e6c55
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/AbstractBehaviour.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Base implementation of device driver behaviour.
+ */
+public class AbstractBehaviour implements Behaviour {
+
+ private DriverData data;
+
+ @Override
+ public DriverData data() {
+ return data;
+ }
+
+ @Override
+ public void setData(DriverData data) {
+ checkState(this.data == null, "Driver data already set");
+ this.data = data;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/AbstractHandlerBehaviour.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/AbstractHandlerBehaviour.java
new file mode 100644
index 00000000..66b21ffe
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/AbstractHandlerBehaviour.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Base implementation of device driver handler behaviour.
+ */
+public class AbstractHandlerBehaviour
+ extends AbstractBehaviour implements HandlerBehaviour {
+
+ private DriverHandler handler;
+
+ @Override
+ public DriverHandler handler() {
+ return handler;
+ }
+
+ @Override
+ public void setHandler(DriverHandler handler) {
+ checkState(this.handler == null, "Driver handler already set");
+ this.handler = handler;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/Behaviour.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/Behaviour.java
new file mode 100644
index 00000000..6e28aa86
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/Behaviour.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+/**
+ * Representation of a facet of device behaviour that can be used to talk about
+ * a device (in context of {@link DriverData}) or to a device (in context of
+ * {@link DriverHandler}).
+ */
+public interface Behaviour {
+
+ /**
+ * Returns the driver data context.
+ *
+ * @return driver data
+ */
+ DriverData data();
+
+ /**
+ * Sets the driver data context on this this behaviour should operate.
+ *
+ * @param data driver data
+ */
+ void setData(DriverData data);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
new file mode 100644
index 00000000..b7a9f2b7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.ImmutableMap.copyOf;
+
+/**
+ * Default implementation of extensible driver.
+ */
+public class DefaultDriver implements Driver {
+
+ private final String name;
+ private final Driver parent;
+
+ private final String manufacturer;
+ private final String hwVersion;
+ private final String swVersion;
+
+ private final Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours;
+ private final Map<String, String> properties;
+
+ /**
+ * Creates a driver with the specified name.
+ *
+ * @param name driver name
+ * @param parent optional parent driver
+ * @param manufacturer device manufacturer
+ * @param hwVersion device hardware version
+ * @param swVersion device software version
+ * @param behaviours device behaviour classes
+ * @param properties properties for configuration of device behaviour classes
+ */
+ public DefaultDriver(String name, Driver parent, String manufacturer,
+ String hwVersion, String swVersion,
+ Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours,
+ Map<String, String> properties) {
+ this.name = checkNotNull(name, "Name cannot be null");
+ this.parent = parent;
+ this.manufacturer = checkNotNull(manufacturer, "Manufacturer cannot be null");
+ this.hwVersion = checkNotNull(hwVersion, "HW version cannot be null");
+ this.swVersion = checkNotNull(swVersion, "SW version cannot be null");
+ this.behaviours = copyOf(checkNotNull(behaviours, "Behaviours cannot be null"));
+ this.properties = copyOf(checkNotNull(properties, "Properties cannot be null"));
+ }
+
+ @Override
+ public Driver merge(Driver other) {
+ checkArgument(parent == null || Objects.equals(parent, other.parent()),
+ "Parent drivers are not the same");
+
+ // Merge the behaviours.
+ Map<Class<? extends Behaviour>, Class<? extends Behaviour>>
+ behaviours = Maps.newHashMap();
+ behaviours.putAll(this.behaviours);
+ other.behaviours().forEach(b -> behaviours.put(b, other.implementation(b)));
+
+ // Merge the properties.
+ ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+ properties.putAll(this.properties).putAll(other.properties());
+
+ return new DefaultDriver(name, other.parent(), manufacturer, hwVersion, swVersion,
+ ImmutableMap.copyOf(behaviours), properties.build());
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public String manufacturer() {
+ return manufacturer;
+ }
+
+ @Override
+ public String hwVersion() {
+ return hwVersion;
+ }
+
+ @Override
+ public String swVersion() {
+ return swVersion;
+ }
+
+ @Override
+ public Driver parent() {
+ return parent;
+ }
+
+ @Override
+ public Set<Class<? extends Behaviour>> behaviours() {
+ return behaviours.keySet();
+ }
+
+ @Override
+ public Class<? extends Behaviour> implementation(Class<? extends Behaviour> behaviour) {
+ return behaviours.get(behaviour);
+ }
+
+ @Override
+ public boolean hasBehaviour(Class<? extends Behaviour> behaviourClass) {
+ return behaviours.containsKey(behaviourClass) ||
+ (parent != null && parent.hasBehaviour(behaviourClass));
+ }
+
+ @Override
+ public <T extends Behaviour> T createBehaviour(DriverData data,
+ Class<T> behaviourClass) {
+ T behaviour = createBehaviour(data, null, behaviourClass);
+ if (behaviour != null) {
+ return behaviour;
+ } else if (parent != null) {
+ return parent.createBehaviour(data, behaviourClass);
+ }
+ throw new IllegalArgumentException(behaviourClass.getName() + " not supported");
+ }
+
+ @Override
+ public <T extends Behaviour> T createBehaviour(DriverHandler handler,
+ Class<T> behaviourClass) {
+ T behaviour = createBehaviour(handler.data(), handler, behaviourClass);
+ if (behaviour != null) {
+ return behaviour;
+ } else if (parent != null) {
+ return parent.createBehaviour(handler, behaviourClass);
+ }
+ throw new IllegalArgumentException(behaviourClass.getName() + " not supported");
+ }
+
+ // Creates an instance of behaviour primed with the specified driver data.
+ private <T extends Behaviour> T createBehaviour(DriverData data, DriverHandler handler,
+ Class<T> behaviourClass) {
+ //checkArgument(handler != null || !HandlerBehaviour.class.isAssignableFrom(behaviourClass),
+ // "{} is applicable only to handler context", behaviourClass.getName());
+
+ // Locate the implementation of the requested behaviour.
+ Class<? extends Behaviour> implementation = behaviours.get(behaviourClass);
+ if (implementation != null) {
+ // Create an instance of the behaviour and apply data as its context.
+ T behaviour = createBehaviour(behaviourClass, implementation);
+ behaviour.setData(data);
+
+ // If this is a handler behaviour, also apply handler as its context.
+ if (handler != null) {
+ ((HandlerBehaviour) behaviour).setHandler(handler);
+ }
+ return behaviour;
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T extends Behaviour> T createBehaviour(Class<T> behaviourClass,
+ Class<? extends Behaviour> implementation) {
+ try {
+ return (T) implementation.newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ // TODO: add a specific unchecked exception
+ throw new IllegalArgumentException("Unable to create behaviour", e);
+ }
+ }
+
+ @Override
+ public Set<String> keys() {
+ return properties.keySet();
+ }
+
+ @Override
+ public String value(String key) {
+ return properties.get(key);
+ }
+
+ @Override
+ public Map<String, String> properties() {
+ return properties;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("name", name)
+ .add("parent", parent)
+ .add("manufacturer", manufacturer)
+ .add("hwVersion", hwVersion)
+ .add("swVersion", swVersion)
+ .add("behaviours", behaviours)
+ .add("properties", properties)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverData.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverData.java
new file mode 100644
index 00000000..76d7932d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverData.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MutableAnnotations;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of driver data descriptor.
+ */
+public class DefaultDriverData implements DriverData {
+
+ private final Driver driver;
+ private final DeviceId deviceId;
+ private final Map<String, String> properties;
+
+ /**
+ * Creates new driver data.
+ *
+ * @param driver parent driver type
+ * @param deviceId device identifier
+ */
+ public DefaultDriverData(Driver driver, DeviceId deviceId) {
+ this.driver = driver;
+ this.deviceId = deviceId;
+ this.properties = new HashMap<>();
+ }
+
+ @Override
+ public Driver driver() {
+ return driver;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
+ return driver.createBehaviour(this, behaviourClass);
+ }
+
+ @Override
+ public MutableAnnotations set(String key, String value) {
+ properties.put(key, value);
+ return this;
+ }
+
+ @Override
+ public MutableAnnotations clear(String... keys) {
+ if (keys.length == 0) {
+ properties.clear();
+ } else {
+ for (String key : keys) {
+ properties.remove(key);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public Set<String> keys() {
+ return ImmutableSet.copyOf(properties.keySet());
+ }
+
+ @Override
+ public String value(String key) {
+ return properties.get(key);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("type", driver)
+ .add("properties", properties)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverHandler.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverHandler.java
new file mode 100644
index 00000000..28fdb2f3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverHandler.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of driver handler.
+ */
+public class DefaultDriverHandler implements DriverHandler {
+
+ private final DefaultDriverData data;
+
+ // Reference to service directory to provide run-time context.
+ protected static ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+
+ /**
+ * Creates new driver handler with the attached driver data.
+ *
+ * @param data driver data to attach
+ */
+ public DefaultDriverHandler(DefaultDriverData data) {
+ this.data = data;
+ }
+
+ @Override
+ public Driver driver() {
+ return data.driver();
+ }
+
+ @Override
+ public DriverData data() {
+ return data;
+ }
+
+ @Override
+ public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
+ return data.driver().createBehaviour(this, behaviourClass);
+ }
+
+ @Override
+ public <T> T get(Class<T> serviceClass) {
+ return serviceDirectory.get(serviceClass);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("data", data).toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverProvider.java
new file mode 100644
index 00000000..b2b5281c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverProvider.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default driver provider implementation.
+ */
+public class DefaultDriverProvider implements DriverProvider {
+
+ protected final Map<String, Driver> drivers = Maps.newConcurrentMap();
+
+ @Override
+ public Set<Driver> getDrivers() {
+ return ImmutableSet.copyOf(drivers.values());
+ }
+
+ /**
+ * Adds the specified drivers to the provider.
+ *
+ * @param drivers drivers to be added
+ */
+ public void addDrivers(Set<Driver> drivers) {
+ drivers.forEach(this::addDriver);
+ }
+
+ /**
+ * Adds the specified driver to the provider.
+ *
+ * @param driver driver to be provided
+ */
+ public void addDriver(Driver driver) {
+ Driver ddc = drivers.get(driver.name());
+ if (ddc == null) {
+ // If we don't have the driver yet, just use the new one.
+ drivers.put(driver.name(), driver);
+ } else {
+ // Otherwise merge the existing driver with the new one and rebind.
+ drivers.put(driver.name(), ddc.merge(driver));
+ }
+ }
+
+ /**
+ * Removes the specified drivers from the provider.
+ *
+ * @param drivers drivers to be removed
+ */
+ public void removeDrivers(Set<Driver> drivers) {
+ drivers.forEach(this::removeDriver);
+ }
+
+ /**
+ * Removes the specified driver from the provider.
+ *
+ * @param driver driver to be removed
+ */
+ public void removeDriver(Driver driver) {
+ // TODO: make selective if possible
+ drivers.remove(driver.name());
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("drivers", drivers).toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverProviderService.java
new file mode 100644
index 00000000..153c7c56
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverProviderService.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.driver;
+
+/**
+ * Service representing availability of default drivers.
+ */
+public interface DefaultDriverProviderService {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/Driver.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/Driver.java
new file mode 100644
index 00000000..50611b14
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/Driver.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import org.onosproject.net.Annotations;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Representation of a specific family of device drivers. Behaviour configuration
+ * data is stored using {@link org.onosproject.net.Annotations}.
+ */
+public interface Driver extends Annotations {
+
+ /**
+ * Returns the driver name. This is expected to be a reverse-DNS,
+ * Java package-like name.
+ *
+ * @return driver name
+ */
+ String name();
+
+ /**
+ * Returns the parent driver from which this driver inherits behaviours
+ * and properties.
+ *
+ * @return parent driver; null if driver has no parent
+ */
+ Driver parent();
+
+ /**
+ * Returns the device manufacturer name.
+ *
+ * @return manufacturer name
+ */
+ String manufacturer();
+
+ /**
+ * Returns the device hardware version.
+ *
+ * @return hardware version
+ */
+ String hwVersion();
+
+ /**
+ * Returns the device software version.
+ *
+ * @return software version
+ */
+ String swVersion();
+
+ /**
+ * Returns the set of behaviours supported by this driver.
+ * It reflects behaviours of only this driver and not its parent.
+ *
+ * @return set of device driver behaviours
+ */
+ Set<Class<? extends Behaviour>> behaviours();
+
+ /**
+ * Returns the implementation class for the specified behaviour.
+ * It reflects behaviours of only this driver and not its parent.
+ *
+ * @param behaviour behaviour interface
+ * @return implementation class
+ */
+ Class<? extends Behaviour> implementation(Class<? extends Behaviour> behaviour);
+
+ /**
+ * Indicates whether or not the driver, or any of its parents, support
+ * the specified class of behaviour. It
+ *
+ * @param behaviourClass behaviour class
+ * @return true if behaviour is supported
+ */
+ boolean hasBehaviour(Class<? extends Behaviour> behaviourClass);
+
+ /**
+ * Creates an instance of behaviour primed with the specified driver data.
+ * If the current driver does not support the specified behaviour and the
+ * driver has parent, the request is delegated to the parent driver.
+ *
+ * @param data driver data context
+ * @param behaviourClass driver behaviour class
+ * @param <T> type of behaviour
+ * @return behaviour instance
+ */
+ <T extends Behaviour> T createBehaviour(DriverData data, Class<T> behaviourClass);
+
+ /**
+ * Creates an instance of behaviour primed with the specified driver data.
+ * If the current driver does not support the specified behaviour and the
+ * driver has parent, the request is delegated to the parent driver.
+ *
+ * @param handler driver handler context
+ * @param behaviourClass driver behaviour class
+ * @param <T> type of behaviour
+ * @return behaviour instance
+ */
+ <T extends Behaviour> T createBehaviour(DriverHandler handler, Class<T> behaviourClass);
+
+ /**
+ * Returns the set of annotations as map of key/value properties.
+ *
+ * @return map of properties
+ */
+ Map<String, String> properties();
+
+ /**
+ * Merges the specified driver behaviours and properties into this one,
+ * giving preference to the other driver when dealing with conflicts.
+ *
+ * @param other other driver
+ * @return merged driver
+ */
+ Driver merge(Driver other);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverAdminService.java
new file mode 100644
index 00000000..e7fa1385
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverAdminService.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import java.util.Set;
+
+/**
+ * Service for managing drivers and driver behaviour implementations.
+ */
+public interface DriverAdminService extends DriverService {
+
+ /**
+ * Returns the set of driver providers currently registered.
+ *
+ * @return registered driver providers
+ */
+ Set<DriverProvider> getProviders();
+
+ /**
+ * Registers the specified driver provider.
+ *
+ * @param provider driver provider to register
+ */
+ void registerProvider(DriverProvider provider);
+
+ /**
+ * Unregisters the specified driver provider.
+ *
+ * @param provider driver provider to unregister
+ */
+ void unregisterProvider(DriverProvider provider);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverConnect.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverConnect.java
new file mode 100644
index 00000000..1d510913
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverConnect.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+/**
+ * Abstraction of handler behaviour used to set-up and tear-down driver
+ * connection with a device.
+ */
+public interface DriverConnect extends HandlerBehaviour {
+
+ /**
+ * Connects to the device.
+ *
+ * @param credentials optional login credentials in string form
+ */
+ void connect(String... credentials);
+
+ /**
+ * Disconnects from the device.
+ */
+ void disconnect();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverData.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverData.java
new file mode 100644
index 00000000..1d66ea9a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverData.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MutableAnnotations;
+
+/**
+ * Container for data about a device. Data is stored using
+ * {@link org.onosproject.net.MutableAnnotations}.
+ */
+public interface DriverData extends MutableAnnotations {
+
+ /**
+ * Returns the parent device driver.
+ *
+ * @return device driver
+ */
+ Driver driver();
+
+ /**
+ * Returns the device identifier.
+ *
+ * @return device identifier
+ */
+ DeviceId deviceId();
+
+ /**
+ * Returns the specified facet of behaviour to access the device data.
+ *
+ * @param behaviourClass behaviour class
+ * @param <T> type of behaviour
+ * @return requested behaviour or null if not supported
+ */
+ <T extends Behaviour> T behaviour(Class<T> behaviourClass);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverHandler.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverHandler.java
new file mode 100644
index 00000000..202708ba
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverHandler.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+/**
+ * Representation of context for interacting with a device.
+ */
+public interface DriverHandler {
+
+ /**
+ * Returns the parent device driver.
+ *
+ * @return device driver
+ */
+ Driver driver();
+
+ /**
+ * Returns the device driver data.
+ *
+ * @return device driver data
+ */
+ DriverData data();
+
+ /**
+ * Returns the specified facet of behaviour to interact with the device.
+ *
+ * @param behaviourClass behaviour class
+ * @param <T> type of behaviour
+ * @return behaviour
+ */
+ <T extends Behaviour> T behaviour(Class<T> behaviourClass);
+
+ /**
+ * Returns the reference to the implementation of the specified service.
+ * Provides access to run-time context.
+ *
+ * @param serviceClass service class
+ * @param <T> type of service
+ * @return service implementation
+ * @throws org.onlab.osgi.ServiceNotFoundException if service is unavailable
+ */
+ <T> T get(Class<T> serviceClass);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverProvider.java
new file mode 100644
index 00000000..354d93e9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import java.util.Set;
+
+/**
+ * Represents entity capable of providing device drivers and their
+ * behaviours.
+ */
+public interface DriverProvider {
+
+ /**
+ * Returns the set of driver types and behaviour implementations to be
+ * made available by this provider.
+ *
+ * @return set of driver types and their behaviours
+ */
+ Set<Driver> getDrivers();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverResolver.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverResolver.java
new file mode 100644
index 00000000..094c710f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverResolver.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.driver;
+
+/**
+ * Entity capable of resolving a driver using its name.
+ */
+public interface DriverResolver {
+
+ /**
+ * Returns the specified driver.
+ *
+ * @param driverName driver name
+ * @return driver
+ * @throws org.onlab.util.ItemNotFoundException if driver with the given
+ * name is not found
+ */
+ Driver getDriver(String driverName);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverService.java
new file mode 100644
index 00000000..1a74255b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/DriverService.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import org.onosproject.net.DeviceId;
+
+import java.util.Set;
+
+/**
+ * Service for obtaining drivers and driver behaviour implementations.
+ */
+public interface DriverService extends DriverResolver {
+
+ /**
+ * Returns the overall set of drivers being provided.
+ *
+ * @return provided drivers
+ */
+ Set<Driver> getDrivers();
+
+ /**
+ * Returns the set of drivers which support the specified behaviour.
+ *
+ * @param withBehaviour behaviour class to query by
+ * @return provided drivers
+ */
+ Set<Driver> getDrivers(Class<? extends Behaviour> withBehaviour);
+
+ /**
+ * Returns the driver that matches the specified primordial device
+ * discovery information.
+ *
+ * @param mfr device manufacturer
+ * @param hw device hardware name/version
+ * @param sw device software version
+ * @return driver or null of no matching one is found
+ */
+ Driver getDriver(String mfr, String hw, String sw);
+
+ /**
+ * Returns the driver for the specified device. If the device carries
+ * {@code driver} annotation, its value is used to look-up the driver.
+ * Otherwise, the device manufacturer, hardware and software version
+ * attributes are used to look-up the driver. First using their literal
+ * values and if no driver is found, using ERE matching against the
+ * driver manufacturer, hardware and software version fields.
+ *
+ * @param deviceId device identifier
+ * @return driver or null of no matching one is found
+ * @throws org.onlab.util.ItemNotFoundException if device or driver for it
+ * are not found
+ */
+ Driver getDriver(DeviceId deviceId);
+
+ /**
+ * Creates a new driver handler for interacting with the specified device.
+ * The driver is looked-up using the same semantics as
+ * {@link #getDriver(DeviceId)} method.
+ *
+ * @param deviceId device identifier
+ * @param credentials optional login credentials in string form
+ * @return driver handler
+ * @throws org.onlab.util.ItemNotFoundException if device or driver for it
+ * are not found
+ */
+ DriverHandler createHandler(DeviceId deviceId, String... credentials);
+
+ // TODO: Devise a mechanism for retaining DriverData for devices
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/HandlerBehaviour.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/HandlerBehaviour.java
new file mode 100644
index 00000000..b5771ac1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/HandlerBehaviour.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+/**
+ * Representation of a facet of device behaviour that can be used to interact
+ * with a device (in context of {@link org.onosproject.net.driver.DriverHandler}).
+ */
+public interface HandlerBehaviour extends Behaviour {
+
+ /**
+ * Returns the driver handler context on which this behaviour operates.
+ *
+ * @return driver handler context
+ */
+ DriverHandler handler();
+
+ /**
+ * Sets the driver handler context for this behaviour.
+ *
+ * @param handler driver handler
+ */
+ void setHandler(DriverHandler handler);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/XmlDriverLoader.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/XmlDriverLoader.java
new file mode 100644
index 00000000..fc5e04a1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/XmlDriverLoader.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.driver;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.commons.configuration.XMLConfiguration;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * Utility capable of reading driver configuration XML resources and producing
+ * a device driver provider as a result.
+ * <p>
+ * The drivers stream structure is as follows:
+ * </p>
+ * <pre>
+ * &lt;drivers&gt;
+ * &lt;driver name=“...” [manufacturer="..." hwVersion="..." swVersion="..."]&gt;
+ * &lt;behaviour api="..." impl="..."/&gt;
+ * ...
+ * [&lt;property name=“key”&gt;value&lt;/key&gt;]
+ * ...
+ * &lt;/driver&gt;
+ * ...
+ * &lt;/drivers&gt;
+ * </pre>
+ */
+public class XmlDriverLoader {
+
+ private static final String DRIVERS = "drivers";
+ private static final String DRIVER = "driver";
+
+ private static final String BEHAVIOUR = "behaviour";
+ private static final String PROPERTY = "property";
+
+ private static final String NAME = "[@name]";
+ private static final String EXTENDS = "[@extends]";
+ private static final String MFG = "[@manufacturer]";
+ private static final String HW = "[@hwVersion]";
+ private static final String SW = "[@swVersion]";
+ private static final String API = "[@api]";
+ private static final String IMPL = "[@impl]";
+
+ private final ClassLoader classLoader;
+
+ private Map<String, Driver> drivers = Maps.newHashMap();
+
+ /**
+ * Creates a new driver loader capable of loading drivers from the supplied
+ * class loader.
+ *
+ * @param classLoader class loader to use
+ */
+ public XmlDriverLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * Loads the specified drivers resource as an XML stream and parses it to
+ * produce a ready-to-register driver provider.
+ *
+ * @param driversStream stream containing the drivers definitions
+ * @param resolver driver resolver
+ * @return driver provider
+ * @throws java.io.IOException if issues are encountered reading the stream
+ * or parsing the driver definitions within
+ */
+ public DefaultDriverProvider loadDrivers(InputStream driversStream,
+ DriverResolver resolver) throws IOException {
+ try {
+ XMLConfiguration cfg = new XMLConfiguration();
+ cfg.setRootElementName(DRIVERS);
+ cfg.setAttributeSplittingDisabled(true);
+
+ cfg.load(driversStream);
+ return loadDrivers(cfg, resolver);
+ } catch (ConfigurationException e) {
+ throw new IOException("Unable to load drivers", e);
+ }
+ }
+
+ /**
+ * Loads a driver provider from the supplied hierarchical configuration.
+ *
+ * @param driversCfg hierarchical configuration containing the drivers definitions
+ * @param resolver driver resolver
+ * @return driver provider
+ */
+ public DefaultDriverProvider loadDrivers(HierarchicalConfiguration driversCfg,
+ DriverResolver resolver) {
+ DefaultDriverProvider provider = new DefaultDriverProvider();
+ for (HierarchicalConfiguration cfg : driversCfg.configurationsAt(DRIVER)) {
+ DefaultDriver driver = loadDriver(cfg, resolver);
+ drivers.put(driver.name(), driver);
+ provider.addDriver(driver);
+ }
+ drivers.clear();
+ return provider;
+ }
+
+ /**
+ * Loads a driver from the supplied hierarchical configuration.
+ *
+ * @param driverCfg hierarchical configuration containing the driver definition
+ * @param resolver driver resolver
+ * @return driver
+ */
+ public DefaultDriver loadDriver(HierarchicalConfiguration driverCfg,
+ DriverResolver resolver) {
+ String name = driverCfg.getString(NAME);
+ String parentName = driverCfg.getString(EXTENDS);
+ String manufacturer = driverCfg.getString(MFG, "");
+ String hwVersion = driverCfg.getString(HW, "");
+ String swVersion = driverCfg.getString(SW, "");
+
+ Driver parent = parentName != null ? resolve(parentName, resolver) : null;
+ return new DefaultDriver(name, parent, manufacturer, hwVersion, swVersion,
+ parseBehaviours(driverCfg),
+ parseProperties(driverCfg));
+ }
+
+ // Resolves the driver by name locally at first and then using the specified resolver.
+ private Driver resolve(String parentName, DriverResolver resolver) {
+ Driver driver = drivers.get(parentName);
+ return driver != null ? driver :
+ (resolver != null ? resolver.getDriver(parentName) : null);
+ }
+
+ // Parses the behaviours section.
+ private Map<Class<? extends Behaviour>, Class<? extends Behaviour>>
+ parseBehaviours(HierarchicalConfiguration driverCfg) {
+ ImmutableMap.Builder<Class<? extends Behaviour>,
+ Class<? extends Behaviour>> behaviours = ImmutableMap.builder();
+ for (HierarchicalConfiguration b : driverCfg.configurationsAt(BEHAVIOUR)) {
+ behaviours.put(getClass(b.getString(API)), getClass(b.getString(IMPL)));
+ }
+ return behaviours.build();
+ }
+
+ // Parses the properties section.
+ private Map<String, String> parseProperties(HierarchicalConfiguration driverCfg) {
+ ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
+ for (HierarchicalConfiguration b : driverCfg.configurationsAt(PROPERTY)) {
+ properties.put(b.getString(NAME), (String) b.getRootNode().getValue());
+ }
+ return properties.build();
+ }
+
+ @SuppressWarnings("unchecked")
+ private Class<? extends Behaviour> getClass(String className) {
+ try {
+ return (Class<? extends Behaviour>) classLoader.loadClass(className);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Unable to load class " + className, e);
+ }
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/package-info.java
new file mode 100644
index 00000000..fbc39a89
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/driver/package-info.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Set of facilities to allow the platform to be extended with
+ * device specific behaviours and to allow modeling device behaviours while
+ * hiding details of specific device driver implementations.
+ * <p>
+ * {@link org.onosproject.net.driver.Driver} is a representation of a
+ * specific family of devices supports set of
+ * {@link org.onosproject.net.driver.Behaviour behaviour classes}. Default
+ * implementation is provided by the platform and allows DriverProviders to
+ * add different behaviour implementations via DriverService.
+ * </p>
+ * <p>
+ * {@link org.onosproject.net.driver.DriverData} is a container for data
+ * learned about a device. It is associated with a specific
+ * {@link org.onosproject.net.driver.Driver}
+ * and provides set of {@link org.onosproject.net.driver.Behaviour behaviours}
+ * for talking about a device. A default
+ * implementation provided by platform and has mutable key/value store for use by
+ * implementations of {@link org.onosproject.net.driver.Behaviour behaviours}.
+ * </p>
+ * <p>
+ * {@link org.onosproject.net.driver.DriverHandler} is an entity used as a
+ * context to interact with a device. It has a peer
+ * {@link org.onosproject.net.driver.DriverData} instance, which is used to
+ * store information learned about a device. It also
+ * provides set of {@link org.onosproject.net.driver.Behaviour behaviours}
+ * for talking to a device.
+ * </p>
+ * <p>
+ * {@link org.onosproject.net.driver.DriverService} can be used to query the
+ * inventory of device drivers and their behaviours, while the
+ * {@link org.onosproject.net.driver.DriverAdminService} allows adding/removing
+ * drivers and managing behaviour implementations.
+ * {@link org.onosproject.net.driver.DriverProvider} is an entity capable
+ * of add/removing drivers and supplying and managing behaviour
+ * implementations. A default implementation is provided by the framework along
+ * with a {@link org.onosproject.net.driver.XmlDriverLoader loader utility} to
+ * create a driver provider from an XML file structured as follows:
+ * <pre>
+ * &lt;drivers&gt;
+ * &lt;driver name=“...” [manufacturer="..." hwVersion="..." swVersion="..."]&gt;
+ * &lt;behaviour api="..." impl="..."/&gt;
+ * ...
+ * [&lt;property name=“key”&gt;value&lt;/key&gt;]
+ * ...
+ * &lt;/driver&gt;
+ * ...
+ * &lt;/drivers&gt;
+ * </pre>
+ *
+ */
+package org.onosproject.net.driver; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortEvent.java
new file mode 100644
index 00000000..85e6a1b5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortEvent.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.edge;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Describes an event pertaining to edge-port inventory.
+ */
+public class EdgePortEvent extends AbstractEvent<EdgePortEvent.Type, ConnectPoint> {
+
+ public enum Type {
+ /**
+ * Signifies that a new edge port was detected.
+ */
+ EDGE_PORT_ADDED,
+
+ /**
+ * Signifies that a new edge port vanished.
+ */
+ EDGE_PORT_REMOVED
+ }
+
+ /**
+ * Creates a new edge port event.
+ *
+ * @param type event type
+ * @param subject connection point subject
+ */
+ public EdgePortEvent(Type type, ConnectPoint subject) {
+ super(type, subject);
+ }
+
+ /**
+ * Creates a new edge port event.
+ *
+ * @param type event type
+ * @param subject connection point subject
+ * @param time occurrence time
+ */
+ public EdgePortEvent(Type type, ConnectPoint subject, long time) {
+ super(type, subject, time);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortListener.java
new file mode 100644
index 00000000..dae03beb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.edge;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving edge port events.
+ */
+public interface EdgePortListener extends EventListener<EdgePortEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortService.java
new file mode 100644
index 00000000..89a2c171
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/EdgePortService.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.edge;
+
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.nio.ByteBuffer;
+import java.util.Optional;
+
+/**
+ * Service for interacting with an inventory of network edge ports. A port
+ * is considered an edge port if it is an active port and does not have an
+ * infrastructure link associated with it.
+ */
+public interface EdgePortService
+ extends ListenerService<EdgePortEvent, EdgePortListener> {
+
+ /**
+ * Indicates whether or not the specified connection point is an edge point.
+ *
+ * @param point connection point
+ * @return true if edge point
+ */
+ boolean isEdgePoint(ConnectPoint point);
+
+ /**
+ * Returns a collection of all edge point within the current topology.
+ *
+ * @return iterable collection of all edge points
+ */
+ Iterable<ConnectPoint> getEdgePoints();
+
+ /**
+ * Returns a collection of all edge point for the specified device.
+ *
+ * @param deviceId device identifier
+ * @return iterable collection of all edge points for the device
+ */
+ Iterable<ConnectPoint> getEdgePoints(DeviceId deviceId);
+
+ /**
+ * Emits the specified packet, with optional treatment to all edge ports.
+ *
+ * @param data packet data
+ * @param treatment optional traffic treatment to apply to the packet
+ */
+ void emitPacket(ByteBuffer data, Optional<TrafficTreatment> treatment);
+
+ /**
+ * Emits the specified packet, with optional treatment to all edge ports.
+ *
+ * @param deviceId device where to send the packet out
+ * @param data packet data
+ * @param treatment optional traffic treatment to apply to the packet
+ */
+ void emitPacket(DeviceId deviceId, ByteBuffer data,
+ Optional<TrafficTreatment> treatment);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/package-info.java
new file mode 100644
index 00000000..d637f195
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/edge/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service for interacting with network edge.
+ */
+package org.onosproject.net.edge; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperation.java
new file mode 100644
index 00000000..09e34d88
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperation.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A list of BatchOperationEntry.
+ *
+ * @param <T> the enum of operators <br>
+ * This enum must be defined in each sub-classes.
+ */
+public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> {
+
+ private final List<T> ops;
+
+ /**
+ * Creates new {@link BatchOperation} object.
+ */
+ public BatchOperation() {
+ ops = new LinkedList<>();
+ }
+
+ /**
+ * Creates {@link BatchOperation} object from a list of batch operation
+ * entries.
+ *
+ * @param batchOperations the list of batch operation entries.
+ */
+ public BatchOperation(Collection<T> batchOperations) {
+ ops = new LinkedList<>(checkNotNull(batchOperations));
+ }
+
+ /**
+ * Removes all operations maintained in this object.
+ */
+ public void clear() {
+ ops.clear();
+ }
+
+ /**
+ * Returns the number of operations in this object.
+ *
+ * @return the number of operations in this object
+ */
+ public int size() {
+ return ops.size();
+ }
+
+ /**
+ * Returns the operations in this object.
+ *
+ * @return the operations in this object
+ */
+ public List<T> getOperations() {
+ return Collections.unmodifiableList(ops);
+ }
+
+ /**
+ * Adds an operation.
+ * FIXME: Brian promises that the Intent Framework
+ * will not modify the batch operation after it has submitted it.
+ * Ali would prefer immutablity, but trusts brian for better or
+ * for worse.
+ *
+ * @param entry the operation to be added
+ * @return this object if succeeded, null otherwise
+ */
+ public BatchOperation<T> addOperation(T entry) {
+ return ops.add(entry) ? this : null;
+ }
+
+ /**
+ * Add all operations from another batch to this batch.
+ *
+ * @param another another batch
+ * @return true if success
+ */
+ public boolean addAll(BatchOperation<T> another) {
+ return ops.addAll(another.getOperations());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o == null) {
+ return false;
+ }
+
+ if (getClass() != o.getClass()) {
+ return false;
+ }
+ BatchOperation<?> other = (BatchOperation<?>) o;
+
+ return this.ops.equals(other.ops);
+ }
+
+ @Override
+ public int hashCode() {
+ return ops.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return ops.toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperationEntry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperationEntry.java
new file mode 100644
index 00000000..cc054286
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperationEntry.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A super class for batch operation entry classes.
+ * <p>
+ * This is the interface to classes which are maintained by BatchOperation as
+ * its entries.
+ */
+public class BatchOperationEntry<T extends Enum<?>, U> {
+
+ private final T operator;
+ private final U target;
+
+ /**
+ * Constructs new instance for the entry of the BatchOperation.
+ *
+ * @param operator the operator of this operation
+ * @param target the target object of this operation
+ */
+ public BatchOperationEntry(T operator, U target) {
+ this.operator = checkNotNull(operator);
+ this.target = checkNotNull(target);
+ }
+
+ /**
+ * Gets the target object of this operation.
+ *
+ * @return the target object of this operation
+ */
+ public U target() {
+ return target;
+ }
+
+ /**
+ * Gets the operator of this operation.
+ *
+ * @return the operator of this operation
+ */
+ public T operator() {
+ return operator;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ BatchOperationEntry<?, ?> other = (BatchOperationEntry<?, ?>) o;
+ return (this.operator == other.operator) &&
+ Objects.equals(this.target, other.target);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(operator, target);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("operator", operator)
+ .add("target", target)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperationResult.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperationResult.java
new file mode 100644
index 00000000..684a8698
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/BatchOperationResult.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import java.util.Set;
+
+/**
+ * Interface capturing the result of a batch operation.
+ *
+ */
+public interface BatchOperationResult<T> {
+
+ /**
+ * Returns whether the operation was successful.
+ * @return true if successful, false otherwise
+ */
+ boolean isSuccess();
+
+ /**
+ * Obtains a set of items which failed.
+ * @return a set of failures
+ */
+ Set<T> failedItems();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/CompletedBatchOperation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/CompletedBatchOperation.java
new file mode 100644
index 00000000..3afae5ef
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/CompletedBatchOperation.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.DeviceId;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Representation of a completed flow rule batch operation.
+ */
+public class CompletedBatchOperation implements BatchOperationResult<FlowRule> {
+
+ private final boolean success;
+ private final Set<FlowRule> failures;
+ private final Set<Long> failedIds;
+ private final DeviceId deviceId;
+
+ /**
+ * Creates a new batch completion result.
+ *
+ * @param success indicates whether the completion is successful
+ * @param failures set of any failures encountered
+ * @param failedIds (optional) set of failed operation ids
+ * @param deviceId the device this operation completed for
+ */
+ public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures,
+ Set<Long> failedIds, DeviceId deviceId) {
+ this.success = success;
+ this.failures = ImmutableSet.copyOf(failures);
+ this.failedIds = ImmutableSet.copyOf(failedIds);
+ this.deviceId = deviceId;
+ }
+
+ /**
+ * Creates a new batch completion result.
+ *
+ * @param success indicates whether the completion is successful.
+ * @param failures set of any failures encountered
+ * @param deviceId the device this operation completed for
+ */
+ public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures,
+ DeviceId deviceId) {
+ this.success = success;
+ this.failures = ImmutableSet.copyOf(failures);
+ this.failedIds = Collections.emptySet();
+ this.deviceId = deviceId;
+ }
+
+
+
+ @Override
+ public boolean isSuccess() {
+ return success;
+ }
+
+ @Override
+ public Set<FlowRule> failedItems() {
+ return failures;
+ }
+
+ public Set<Long> failedIds() {
+ return failedIds;
+ }
+
+ public DeviceId deviceId() {
+ return this.deviceId;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("success?", success)
+ .add("failedItems", failures)
+ .add("failedIds", failedIds)
+ .add("deviceId", deviceId)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowEntry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowEntry.java
new file mode 100644
index 00000000..f7e7708e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowEntry.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import org.slf4j.Logger;
+
+public class DefaultFlowEntry extends DefaultFlowRule
+ implements StoredFlowEntry {
+
+ private static final Logger log = getLogger(DefaultFlowEntry.class);
+
+ private long life;
+ private long packets;
+ private long bytes;
+ private FlowEntryState state;
+
+ private long lastSeen = -1;
+
+ private final int errType;
+
+ private final int errCode;
+
+ public DefaultFlowEntry(FlowRule rule, FlowEntryState state,
+ long life, long packets, long bytes) {
+ super(rule);
+ this.state = state;
+ this.life = life;
+ this.packets = packets;
+ this.bytes = bytes;
+ this.errCode = -1;
+ this.errType = -1;
+ this.lastSeen = System.currentTimeMillis();
+ }
+
+ public DefaultFlowEntry(FlowRule rule) {
+ super(rule);
+ this.state = FlowEntryState.PENDING_ADD;
+ this.life = 0;
+ this.packets = 0;
+ this.bytes = 0;
+ this.errCode = -1;
+ this.errType = -1;
+ this.lastSeen = System.currentTimeMillis();
+ }
+
+ public DefaultFlowEntry(FlowRule rule, int errType, int errCode) {
+ super(rule);
+ this.state = FlowEntryState.FAILED;
+ this.errType = errType;
+ this.errCode = errCode;
+ this.lastSeen = System.currentTimeMillis();
+ }
+
+ @Override
+ public long life() {
+ return life;
+ }
+
+ @Override
+ public long packets() {
+ return packets;
+ }
+
+ @Override
+ public long bytes() {
+ return bytes;
+ }
+
+ @Override
+ public FlowEntryState state() {
+ return this.state;
+ }
+
+ @Override
+ public long lastSeen() {
+ return lastSeen;
+ }
+
+ @Override
+ public void setLastSeen() {
+ this.lastSeen = System.currentTimeMillis();
+ }
+
+ @Override
+ public void setState(FlowEntryState newState) {
+ this.state = newState;
+ }
+
+ @Override
+ public void setLife(long life) {
+ this.life = life;
+ }
+
+ @Override
+ public void setPackets(long packets) {
+ this.packets = packets;
+ }
+
+ @Override
+ public void setBytes(long bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public int errType() {
+ return this.errType;
+ }
+
+ @Override
+ public int errCode() {
+ return this.errCode;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("rule", super.toString())
+ .add("state", state)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
new file mode 100644
index 00000000..44a4d364
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class DefaultFlowRule implements FlowRule {
+
+ private final DeviceId deviceId;
+ private final int priority;
+ private final TrafficSelector selector;
+ private final TrafficTreatment treatment;
+ private final long created;
+
+ private final FlowId id;
+
+ private final Short appId;
+
+ private final int timeout;
+ private final boolean permanent;
+ private final GroupId groupId;
+
+ private final Integer tableId;
+ private final FlowRuleExtPayLoad payLoad;
+
+ public DefaultFlowRule(FlowRule rule) {
+ this.deviceId = rule.deviceId();
+ this.priority = rule.priority();
+ this.selector = rule.selector();
+ this.treatment = rule.treatment();
+ this.appId = rule.appId();
+ this.groupId = rule.groupId();
+ this.id = rule.id();
+ this.timeout = rule.timeout();
+ this.permanent = rule.isPermanent();
+ this.created = System.currentTimeMillis();
+ this.tableId = rule.tableId();
+ this.payLoad = rule.payLoad();
+ }
+
+ private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
+ TrafficTreatment treatment, Integer priority,
+ FlowId flowId, Boolean permanent, Integer timeout,
+ Integer tableId) {
+
+ this.deviceId = deviceId;
+ this.selector = selector;
+ this.treatment = treatment;
+ this.priority = priority;
+ this.appId = (short) (flowId.value() >>> 48);
+ this.id = flowId;
+ this.permanent = permanent;
+ this.timeout = timeout;
+ this.tableId = tableId;
+ this.created = System.currentTimeMillis();
+
+
+ //FIXME: fields below will be removed.
+ this.groupId = new DefaultGroupId(0);
+ this.payLoad = null;
+ }
+
+ /**
+ * Support for the third party flow rule. Creates a flow rule of flow table.
+ *
+ * @param deviceId the identity of the device where this rule applies
+ * @param selector the traffic selector that identifies what traffic this
+ * rule
+ * @param treatment the traffic treatment that applies to selected traffic
+ * @param priority the flow rule priority given in natural order
+ * @param appId the application id of this flow
+ * @param timeout the timeout for this flow requested by an application
+ * @param permanent whether the flow is permanent i.e. does not time out
+ * @param payLoad 3rd-party origin private flow
+ */
+ public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
+ TrafficTreatment treatment, int priority,
+ ApplicationId appId, int timeout, boolean permanent,
+ FlowRuleExtPayLoad payLoad) {
+
+ if (priority < FlowRule.MIN_PRIORITY) {
+ throw new IllegalArgumentException("Priority cannot be less than "
+ + MIN_PRIORITY);
+ }
+
+ this.deviceId = deviceId;
+ this.priority = priority;
+ this.selector = selector;
+ this.treatment = treatment;
+ this.appId = appId.id();
+ this.groupId = new DefaultGroupId(0);
+ this.timeout = timeout;
+ this.permanent = permanent;
+ this.tableId = 0;
+ this.created = System.currentTimeMillis();
+ this.payLoad = payLoad;
+
+ /*
+ * id consists of the following. | appId (16 bits) | groupId (16 bits) |
+ * flowId (32 bits) |
+ */
+ this.id = FlowId.valueOf((((long) this.appId) << 48)
+ | (((long) this.groupId.id()) << 32)
+ | (this.hash() & 0xffffffffL));
+ }
+
+ /**
+ * Support for the third party flow rule. Creates a flow rule of group
+ * table.
+ *
+ * @param deviceId the identity of the device where this rule applies
+ * @param selector the traffic selector that identifies what traffic this
+ * rule
+ * @param treatment the traffic treatment that applies to selected traffic
+ * @param priority the flow rule priority given in natural order
+ * @param appId the application id of this flow
+ * @param groupId the group id of this flow
+ * @param timeout the timeout for this flow requested by an application
+ * @param permanent whether the flow is permanent i.e. does not time out
+ * @param payLoad 3rd-party origin private flow
+ *
+ */
+ public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
+ TrafficTreatment treatment, int priority,
+ ApplicationId appId, GroupId groupId, int timeout,
+ boolean permanent, FlowRuleExtPayLoad payLoad) {
+
+ if (priority < FlowRule.MIN_PRIORITY) {
+ throw new IllegalArgumentException("Priority cannot be less than "
+ + MIN_PRIORITY);
+ }
+
+ this.deviceId = deviceId;
+ this.priority = priority;
+ this.selector = selector;
+ this.treatment = treatment;
+ this.appId = appId.id();
+ this.groupId = groupId;
+ this.timeout = timeout;
+ this.permanent = permanent;
+ this.created = System.currentTimeMillis();
+ this.tableId = 0;
+ this.payLoad = payLoad;
+
+ /*
+ * id consists of the following. | appId (16 bits) | groupId (16 bits) |
+ * flowId (32 bits) |
+ */
+ this.id = FlowId.valueOf((((long) this.appId) << 48)
+ | (((long) this.groupId.id()) << 32)
+ | (this.hash() & 0xffffffffL));
+ }
+
+ @Override
+ public FlowId id() {
+ return id;
+ }
+
+ @Override
+ public short appId() {
+ return appId;
+ }
+
+ @Override
+ public GroupId groupId() {
+ return groupId;
+ }
+
+ @Override
+ public int priority() {
+ return priority;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public TrafficSelector selector() {
+ return selector;
+ }
+
+ @Override
+ public TrafficTreatment treatment() {
+ return treatment;
+ }
+
+ @Override
+ /*
+ * The priority and statistics can change on a given treatment and selector
+ *
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public int hashCode() {
+ return Objects.hash(deviceId, selector, tableId, payLoad);
+ }
+
+ //FIXME do we need this method in addition to hashCode()?
+ private int hash() {
+ return Objects.hash(deviceId, selector, tableId, payLoad);
+ }
+
+ @Override
+ /*
+ * The priority and statistics can change on a given treatment and selector
+ *
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultFlowRule) {
+ DefaultFlowRule that = (DefaultFlowRule) obj;
+ return Objects.equals(deviceId, that.deviceId) &&
+ Objects.equals(priority, that.priority) &&
+ Objects.equals(selector, that.selector) &&
+ Objects.equals(tableId, that.tableId)
+ && Objects.equals(payLoad, that.payLoad);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean exactMatch(FlowRule rule) {
+ return this.equals(rule) &&
+ Objects.equals(this.id, rule.id()) &&
+ Objects.equals(this.treatment, rule.treatment());
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("id", Long.toHexString(id.value()))
+ .add("deviceId", deviceId)
+ .add("priority", priority)
+ .add("selector", selector.criteria())
+ .add("treatment", treatment == null ? "N/A" : treatment.allInstructions())
+ .add("tableId", tableId)
+ .add("created", created)
+ .add("payLoad", payLoad)
+ .toString();
+ }
+
+ @Override
+ public int timeout() {
+ return timeout;
+ }
+
+ @Override
+ public boolean isPermanent() {
+ return permanent;
+ }
+
+ @Override
+ public int tableId() {
+ return tableId;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder implements FlowRule.Builder {
+
+ private FlowId flowId;
+ private Integer priority;
+ private DeviceId deviceId;
+ private Integer tableId = 0;
+ private TrafficSelector selector;
+ private TrafficTreatment treatment;
+ private Integer timeout;
+ private Boolean permanent;
+
+ @Override
+ public FlowRule.Builder withCookie(long cookie) {
+ this.flowId = FlowId.valueOf(cookie);
+ return this;
+ }
+
+ @Override
+ public FlowRule.Builder fromApp(ApplicationId appId) {
+ this.flowId = computeFlowId(appId);
+ return this;
+ }
+
+ @Override
+ public FlowRule.Builder withPriority(int priority) {
+ this.priority = priority;
+ return this;
+ }
+
+ @Override
+ public FlowRule.Builder forDevice(DeviceId deviceId) {
+ this.deviceId = deviceId;
+ return this;
+ }
+
+ @Override
+ public FlowRule.Builder forTable(int tableId) {
+ this.tableId = tableId;
+ return this;
+ }
+
+ @Override
+ public FlowRule.Builder withSelector(TrafficSelector selector) {
+ this.selector = selector;
+ return this;
+ }
+
+ @Override
+ public FlowRule.Builder withTreatment(TrafficTreatment treatment) {
+ this.treatment = treatment;
+ return this;
+ }
+
+ @Override
+ public FlowRule.Builder makePermanent() {
+ this.timeout = 0;
+ this.permanent = true;
+ return this;
+ }
+
+ @Override
+ public FlowRule.Builder makeTemporary(int timeout) {
+ this.permanent = false;
+ this.timeout = timeout;
+ return this;
+ }
+
+ @Override
+ public FlowRule build() {
+ checkNotNull(flowId != null, "Either an application" +
+ " id or a cookie must be supplied");
+ checkNotNull(selector != null, "Traffic selector cannot be null");
+ checkNotNull(timeout != null || permanent != null, "Must either have " +
+ "a timeout or be permanent");
+ checkNotNull(deviceId != null, "Must refer to a device");
+ checkNotNull(priority != null, "Priority cannot be null");
+ checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
+ MIN_PRIORITY);
+
+ return new DefaultFlowRule(deviceId, selector, treatment, priority,
+ flowId, permanent, timeout, tableId);
+ }
+
+ private FlowId computeFlowId(ApplicationId appId) {
+ return FlowId.valueOf((((long) appId.id()) << 48)
+ | (hash() & 0xffffffffL));
+ }
+
+ private int hash() {
+ return Objects.hash(deviceId, priority, selector, tableId);
+ }
+
+ }
+
+ @Override
+ public FlowRuleExtPayLoad payLoad() {
+ return payLoad;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
new file mode 100644
index 00000000..f88c6bc3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.IndexedLambda;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.Criterion;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Default traffic selector implementation.
+ */
+public final class DefaultTrafficSelector implements TrafficSelector {
+
+ private final Set<Criterion> criteria;
+
+ private static final TrafficSelector EMPTY
+ = new DefaultTrafficSelector(Collections.emptySet());
+
+ /**
+ * Creates a new traffic selector with the specified criteria.
+ *
+ * @param criteria criteria
+ */
+ private DefaultTrafficSelector(Set<Criterion> criteria) {
+ this.criteria = ImmutableSet.copyOf(criteria);
+ }
+
+ @Override
+ public Set<Criterion> criteria() {
+ return criteria;
+ }
+
+ @Override
+ public Criterion getCriterion(Criterion.Type type) {
+ for (Criterion c : criteria) {
+ if (c.type() == type) {
+ return c;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ return criteria.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultTrafficSelector) {
+ DefaultTrafficSelector that = (DefaultTrafficSelector) obj;
+ return Objects.equals(criteria, that.criteria);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("criteria", criteria)
+ .toString();
+ }
+
+ /**
+ * Returns a new traffic selector builder.
+ *
+ * @return traffic selector builder
+ */
+ public static TrafficSelector.Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Returns an empty traffic selector.
+ *
+ * @return empty traffic selector
+ */
+ public static TrafficSelector emptySelector() {
+ return EMPTY;
+ }
+
+ /**
+ * Returns a new traffic selector builder primed to produce entities
+ * patterned after the supplied selector.
+ *
+ * @param selector base selector
+ * @return traffic selector builder
+ */
+ public static TrafficSelector.Builder builder(TrafficSelector selector) {
+ return new Builder(selector);
+ }
+
+ /**
+ * Builder of traffic selector entities.
+ */
+ public static final class Builder implements TrafficSelector.Builder {
+
+ private final Map<Criterion.Type, Criterion> selector = new HashMap<>();
+
+ private Builder() {
+ }
+
+ private Builder(TrafficSelector selector) {
+ for (Criterion c : selector.criteria()) {
+ add(c);
+ }
+ }
+
+ @Override
+ public Builder add(Criterion criterion) {
+ selector.put(criterion.type(), criterion);
+ return this;
+ }
+
+ @Override
+ public Builder matchInPort(PortNumber port) {
+ return add(Criteria.matchInPort(port));
+ }
+
+ @Override
+ public Builder matchInPhyPort(PortNumber port) {
+ return add(Criteria.matchInPhyPort(port));
+ }
+
+ @Override
+ public Builder matchMetadata(long metadata) {
+ return add(Criteria.matchMetadata(metadata));
+ }
+
+ @Override
+ public Builder matchEthDst(MacAddress addr) {
+ return add(Criteria.matchEthDst(addr));
+ }
+
+ @Override
+ public Builder matchEthSrc(MacAddress addr) {
+ return add(Criteria.matchEthSrc(addr));
+ }
+
+ @Override
+ public Builder matchEthType(short ethType) {
+ return add(Criteria.matchEthType(ethType));
+ }
+
+ @Override
+ public Builder matchVlanId(VlanId vlanId) {
+ return add(Criteria.matchVlanId(vlanId));
+ }
+
+ @Override
+ public Builder matchVlanPcp(byte vlanPcp) {
+ return add(Criteria.matchVlanPcp(vlanPcp));
+ }
+
+ @Override
+ public Builder matchIPDscp(byte ipDscp) {
+ return add(Criteria.matchIPDscp(ipDscp));
+ }
+
+ @Override
+ public Builder matchIPEcn(byte ipEcn) {
+ return add(Criteria.matchIPEcn(ipEcn));
+ }
+
+ @Override
+ public Builder matchIPProtocol(byte proto) {
+ return add(Criteria.matchIPProtocol(proto));
+ }
+
+ @Override
+ public Builder matchIPSrc(IpPrefix ip) {
+ return add(Criteria.matchIPSrc(ip));
+ }
+
+ @Override
+ public Builder matchIPDst(IpPrefix ip) {
+ return add(Criteria.matchIPDst(ip));
+ }
+
+ @Deprecated
+ @Override
+ public Builder matchTcpSrc(short tcpPort) {
+ return matchTcpSrc(TpPort.tpPort(tcpPort));
+ }
+
+ @Override
+ public Builder matchTcpSrc(TpPort tcpPort) {
+ return add(Criteria.matchTcpSrc(tcpPort));
+ }
+
+ @Deprecated
+ @Override
+ public Builder matchTcpDst(short tcpPort) {
+ return matchTcpDst(TpPort.tpPort(tcpPort));
+ }
+
+ @Override
+ public Builder matchTcpDst(TpPort tcpPort) {
+ return add(Criteria.matchTcpDst(tcpPort));
+ }
+
+ @Deprecated
+ @Override
+ public Builder matchUdpSrc(short udpPort) {
+ return matchUdpSrc(TpPort.tpPort(udpPort));
+ }
+
+ @Override
+ public Builder matchUdpSrc(TpPort udpPort) {
+ return add(Criteria.matchUdpSrc(udpPort));
+ }
+
+ @Deprecated
+ @Override
+ public Builder matchUdpDst(short udpPort) {
+ return matchUdpDst(TpPort.tpPort(udpPort));
+ }
+
+ @Override
+ public Builder matchUdpDst(TpPort udpPort) {
+ return add(Criteria.matchUdpDst(udpPort));
+ }
+
+ @Deprecated
+ @Override
+ public Builder matchSctpSrc(short sctpPort) {
+ return matchSctpSrc(TpPort.tpPort(sctpPort));
+ }
+
+ @Override
+ public Builder matchSctpSrc(TpPort sctpPort) {
+ return add(Criteria.matchSctpSrc(sctpPort));
+ }
+
+ @Deprecated
+ @Override
+ public Builder matchSctpDst(short sctpPort) {
+ return matchSctpDst(TpPort.tpPort(sctpPort));
+ }
+
+ @Override
+ public Builder matchSctpDst(TpPort sctpPort) {
+ return add(Criteria.matchSctpDst(sctpPort));
+ }
+
+ @Override
+ public Builder matchIcmpType(byte icmpType) {
+ return add(Criteria.matchIcmpType(icmpType));
+ }
+
+ @Override
+ public Builder matchIcmpCode(byte icmpCode) {
+ return add(Criteria.matchIcmpCode(icmpCode));
+ }
+
+ @Override
+ public Builder matchIPv6Src(IpPrefix ip) {
+ return add(Criteria.matchIPv6Src(ip));
+ }
+
+ @Override
+ public Builder matchIPv6Dst(IpPrefix ip) {
+ return add(Criteria.matchIPv6Dst(ip));
+ }
+
+ @Override
+ public Builder matchIPv6FlowLabel(int flowLabel) {
+ return add(Criteria.matchIPv6FlowLabel(flowLabel));
+ }
+
+ @Override
+ public Builder matchIcmpv6Type(byte icmpv6Type) {
+ return add(Criteria.matchIcmpv6Type(icmpv6Type));
+ }
+
+ @Override
+ public Builder matchIcmpv6Code(byte icmpv6Code) {
+ return add(Criteria.matchIcmpv6Code(icmpv6Code));
+ }
+
+ @Override
+ public Builder matchIPv6NDTargetAddress(Ip6Address targetAddress) {
+ return add(Criteria.matchIPv6NDTargetAddress(targetAddress));
+ }
+
+ @Override
+ public Builder matchIPv6NDSourceLinkLayerAddress(MacAddress mac) {
+ return add(Criteria.matchIPv6NDSourceLinkLayerAddress(mac));
+ }
+
+ @Override
+ public Builder matchIPv6NDTargetLinkLayerAddress(MacAddress mac) {
+ return add(Criteria.matchIPv6NDTargetLinkLayerAddress(mac));
+ }
+
+ @Override
+ public Builder matchMplsLabel(MplsLabel mplsLabel) {
+ return add(Criteria.matchMplsLabel(mplsLabel));
+ }
+
+ @Override
+ public Builder matchMplsBos(boolean mplsBos) {
+ return add(Criteria.matchMplsLabel(mplsBos));
+ }
+
+ @Override
+ public TrafficSelector.Builder matchTunnelId(long tunnelId) {
+ return add(Criteria.matchTunnelId(tunnelId));
+ }
+
+ @Override
+ public Builder matchIPv6ExthdrFlags(short exthdrFlags) {
+ return add(Criteria.matchIPv6ExthdrFlags(exthdrFlags));
+ }
+
+ @Deprecated
+ @Override
+ public Builder matchLambda(short lambda) {
+ return add(Criteria.matchLambda(new IndexedLambda(lambda)));
+ }
+
+ @Deprecated
+ @Override
+ public Builder matchOpticalSignalType(short signalType) {
+ return add(Criteria.matchOpticalSignalType(signalType));
+ }
+
+ @Override
+ public TrafficSelector build() {
+ return new DefaultTrafficSelector(ImmutableSet.copyOf(selector.values()));
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
new file mode 100644
index 00000000..5d18a9ad
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.onlab.packet.EthType;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.IndexedLambda;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.meter.MeterId;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default traffic treatment implementation.
+ */
+public final class DefaultTrafficTreatment implements TrafficTreatment {
+
+ private final List<Instruction> immediate;
+ private final List<Instruction> deferred;
+ private final List<Instruction> all;
+ private final Instructions.TableTypeTransition table;
+ private final Instructions.MetadataInstruction meta;
+
+ private final boolean hasClear;
+
+ private static final DefaultTrafficTreatment EMPTY
+ = new DefaultTrafficTreatment(Collections.emptyList());
+ private final Instructions.MeterInstruction meter;
+
+ /**
+ * Creates a new traffic treatment from the specified list of instructions.
+ *
+ * @param immediate immediate instructions
+ */
+ private DefaultTrafficTreatment(List<Instruction> immediate) {
+ this.immediate = ImmutableList.copyOf(checkNotNull(immediate));
+ this.deferred = ImmutableList.of();
+ this.all = this.immediate;
+ this.hasClear = false;
+ this.table = null;
+ this.meta = null;
+ this.meter = null;
+ }
+
+ /**
+ * Creates a new traffic treatment from the specified list of instructions.
+ *
+ * @param deferred deferred instructions
+ * @param immediate immediate instructions
+ * @param table table transition instruction
+ * @param clear instruction to clear the deferred actions list
+ */
+ private DefaultTrafficTreatment(List<Instruction> deferred,
+ List<Instruction> immediate,
+ Instructions.TableTypeTransition table,
+ boolean clear,
+ Instructions.MetadataInstruction meta,
+ Instructions.MeterInstruction meter) {
+ this.immediate = ImmutableList.copyOf(checkNotNull(immediate));
+ this.deferred = ImmutableList.copyOf(checkNotNull(deferred));
+ this.all = new ImmutableList.Builder<Instruction>()
+ .addAll(immediate)
+ .addAll(deferred)
+ .build();
+ this.table = table;
+ this.meta = meta;
+ this.hasClear = clear;
+ this.meter = meter;
+ }
+
+ @Override
+ public List<Instruction> deferred() {
+ return deferred;
+ }
+
+ @Override
+ public List<Instruction> immediate() {
+ return immediate;
+ }
+
+ @Override
+ public List<Instruction> allInstructions() {
+ return all;
+ }
+
+ @Override
+ public Instructions.TableTypeTransition tableTransition() {
+ return table;
+ }
+
+ @Override
+ public boolean clearedDeferred() {
+ return hasClear;
+ }
+
+ @Override
+ public Instructions.MetadataInstruction writeMetadata() {
+ return meta;
+ }
+
+ @Override
+ public Instructions.MeterInstruction metered() {
+ return meter;
+ }
+
+ /**
+ * Returns a new traffic treatment builder.
+ *
+ * @return traffic treatment builder
+ */
+ public static TrafficTreatment.Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Returns an empty traffic treatment.
+ *
+ * @return empty traffic treatment
+ */
+ public static TrafficTreatment emptyTreatment() {
+ return EMPTY;
+ }
+
+ /**
+ * Returns a new traffic treatment builder primed to produce entities
+ * patterned after the supplied treatment.
+ *
+ * @param treatment base treatment
+ * @return traffic treatment builder
+ */
+ public static TrafficTreatment.Builder builder(TrafficTreatment treatment) {
+ return new Builder(treatment);
+ }
+
+ //FIXME: Order of instructions may affect hashcode
+ @Override
+ public int hashCode() {
+ return Objects.hash(immediate, deferred, table, meta);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultTrafficTreatment) {
+ DefaultTrafficTreatment that = (DefaultTrafficTreatment) obj;
+ return Objects.equals(immediate, that.immediate) &&
+ Objects.equals(deferred, that.deferred) &&
+ Objects.equals(table, that.table) &&
+ Objects.equals(meta, that.meta);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("immediate", immediate)
+ .add("deferred", deferred)
+ .add("transition", table == null ? "None" : table.toString())
+ .add("cleared", hasClear)
+ .add("metadata", meta)
+ .toString();
+ }
+
+ /**
+ * Builds a list of treatments following the following order.
+ * Modifications -&gt; Group -&gt; Output (including drop)
+ */
+ public static final class Builder implements TrafficTreatment.Builder {
+
+ boolean clear = false;
+
+ Instructions.TableTypeTransition table;
+
+ Instructions.MetadataInstruction meta;
+
+ Instructions.MeterInstruction meter;
+
+ List<Instruction> deferred = Lists.newLinkedList();
+
+ List<Instruction> immediate = Lists.newLinkedList();
+
+ List<Instruction> current = immediate;
+
+
+
+ // Creates a new builder
+ private Builder() {
+ }
+
+ // Creates a new builder based off an existing treatment
+ private Builder(TrafficTreatment treatment) {
+ deferred();
+ treatment.deferred().forEach(i -> add(i));
+
+ immediate();
+ treatment.immediate().forEach(i -> add(i));
+
+ clear = treatment.clearedDeferred();
+ }
+
+ @Override
+ public Builder add(Instruction instruction) {
+
+ switch (instruction.type()) {
+ case DROP:
+ case OUTPUT:
+ case GROUP:
+ case L0MODIFICATION:
+ case L2MODIFICATION:
+ case L3MODIFICATION:
+ case L4MODIFICATION:
+ current.add(instruction);
+ break;
+ case TABLE:
+ table = (Instructions.TableTypeTransition) instruction;
+ break;
+ case METADATA:
+ meta = (Instructions.MetadataInstruction) instruction;
+ break;
+ case METER:
+ meter = (Instructions.MeterInstruction) instruction;
+ default:
+ throw new IllegalArgumentException("Unknown instruction type: " +
+ instruction.type());
+ }
+
+ return this;
+ }
+
+ @Override
+ public Builder drop() {
+ return add(Instructions.createDrop());
+ }
+
+ @Override
+ public Builder punt() {
+ return add(Instructions.createOutput(PortNumber.CONTROLLER));
+ }
+
+ @Override
+ public Builder setOutput(PortNumber number) {
+ return add(Instructions.createOutput(number));
+ }
+
+ @Override
+ public Builder setEthSrc(MacAddress addr) {
+ return add(Instructions.modL2Src(addr));
+ }
+
+ @Override
+ public Builder setEthDst(MacAddress addr) {
+ return add(Instructions.modL2Dst(addr));
+ }
+
+ @Override
+ public Builder setVlanId(VlanId id) {
+ return add(Instructions.modVlanId(id));
+ }
+
+ @Override
+ public Builder setVlanPcp(Byte pcp) {
+ return add(Instructions.modVlanPcp(pcp));
+ }
+
+ @Override
+ public Builder setIpSrc(IpAddress addr) {
+ return add(Instructions.modL3Src(addr));
+ }
+
+ @Override
+ public Builder setIpDst(IpAddress addr) {
+ return add(Instructions.modL3Dst(addr));
+ }
+
+ @Override
+ public Builder decNwTtl() {
+ return add(Instructions.decNwTtl());
+ }
+
+ @Override
+ public Builder copyTtlIn() {
+ return add(Instructions.copyTtlIn());
+ }
+
+ @Override
+ public Builder copyTtlOut() {
+ return add(Instructions.copyTtlOut());
+ }
+
+ @Override
+ public Builder pushMpls() {
+ return add(Instructions.pushMpls());
+ }
+
+ @Override
+ public Builder popMpls() {
+ return add(Instructions.popMpls());
+ }
+
+ @Override
+ public Builder popMpls(int etherType) {
+ return add(Instructions.popMpls(new EthType(etherType)));
+ }
+
+ @Override
+ public Builder popMpls(EthType etherType) {
+ return add(Instructions.popMpls(etherType));
+ }
+
+ @Override
+ public Builder setMpls(MplsLabel mplsLabel) {
+ return add(Instructions.modMplsLabel(mplsLabel));
+ }
+
+ @Override
+ public Builder setMplsBos(boolean mplsBos) {
+ return add(Instructions.modMplsBos(mplsBos));
+ }
+
+ @Override
+ public Builder decMplsTtl() {
+ return add(Instructions.decMplsTtl());
+ }
+
+ @Deprecated
+ @Override
+ public Builder setLambda(short lambda) {
+ return add(Instructions.modL0Lambda(new IndexedLambda(lambda)));
+ }
+
+ @Override
+ public Builder group(GroupId groupId) {
+ return add(Instructions.createGroup(groupId));
+ }
+
+ @Override
+ public TrafficTreatment.Builder meter(MeterId meterId) {
+ return add(Instructions.meterTraffic(meterId));
+ }
+
+ @Override
+ public Builder popVlan() {
+ return add(Instructions.popVlan());
+ }
+
+ @Override
+ public Builder pushVlan() {
+ return add(Instructions.pushVlan());
+ }
+
+ @Override
+ public Builder transition(FlowRule.Type type) {
+ return add(Instructions.transition(type.ordinal()));
+ }
+
+ @Override
+ public Builder transition(Integer tableId) {
+ return add(Instructions.transition(tableId));
+ }
+
+ @Override
+ public Builder immediate() {
+ current = immediate;
+ return this;
+ }
+
+ @Override
+ public Builder deferred() {
+ current = deferred;
+ return this;
+ }
+
+ @Override
+ public Builder wipeDeferred() {
+ clear = true;
+ return this;
+ }
+
+ @Override
+ public Builder writeMetadata(long metadata, long metadataMask) {
+ return add(Instructions.writeMetadata(metadata, metadataMask));
+ }
+
+ @Override
+ public Builder setTunnelId(long tunnelId) {
+ return add(Instructions.modTunnelId(tunnelId));
+ }
+
+ @Deprecated
+ @Override
+ public TrafficTreatment.Builder setTcpSrc(short port) {
+ return setTcpSrc(TpPort.tpPort(port));
+ }
+
+ @Override
+ public TrafficTreatment.Builder setTcpSrc(TpPort port) {
+ return add(Instructions.modTcpSrc(port));
+ }
+
+ @Deprecated
+ @Override
+ public TrafficTreatment.Builder setTcpDst(short port) {
+ return setTcpDst(TpPort.tpPort(port));
+ }
+
+ @Override
+ public TrafficTreatment.Builder setTcpDst(TpPort port) {
+ return add(Instructions.modTcpDst(port));
+ }
+
+ @Deprecated
+ @Override
+ public TrafficTreatment.Builder setUdpSrc(short port) {
+ return setUdpSrc(TpPort.tpPort(port));
+ }
+
+ @Override
+ public TrafficTreatment.Builder setUdpSrc(TpPort port) {
+ return add(Instructions.modUdpSrc(port));
+ }
+
+ @Deprecated
+ @Override
+ public TrafficTreatment.Builder setUdpDst(short port) {
+ return setUdpDst(TpPort.tpPort(port));
+ }
+
+ @Override
+ public TrafficTreatment.Builder setUdpDst(TpPort port) {
+ return add(Instructions.modUdpDst(port));
+ }
+
+ @Override
+ public TrafficTreatment build() {
+ //Don't add DROP instruction by default when instruction
+ //set is empty. This will be handled in DefaultSingleTablePipeline
+ //driver.
+
+ //if (deferred.size() == 0 && immediate.size() == 0
+ // && table == null && !clear) {
+ // drop();
+ //}
+ return new DefaultTrafficTreatment(deferred, immediate, table, clear, meta, meter);
+ }
+
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowEntry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowEntry.java
new file mode 100644
index 00000000..389b2142
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowEntry.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+
+/**
+ * Represents a generalized match &amp; action pair to be applied to
+ * an infrastucture device.
+ */
+public interface FlowEntry extends FlowRule {
+
+
+ enum FlowEntryState {
+
+ /**
+ * Indicates that this rule has been submitted for addition.
+ * Not necessarily in the flow table.
+ */
+ PENDING_ADD,
+
+ /**
+ * Rule has been added which means it is in the flow table.
+ */
+ ADDED,
+
+ /**
+ * Flow has been marked for removal, might still be in flow table.
+ */
+ PENDING_REMOVE,
+
+ /**
+ * Flow has been removed from flow table and can be purged.
+ */
+ REMOVED,
+
+ /**
+ * Indicates that the installation of this flow has failed.
+ */
+ FAILED
+ }
+
+ /**
+ * Returns the flow entry state.
+ *
+ * @return flow entry state
+ */
+ FlowEntryState state();
+
+ /**
+ * Returns the number of milliseconds this flow rule has been applied.
+ *
+ * @return number of millis
+ */
+ long life();
+
+ /**
+ * Returns the number of packets this flow rule has matched.
+ *
+ * @return number of packets
+ */
+ long packets();
+
+ /**
+ * Returns the number of bytes this flow rule has matched.
+ *
+ * @return number of bytes
+ */
+ long bytes();
+
+ // TODO: consider removing this attribute
+ /**
+ * When this flow entry was last deemed active.
+ * @return epoch time of last activity
+ */
+ long lastSeen();
+
+ /**
+ * Indicates the error type.
+ * @return an integer value of the error
+ */
+ int errType();
+
+ /**
+ * Indicates the error code.
+ * @return an integer value of the error
+ */
+ int errCode();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowId.java
new file mode 100644
index 00000000..52500f59
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowId.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import com.google.common.base.Objects;
+
+/**
+ * Representation of a Flow ID.
+ */
+public final class FlowId {
+
+ private final long flowid;
+
+ private FlowId(long id) {
+ this.flowid = id;
+ }
+
+ public static FlowId valueOf(long id) {
+ return new FlowId(id);
+ }
+
+ public long value() {
+ return flowid;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (obj.getClass() == this.getClass()) {
+ FlowId that = (FlowId) obj;
+ return Objects.equal(this.flowid, that.flowid);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.flowid);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
new file mode 100644
index 00000000..e446a9fe
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Represents a generalized match &amp; action pair to be applied to an
+ * infrastructure device.
+ */
+public interface FlowRule {
+
+ static final int MAX_TIMEOUT = 60;
+ static final int MIN_PRIORITY = 0;
+
+ /**
+ * The FlowRule type is used to determine in which table the flow rule needs
+ * to be put for multi-table support switch. For single table switch,
+ * Default is used.
+ *
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ static enum Type {
+ /*
+ * Default type - used in flow rule for single table switch NOTE: this
+ * setting should not be used as Table 0 in a multi-table pipeline
+ */
+ DEFAULT,
+ /* Used in flow entry for IP table */
+ IP,
+ /* Used in flow entry for MPLS table */
+ MPLS,
+ /* Used in flow entry for ACL table */
+ ACL,
+
+ /* VLAN-to-MPLS table */
+ VLAN_MPLS,
+
+ /* VLAN table */
+ VLAN,
+
+ /* Ethtype table */
+ ETHER,
+
+ /* Class of Service table */
+ COS,
+
+ /* Table 0 in a multi-table pipeline */
+ FIRST,
+ }
+
+ /**
+ * Returns the ID of this flow.
+ *
+ * @return the flow ID
+ */
+ FlowId id();
+
+ /**
+ * Returns the application id of this flow.
+ *
+ * @return an applicationId
+ */
+ short appId();
+
+ /**
+ * Returns the group id of this flow.
+ *
+ * @return an groupId
+ */
+ GroupId groupId();
+
+ /**
+ * Returns the flow rule priority given in natural order; higher numbers
+ * mean higher priorities.
+ *
+ * @return flow rule priority
+ */
+ int priority();
+
+ /**
+ * Returns the identity of the device where this rule applies.
+ *
+ * @return device identifier
+ */
+ DeviceId deviceId();
+
+ /**
+ * Returns the traffic selector that identifies what traffic this rule
+ * should apply to.
+ *
+ * @return traffic selector
+ */
+ TrafficSelector selector();
+
+ /**
+ * Returns the traffic treatment that applies to selected traffic.
+ *
+ * @return traffic treatment
+ */
+ TrafficTreatment treatment();
+
+ /**
+ * Returns the timeout for this flow requested by an application.
+ *
+ * @return integer value of the timeout
+ */
+ int timeout();
+
+ /**
+ * Returns whether the flow is permanent i.e. does not time out.
+ *
+ * @return true if the flow is permanent, otherwise false
+ */
+ boolean isPermanent();
+
+ /**
+ * Returns the table id for this rule.
+ *
+ * @return an integer.
+ */
+ int tableId();
+
+ /**
+ * {@inheritDoc}
+ *
+ * Equality for flow rules only considers 'match equality'. This means that
+ * two flow rules with the same match conditions will be equal, regardless
+ * of the treatment or other characteristics of the flow.
+ *
+ * @param obj the reference object with which to compare.
+ * @return {@code true} if this object is the same as the obj
+ * argument; {@code false} otherwise.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * Returns whether this flow rule is an exact match to the flow rule given
+ * in the argument.
+ * <p>
+ * Exact match means that deviceId, priority, selector,
+ * tableId, flowId and treatment are equal. Note that this differs from
+ * the notion of object equality for flow rules, which does not consider the
+ * flowId or treatment when testing equality.
+ * </p>
+ *
+ * @param rule other rule to match against
+ * @return true if the rules are an exact match, otherwise false
+ */
+ boolean exactMatch(FlowRule rule);
+
+ /**
+ * A flowrule builder.
+ */
+ interface Builder {
+
+ /**
+ * Assigns a cookie value to this flowrule. Mutually exclusive with the
+ * fromApp method. This method is intended to take a cookie value from
+ * the dataplane and not from the application.
+ *
+ * @param cookie a long value
+ * @return this
+ */
+ Builder withCookie(long cookie);
+
+ /**
+ * Assigns the application that built this flow rule to this object.
+ * The short value of the appId will be used as a basis for the
+ * cookie value computation. It is expected that application use this
+ * call to set their application id.
+ *
+ * @param appId an application id
+ * @return this
+ */
+ Builder fromApp(ApplicationId appId);
+
+ /**
+ * Sets the priority for this flow rule.
+ *
+ * @param priority an integer
+ * @return this
+ */
+ Builder withPriority(int priority);
+
+ /**
+ * Sets the deviceId for this flow rule.
+ *
+ * @param deviceId a device id
+ * @return this
+ */
+ Builder forDevice(DeviceId deviceId);
+
+ /**
+ * Sets the table id for this flow rule. Default value is 0.
+ *
+ * @param tableId an integer
+ * @return this
+ */
+ Builder forTable(int tableId);
+
+ /**
+ * Sets the selector (or match field) for this flow rule.
+ *
+ * @param selector a traffic selector
+ * @return this
+ */
+ Builder withSelector(TrafficSelector selector);
+
+ /**
+ * Sets the traffic treatment for this flow rule.
+ *
+ * @param treatment a traffic treatment
+ * @return this
+ */
+ Builder withTreatment(TrafficTreatment treatment);
+
+ /**
+ * Makes this rule permanent on the dataplane.
+ *
+ * @return this
+ */
+ Builder makePermanent();
+
+ /**
+ * Makes this rule temporary and timeout after the specified amount
+ * of time.
+ *
+ * @param timeout an integer
+ * @return this
+ */
+ Builder makeTemporary(int timeout);
+
+ /**
+ * Builds a flow rule object.
+ *
+ * @return a flow rule.
+ */
+ FlowRule build();
+
+ }
+
+ /**
+ * Returns the third party original flow rule.
+ *
+ * @return FlowRuleExtPayLoad
+ */
+ FlowRuleExtPayLoad payLoad();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEntry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEntry.java
new file mode 100644
index 00000000..455c6bd8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEntry.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
+
+@Deprecated
+/**
+ * @deprecated in Drake release - no longer a public API
+ */
+public class FlowRuleBatchEntry
+ extends BatchOperationEntry<FlowRuleOperation, FlowRule> {
+
+ private final Long id; // FIXME: consider using Optional<Long>
+
+ public FlowRuleBatchEntry(FlowRuleOperation operator, FlowRule target) {
+ super(operator, target);
+ this.id = null;
+ }
+
+ public FlowRuleBatchEntry(FlowRuleOperation operator, FlowRule target, Long id) {
+ super(operator, target);
+ this.id = id;
+ }
+
+ public Long id() {
+ return id;
+ }
+
+ public enum FlowRuleOperation {
+ ADD,
+ REMOVE,
+ MODIFY
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEvent.java
new file mode 100644
index 00000000..2e823c23
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEvent.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.DeviceId;
+
+@Deprecated
+/**
+ * Describes flow rule batch event.
+ *
+ * @deprecated in Drake release - no longer a public API
+ */
+public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.Type, FlowRuleBatchRequest> {
+
+
+ /**
+ * Type of flow rule events.
+ */
+ public enum Type {
+
+ // Request has been forwarded to MASTER Node
+ /**
+ * Signifies that a batch operation has been initiated.
+ */
+ BATCH_OPERATION_REQUESTED,
+
+ // MASTER Node has pushed the batch down to the Device
+ // (e.g., Received barrier reply)
+ /**
+ * Signifies that a batch operation has completed.
+ */
+ BATCH_OPERATION_COMPLETED,
+ }
+
+ private final CompletedBatchOperation result;
+ private final DeviceId deviceId;
+
+ /**
+ * Constructs a new FlowRuleBatchEvent.
+ *
+ * @param request batch operation request
+ * @param deviceId the device this batch will be processed on
+ * @return event.
+ */
+ public static FlowRuleBatchEvent requested(FlowRuleBatchRequest request, DeviceId deviceId) {
+ FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_REQUESTED, request, deviceId);
+ return event;
+ }
+
+ /**
+ * Constructs a new FlowRuleBatchEvent.
+ * @param request batch operation request.
+ * @param result completed batch operation result.
+ * @return event.
+ */
+ public static FlowRuleBatchEvent completed(FlowRuleBatchRequest request, CompletedBatchOperation result) {
+ FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_COMPLETED, request, result);
+ return event;
+ }
+
+ /**
+ * Returns the result of this batch operation.
+ * @return batch operation result.
+ */
+ public CompletedBatchOperation result() {
+ return result;
+ }
+
+ /**
+ * Returns the deviceId for this batch.
+ * @return device id
+ */
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ /**
+ * Creates an event of a given type and for the specified flow rule batch.
+ *
+ * @param type flow rule batch event type
+ * @param request event flow rule batch subject
+ * @param result the result of the batch operation
+ */
+ private FlowRuleBatchEvent(Type type, FlowRuleBatchRequest request, CompletedBatchOperation result) {
+ super(type, request);
+ this.result = result;
+ this.deviceId = result.deviceId();
+ }
+
+ /**
+ * Creates an event of a given type and for the specified flow rule batch.
+ *
+ * @param type flow rule batch event type
+ * @param request event flow rule batch subject
+ * @param deviceId the device id for this batch
+ */
+ private FlowRuleBatchEvent(Type type, FlowRuleBatchRequest request, DeviceId deviceId) {
+ super(type, request);
+ this.result = null;
+ this.deviceId = deviceId;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchOperation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchOperation.java
new file mode 100644
index 00000000..35428f46
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchOperation.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.net.DeviceId;
+
+import java.util.Collection;
+
+@Deprecated
+/**
+ * Class used with the flow subsystem to process per device
+ * batches.
+ *
+ * @deprecated in Drake release - no longer a public API
+ */
+public class FlowRuleBatchOperation
+ extends BatchOperation<FlowRuleBatchEntry> {
+
+ /**
+ * This id is used to cary to id of the original
+ * FlowOperations and track where this batch operation
+ * came from. The id is unique cluster wide.
+ */
+ private final long id;
+ private final DeviceId deviceId;
+
+ public FlowRuleBatchOperation(Collection<FlowRuleBatchEntry> operations,
+ DeviceId deviceId, long flowOperationId) {
+ super(operations);
+ this.id = flowOperationId;
+ this.deviceId = deviceId;
+ }
+
+ public DeviceId deviceId() {
+ return this.deviceId;
+ }
+
+ public long id() {
+ return id;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchRequest.java
new file mode 100644
index 00000000..0b0585b9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchRequest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import com.google.common.collect.Lists;
+import org.onosproject.net.DeviceId;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+@Deprecated
+/**
+ * @deprecated in Drake release - no longer a public API
+ */
+public class FlowRuleBatchRequest {
+
+ /**
+ * This id is used to carry to id of the original
+ * FlowOperations and track where this batch operation
+ * came from. The id is unique cluster wide.
+ */
+ private final long batchId;
+
+ private final Set<FlowRuleBatchEntry> ops;
+
+
+ public FlowRuleBatchRequest(long batchId, Set<FlowRuleBatchEntry> ops) {
+ this.batchId = batchId;
+ this.ops = Collections.unmodifiableSet(ops);
+ }
+
+ public Set<FlowRuleBatchEntry> ops() {
+ return ops;
+ }
+
+ public FlowRuleBatchOperation asBatchOperation(DeviceId deviceId) {
+ List<FlowRuleBatchEntry> entries = Lists.newArrayList();
+ entries.addAll(ops);
+ return new FlowRuleBatchOperation(entries, deviceId, batchId);
+ }
+
+ public long batchId() {
+ return batchId;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleEvent.java
new file mode 100644
index 00000000..41ef1c8a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleEvent.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes flow rule event.
+ */
+public class FlowRuleEvent extends AbstractEvent<FlowRuleEvent.Type, FlowRule> {
+
+ /**
+ * Type of flow rule events.
+ */
+ public enum Type {
+ /**
+ * Signifies that a new flow rule has been detected.
+ */
+ RULE_ADDED,
+
+ /**
+ * Signifies that a flow rule has been removed.
+ */
+ RULE_REMOVED,
+
+ /**
+ * Signifies that a rule has been 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,
+ }
+
+ /**
+ * Creates an event of a given type and for the specified flow rule and the
+ * current time.
+ *
+ * @param type flow rule event type
+ * @param flowRule event flow rule subject
+ */
+ public FlowRuleEvent(Type type, FlowRule flowRule) {
+ super(type, flowRule);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified flow rule and time.
+ *
+ * @param type flow rule event type
+ * @param flowRule event flow rule subject
+ * @param time occurrence time
+ */
+ public FlowRuleEvent(Type type, FlowRule flowRule, long time) {
+ super(type, flowRule, time);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleExtPayLoad.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleExtPayLoad.java
new file mode 100644
index 00000000..8d36be49
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleExtPayLoad.java
@@ -0,0 +1,67 @@
+package org.onosproject.net.flow;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import java.util.Arrays;
+
+/**
+ * Represents for 3rd-party private original flow.
+ */
+public final class FlowRuleExtPayLoad {
+ private final byte[] payLoad;
+
+ /**
+ * private constructor.
+ *
+ * @param payLoad private flow
+ */
+ private FlowRuleExtPayLoad(byte[] payLoad) {
+ this.payLoad = payLoad;
+ }
+
+ /**
+ * Creates a FlowRuleExtPayLoad.
+ *
+ * @param payLoad payload byte data
+ * @return FlowRuleExtPayLoad payLoad
+ */
+ public static FlowRuleExtPayLoad flowRuleExtPayLoad(byte[] payLoad) {
+ return new FlowRuleExtPayLoad(payLoad);
+ }
+
+ /**
+ * Returns private flow.
+ *
+ * @return payLoad private flow
+ */
+ public byte[] payLoad() {
+ return payLoad;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(payLoad);
+ }
+
+ public int hash() {
+ return Arrays.hashCode(payLoad);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof FlowRuleExtPayLoad) {
+ FlowRuleExtPayLoad that = (FlowRuleExtPayLoad) obj;
+ return Arrays.equals(payLoad, that.payLoad);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("payLoad", payLoad).toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleListener.java
new file mode 100644
index 00000000..1a6ef7d9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving flow rule related events.
+ */
+public interface FlowRuleListener extends EventListener<FlowRuleEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperation.java
new file mode 100644
index 00000000..82d43be8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperation.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Representation of an operation on a flow rule table.
+ */
+public class FlowRuleOperation {
+
+ /**
+ * Type of flow table operations.
+ */
+ public enum Type {
+ ADD,
+ MODIFY,
+ REMOVE
+ }
+
+ private final FlowRule rule;
+ private final Type type;
+
+ public FlowRuleOperation(FlowRule rule, Type type) {
+ this.rule = rule;
+ this.type = type;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return type
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the flow rule.
+ *
+ * @return flow rule
+ */
+ public FlowRule rule() {
+ return rule;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("rule", rule)
+ .add("type", type)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperations.java
new file mode 100644
index 00000000..84e0b8be
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperations.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.onosproject.net.flow.FlowRuleOperation.Type.*;
+
+/**
+ * A batch of flow rule operations that are broken into stages.
+ * TODO move this up to parent's package
+ */
+public class FlowRuleOperations {
+
+ private final List<Set<FlowRuleOperation>> stages;
+ private final FlowRuleOperationsContext callback; // TODO consider Optional
+
+ private FlowRuleOperations(List<Set<FlowRuleOperation>> stages,
+ FlowRuleOperationsContext cb) {
+ this.stages = stages;
+ this.callback = cb;
+ }
+
+ // kryo-constructor
+ protected FlowRuleOperations() {
+ this.stages = Lists.newArrayList();
+ this.callback = null;
+ }
+
+ /**
+ * Returns the flow rule operations as sets of stages that should be
+ * executed sequentially.
+ *
+ * @return flow rule stages
+ */
+ public List<Set<FlowRuleOperation>> stages() {
+ return stages;
+ }
+
+ /**
+ * Returns the callback for this batch of operations.
+ *
+ * @return callback
+ */
+ public FlowRuleOperationsContext callback() {
+ return callback;
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("stages", stages)
+ .toString();
+ }
+
+ /**
+ * A builder for constructing flow rule operations.
+ */
+ public static final class Builder {
+
+ private final ImmutableList.Builder<Set<FlowRuleOperation>> listBuilder = ImmutableList.builder();
+ private ImmutableSet.Builder<FlowRuleOperation> currentStage = ImmutableSet.builder();
+
+ // prevent use of the default constructor outside of this file; use the above method
+ private Builder() {}
+
+ /**
+ * Appends a flow rule add to the current stage.
+ *
+ * @param flowRule flow rule
+ * @return this
+ */
+ public Builder add(FlowRule flowRule) {
+ currentStage.add(new FlowRuleOperation(flowRule, ADD));
+ return this;
+ }
+
+ /**
+ * Appends an existing flow rule to the current stage.
+ *
+ * @param flowRuleOperation flow rule operation
+ * @return this
+ */
+ public Builder operation(FlowRuleOperation flowRuleOperation) {
+ currentStage.add(flowRuleOperation);
+ return this;
+ }
+
+ /**
+ * Appends a flow rule modify to the current stage.
+ *
+ * @param flowRule flow rule
+ * @return this
+ */
+ public Builder modify(FlowRule flowRule) {
+ currentStage.add(new FlowRuleOperation(flowRule, MODIFY));
+ return this;
+ }
+
+ /**
+ * Appends a flow rule remove to the current stage.
+ *
+ * @param flowRule flow rule
+ * @return this
+ */
+ // FIXME this is confusing, consider renaming
+ public Builder remove(FlowRule flowRule) {
+ currentStage.add(new FlowRuleOperation(flowRule, REMOVE));
+ return this;
+ }
+
+ /**
+ * Closes the current stage.
+ */
+ private void closeStage() {
+ ImmutableSet<FlowRuleOperation> stage = currentStage.build();
+ if (!stage.isEmpty()) {
+ listBuilder.add(stage);
+ }
+ }
+
+ /**
+ * Closes the current stage and starts a new one.
+ *
+ * @return this
+ */
+ public Builder newStage() {
+ closeStage();
+ currentStage = ImmutableSet.builder();
+ return this;
+ }
+
+ /**
+ * Builds the immutable flow rule operations.
+ *
+ * @return flow rule operations
+ */
+ public FlowRuleOperations build() {
+ return build(null);
+ }
+
+ /**
+ * Builds the immutable flow rule operations.
+ *
+ * @param cb the callback to call when this operation completes
+ * @return flow rule operations
+ */
+ public FlowRuleOperations build(FlowRuleOperationsContext cb) {
+ closeStage();
+ return new FlowRuleOperations(listBuilder.build(), cb);
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperationsContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperationsContext.java
new file mode 100644
index 00000000..c405b129
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleOperationsContext.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+/**
+ * The context of a flow rule operations that will become the subject of
+ * the notification.
+ *
+ * Implementations of this class must be serializable.
+ */
+public interface FlowRuleOperationsContext {
+ // TODO we might also want to execute a method on behalf of the app
+ default void onSuccess(FlowRuleOperations ops){}
+ default void onError(FlowRuleOperations ops){}
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProvider.java
new file mode 100644
index 00000000..ac2895eb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProvider.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Abstraction of a flow rule provider.
+ */
+public interface FlowRuleProvider extends Provider {
+
+ /**
+ * Instructs the provider to apply the specified flow rules to their
+ * respective devices.
+ * @param flowRules one or more flow rules
+ * throws SomeKindOfException that indicates which ones were applied and
+ * which ones failed
+ */
+ void applyFlowRule(FlowRule... flowRules);
+
+ /**
+ * Instructs the provider to remove the specified flow rules to their
+ * respective devices.
+ * @param flowRules one or more flow rules
+ * throws SomeKindOfException that indicates which ones were applied and
+ * which ones failed
+ */
+ void removeFlowRule(FlowRule... flowRules);
+
+ /**
+ * Removes rules by their id.
+ * @param id the id to remove
+ * @param flowRules one or more flow rules
+ */
+ void removeRulesById(ApplicationId id, FlowRule... flowRules);
+
+ /**
+ * Installs a batch of flow rules. Each flowrule is associated to an
+ * operation which results in either addition, removal or modification.
+ * @param batch a batch of flow rules
+ */
+ void executeBatch(FlowRuleBatchOperation batch);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProviderRegistry.java
new file mode 100644
index 00000000..7e317c01
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction for a flow rule provider registry.
+ */
+public interface FlowRuleProviderRegistry
+ extends ProviderRegistry<FlowRuleProvider, FlowRuleProviderService> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProviderService.java
new file mode 100644
index 00000000..8a36a921
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProviderService.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.ProviderService;
+
+/**
+ * Service through which flow rule providers can inject information into
+ * the core.
+ */
+public interface FlowRuleProviderService extends ProviderService<FlowRuleProvider> {
+
+ /**
+ * Signals that a flow rule that was previously installed has been removed.
+ *
+ * @param flowEntry removed flow entry
+ */
+ void flowRemoved(FlowEntry flowEntry);
+
+ /**
+ * Pushes the collection of flow entries currently applied on the given
+ * device.
+ *
+ * @param deviceId device identifier
+ * @param flowEntries collection of flow rules
+ */
+ void pushFlowMetrics(DeviceId deviceId, Iterable<FlowEntry> flowEntries);
+
+ /**
+ * Indicates to the core that the requested batch operation has
+ * been completed.
+ *
+ * @param batchId the batch which was processed
+ * @param operation the resulting outcome of the operation
+ */
+ void batchOperationCompleted(long batchId, CompletedBatchOperation operation);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleService.java
new file mode 100644
index 00000000..e2971158
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleService.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Service for injecting flow rules into the environment and for obtaining
+ * information about flow rules already in the environment. This implements
+ * semantics of a distributed authoritative flow table where the master copy
+ * of the flow rules lies with the controller and the devices hold only the
+ * 'cached' copy.
+ */
+public interface FlowRuleService
+ extends ListenerService<FlowRuleEvent, FlowRuleListener> {
+
+ /**
+ * The topic used for obtaining globally unique ids.
+ */
+ static String FLOW_OP_TOPIC = "flow-ops-ids";
+
+ /**
+ * Returns the number of flow rules in the system.
+ *
+ * @return flow rule count
+ */
+ int getFlowRuleCount();
+
+ /**
+ * Returns the collection of flow entries applied on the specified device.
+ * This will include flow rules which may not yet have been applied to
+ * the device.
+ *
+ * @param deviceId device identifier
+ * @return collection of flow rules
+ */
+ Iterable<FlowEntry> getFlowEntries(DeviceId deviceId);
+
+ // TODO: add createFlowRule factory method and execute operations method
+
+ /**
+ * Applies the specified flow rules onto their respective devices. These
+ * flow rules will be retained by the system and re-applied anytime the
+ * device reconnects to the controller.
+ *
+ * @param flowRules one or more flow rules
+ */
+ void applyFlowRules(FlowRule... flowRules);
+
+ /**
+ * Removes the specified flow rules from their respective devices. If the
+ * device is not presently connected to the controller, these flow will
+ * be removed once the device reconnects.
+ *
+ * @param flowRules one or more flow rules
+ * throws SomeKindOfException that indicates which ones were removed and
+ * which ones failed
+ */
+ void removeFlowRules(FlowRule... flowRules);
+
+ /**
+ * Removes all rules by id.
+ *
+ * @param appId id to remove
+ */
+ void removeFlowRulesById(ApplicationId appId);
+
+ /**
+ * Returns a list of rules with this application id.
+ *
+ * @param id the id to look up
+ * @return collection of flow rules
+ */
+ Iterable<FlowRule> getFlowRulesById(ApplicationId id);
+
+ /**
+ * Returns a list of rules filterd by application and group id.
+ *
+ * @param appId the application id to lookup
+ * @param groupId the groupid to lookup
+ * @return collection of flow rules
+ */
+ Iterable<FlowRule> getFlowRulesByGroupId(ApplicationId appId, short groupId);
+
+ /**
+ * Applies a batch operation of FlowRules.
+ *
+ * @param ops batch operation to apply
+ */
+ void apply(FlowRuleOperations ops);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStore.java
new file mode 100644
index 00000000..cece9893
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStore.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.Store;
+
+/**
+ * Manages inventory of flow rules; not intended for direct use.
+ */
+public interface FlowRuleStore extends Store<FlowRuleBatchEvent, FlowRuleStoreDelegate> {
+
+ /**
+ * Returns the number of flow rule in the store.
+ *
+ * @return number of flow rules
+ */
+ int getFlowRuleCount();
+
+ /**
+ * Returns the stored flow.
+ *
+ * @param rule the rule to look for
+ * @return a flow rule
+ */
+ FlowEntry getFlowEntry(FlowRule rule);
+
+ /**
+ * Returns the flow entries associated with a device.
+ *
+ * @param deviceId the device ID
+ * @return the flow entries
+ */
+ Iterable<FlowEntry> getFlowEntries(DeviceId deviceId);
+
+ /**
+ * // TODO: Better description of method behavior.
+ * Stores a new flow rule without generating events.
+ *
+ * @param rule the flow rule to add
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ void storeFlowRule(FlowRule rule);
+
+ /**
+ * Stores a batch of flow rules.
+ *
+ * @param batchOperation batch of flow rules.
+ * A batch can contain flow rules for a single device only.
+ *
+ */
+ void storeBatch(FlowRuleBatchOperation batchOperation);
+
+ /**
+ * Invoked on the completion of a storeBatch operation.
+ *
+ * @param event flow rule batch event
+ */
+ void batchOperationComplete(FlowRuleBatchEvent event);
+
+ /**
+ * 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
+ */
+ void deleteFlowRule(FlowRule rule);
+
+ /**
+ * Stores a new flow rule, or updates an existing entry.
+ *
+ * @param rule the flow rule to add or update
+ * @return flow_added event, or null if just an update
+ */
+ FlowRuleEvent addOrUpdateFlowRule(FlowEntry rule);
+
+ /**
+ * @param rule the flow entry to remove
+ * @return flow_removed event, or null if nothing removed
+ */
+ FlowRuleEvent removeFlowRule(FlowEntry rule);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStoreDelegate.java
new file mode 100644
index 00000000..c4ddb129
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Flow rule store delegate abstraction.
+ */
+public interface FlowRuleStoreDelegate extends StoreDelegate<FlowRuleBatchEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/StoredFlowEntry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/StoredFlowEntry.java
new file mode 100644
index 00000000..dc0c3395
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/StoredFlowEntry.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+
+public interface StoredFlowEntry extends FlowEntry {
+
+ /**
+ * Sets the last active epoch time.
+ */
+ void setLastSeen();
+
+ /**
+ * Sets the new state for this entry.
+ * @param newState new flow entry state.
+ */
+ void setState(FlowEntryState newState);
+
+ /**
+ * Sets how long this entry has been entered in the system.
+ * @param life epoch time
+ */
+ void setLife(long life);
+
+ /**
+ * Number of packets seen by this entry.
+ * @param packets a long value
+ */
+ void setPackets(long packets);
+
+ /**
+ * Number of bytes seen by this rule.
+ * @param bytes a long value
+ */
+ void setBytes(long bytes);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
new file mode 100644
index 00000000..f2de9a0f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import java.util.Set;
+
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector.Builder;
+import org.onosproject.net.flow.criteria.Criterion;
+
+/**
+ * Abstraction of a slice of network traffic.
+ */
+public interface TrafficSelector {
+
+ /**
+ * Returns selection criteria as an ordered list.
+ *
+ * @return list of criteria
+ */
+ Set<Criterion> criteria();
+
+ /**
+ * Returns the selection criterion for a particular type, if it exists in
+ * this traffic selector.
+ *
+ * @param type criterion type to look up
+ * @return the criterion of the specified type if one exists, otherwise null
+ */
+ Criterion getCriterion(Criterion.Type type);
+
+ /**
+ * Builder of traffic selector entities.
+ */
+ interface Builder {
+
+ /**
+ * Adds a traffic selection criterion. If a same type criterion has
+ * already been added, it will be replaced by this one.
+ *
+ * @param criterion new criterion
+ * @return self
+ */
+ Builder add(Criterion criterion);
+
+ /**
+ * Matches an inport.
+ *
+ * @param port the inport
+ * @return a selection builder
+ */
+ Builder matchInPort(PortNumber port);
+
+ /**
+ * Matches a physical inport.
+ *
+ * @param port the physical inport
+ * @return a selection builder
+ */
+ Builder matchInPhyPort(PortNumber port);
+
+ /**
+ * Matches a metadata.
+ *
+ * @param metadata the metadata
+ * @return a selection builder
+ */
+ Builder matchMetadata(long metadata);
+
+ /**
+ * Matches a l2 dst address.
+ *
+ * @param addr a l2 address
+ * @return a selection builder
+ */
+ Builder matchEthDst(MacAddress addr);
+
+ /**
+ * Matches a l2 src address.
+ *
+ * @param addr a l2 address
+ * @return a selection builder
+ */
+ Builder matchEthSrc(MacAddress addr);
+
+ /**
+ * Matches the ethernet type.
+ *
+ * @param ethType an ethernet type
+ * @return a selection builder
+ */
+ Builder matchEthType(short ethType);
+
+ /**
+ * Matches the vlan id.
+ *
+ * @param vlanId a vlan id
+ * @return a selection builder
+ */
+ Builder matchVlanId(VlanId vlanId);
+
+ /**
+ * Matches a vlan priority.
+ *
+ * @param vlanPcp a vlan priority
+ * @return a selection builder
+ */
+ Builder matchVlanPcp(byte vlanPcp);
+
+ /**
+ * Matches an IP DSCP (6 bits in ToS field).
+ *
+ * @param ipDscp an IP DSCP value
+ * @return a selection builder
+ */
+ Builder matchIPDscp(byte ipDscp);
+
+ /**
+ * Matches an IP ECN (2 bits in ToS field).
+ *
+ * @param ipEcn an IP ECN value
+ * @return a selection builder
+ */
+ Builder matchIPEcn(byte ipEcn);
+
+ /**
+ * Matches the l3 protocol.
+ *
+ * @param proto a l3 protocol
+ * @return a selection builder
+ */
+ Builder matchIPProtocol(byte proto);
+
+ /**
+ * Matches a l3 IPv4 address.
+ *
+ * @param ip a l3 address
+ * @return a selection builder
+ */
+ Builder matchIPSrc(IpPrefix ip);
+
+ /**
+ * Matches a l3 IPv4 address.
+ *
+ * @param ip a l3 address
+ * @return a selection builder
+ */
+ Builder matchIPDst(IpPrefix ip);
+
+ /**
+ * Matches a TCP source port number.
+ *
+ * @param tcpPort a TCP source port number
+ * @return a selection builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder matchTcpSrc(short tcpPort);
+
+ /**
+ * Matches a TCP source port number.
+ *
+ * @param tcpPort a TCP source port number
+ * @return a selection builder
+ */
+ Builder matchTcpSrc(TpPort tcpPort);
+
+ /**
+ * Matches a TCP destination port number.
+ *
+ * @param tcpPort a TCP destination port number
+ * @return a selection builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder matchTcpDst(short tcpPort);
+
+ /**
+ * Matches a TCP destination port number.
+ *
+ * @param tcpPort a TCP destination port number
+ * @return a selection builder
+ */
+ Builder matchTcpDst(TpPort tcpPort);
+
+ /**
+ * Matches an UDP source port number.
+ *
+ * @param udpPort an UDP source port number
+ * @return a selection builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder matchUdpSrc(short udpPort);
+
+ /**
+ * Matches an UDP source port number.
+ *
+ * @param udpPort an UDP source port number
+ * @return a selection builder
+ */
+ Builder matchUdpSrc(TpPort udpPort);
+
+ /**
+ * Matches an UDP destination port number.
+ *
+ * @param udpPort an UDP destination port number
+ * @return a selection builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder matchUdpDst(short udpPort);
+
+ /**
+ * Matches an UDP destination port number.
+ *
+ * @param udpPort an UDP destination port number
+ * @return a selection builder
+ */
+ Builder matchUdpDst(TpPort udpPort);
+
+ /**
+ * Matches a SCTP source port number.
+ *
+ * @param sctpPort a SCTP source port number
+ * @return a selection builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder matchSctpSrc(short sctpPort);
+
+ /**
+ * Matches a SCTP source port number.
+ *
+ * @param sctpPort a SCTP source port number
+ * @return a selection builder
+ */
+ Builder matchSctpSrc(TpPort sctpPort);
+
+ /**
+ * Matches a SCTP destination port number.
+ *
+ * @param sctpPort a SCTP destination port number
+ * @return a selection builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder matchSctpDst(short sctpPort);
+
+ /**
+ * Matches a SCTP destination port number.
+ *
+ * @param sctpPort a SCTP destination port number
+ * @return a selection builder
+ */
+ Builder matchSctpDst(TpPort sctpPort);
+
+ /**
+ * Matches an ICMP type.
+ *
+ * @param icmpType an ICMP type
+ * @return a selection builder
+ */
+ Builder matchIcmpType(byte icmpType);
+
+ /**
+ * Matches an ICMP code.
+ *
+ * @param icmpCode an ICMP code
+ * @return a selection builder
+ */
+ Builder matchIcmpCode(byte icmpCode);
+
+ /**
+ * Matches a l3 IPv6 address.
+ *
+ * @param ip a l3 IPv6 address
+ * @return a selection builder
+ */
+ Builder matchIPv6Src(IpPrefix ip);
+
+ /**
+ * Matches a l3 IPv6 address.
+ *
+ * @param ip a l3 IPv6 address
+ * @return a selection builder
+ */
+ Builder matchIPv6Dst(IpPrefix ip);
+
+ /**
+ * Matches an IPv6 flow label.
+ *
+ * @param flowLabel an IPv6 flow label
+ * @return a selection builder
+ */
+ Builder matchIPv6FlowLabel(int flowLabel);
+
+ /**
+ * Matches an ICMPv6 type.
+ *
+ * @param icmpv6Type an ICMPv6 type
+ * @return a selection builder
+ */
+ Builder matchIcmpv6Type(byte icmpv6Type);
+
+ /**
+ * Matches an ICMPv6 code.
+ *
+ * @param icmpv6Code an ICMPv6 code
+ * @return a selection builder
+ */
+ Builder matchIcmpv6Code(byte icmpv6Code);
+
+ /**
+ * Matches an IPv6 Neighbor Discovery target address.
+ *
+ * @param targetAddress an IPv6 Neighbor Discovery target address
+ * @return a selection builder
+ */
+ Builder matchIPv6NDTargetAddress(Ip6Address targetAddress);
+
+ /**
+ * Matches an IPv6 Neighbor Discovery source link-layer address.
+ *
+ * @param mac an IPv6 Neighbor Discovery source link-layer address
+ * @return a selection builder
+ */
+ Builder matchIPv6NDSourceLinkLayerAddress(MacAddress mac);
+
+ /**
+ * Matches an IPv6 Neighbor Discovery target link-layer address.
+ *
+ * @param mac an IPv6 Neighbor Discovery target link-layer address
+ * @return a selection builder
+ */
+ Builder matchIPv6NDTargetLinkLayerAddress(MacAddress mac);
+
+ /**
+ * Matches on a MPLS label.
+ *
+ * @param mplsLabel a MPLS label.
+ * @return a selection builder
+ */
+ Builder matchMplsLabel(MplsLabel mplsLabel);
+
+ /**
+ * Matches on a MPLS Bottom-of-Stack indicator bit.
+ *
+ * @param mplsBos boolean value indicating BOS=1 (true) or BOS=0 (false).
+ * @return a selection builder
+ */
+ Builder matchMplsBos(boolean mplsBos);
+
+ /**
+ * Matches a tunnel id.
+ *
+ * @param tunnelId a tunnel id
+ * @return a selection builder
+ */
+ Builder matchTunnelId(long tunnelId);
+
+ /**
+ * Matches on IPv6 Extension Header pseudo-field flags.
+ *
+ * @param exthdrFlags the IPv6 Extension Header pseudo-field flags
+ * @return a selection builder
+ */
+ Builder matchIPv6ExthdrFlags(short exthdrFlags);
+
+ /**
+ * Matches an optical signal ID or lambda.
+ *
+ * @param lambda lambda
+ * @return a selection builder
+ * @deprecated in Cardinal Release.
+ * Use {@link #add(Criterion)} with an instance created
+ * by {@link org.onosproject.net.flow.criteria.Criteria#matchLambda(org.onosproject.net.Lambda)}.
+ */
+ @Deprecated
+ Builder matchLambda(short lambda);
+
+ /**
+ * Matches an optical Signal Type.
+ *
+ * @param signalType signalType
+ * @return a selection builder
+ * @deprecated in Cardinal Release.
+ * Use {@link #add(Criterion)}} with an instance created
+ * by {@link org.onosproject.net.flow.criteria.Criteria#matchOchSignalType(org.onosproject.net.OchSignalType)}.
+ */
+ @Deprecated
+ Builder matchOpticalSignalType(short signalType);
+
+ /**
+ * Builds an immutable traffic selector.
+ *
+ * @return traffic selector
+ */
+ TrafficSelector build();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
new file mode 100644
index 00000000..1ce669c2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onlab.packet.EthType;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.meter.MeterId;
+
+import java.util.List;
+
+/**
+ * Abstraction of network traffic treatment.
+ */
+public interface TrafficTreatment {
+
+ /**
+ * Returns the list of treatment instructions that will be applied
+ * further down the pipeline.
+ * @return list of treatment instructions
+ */
+ List<Instruction> deferred();
+
+ /**
+ * Returns the list of treatment instructions that will be applied
+ * immediately.
+ * @return list of treatment instructions
+ */
+ List<Instruction> immediate();
+
+ /**
+ * Returns the list of all instructions in the treatment, both immediate and
+ * deferred.
+ *
+ * @return list of treatment instructions
+ */
+ List<Instruction> allInstructions();
+
+ /**
+ * Returns the next table in the pipeline.
+ * @return a table transition; may be null.
+ */
+ Instructions.TableTypeTransition tableTransition();
+
+ /**
+ * Whether the deferred treatment instructions will be cleared
+ * by the device.
+ * @return a boolean
+ */
+ boolean clearedDeferred();
+
+ /**
+ * Returns the metadata instruction if there is one.
+ *
+ * @return a metadata instruction that may be null
+ */
+ Instructions.MetadataInstruction writeMetadata();
+
+ /**
+ * Returns the meter instruction if there is one.
+ *
+ * @return a meter instruction that may be null
+ */
+ Instructions.MeterInstruction metered();
+
+ /**
+ * Builder of traffic treatment entities.
+ */
+ interface Builder {
+
+ /**
+ * Adds an instruction to the builder.
+ *
+ * @param instruction an instruction
+ * @return a treatment builder
+ */
+ Builder add(Instruction instruction);
+
+ /**
+ * Adds a drop instruction.
+ *
+ * @return a treatment builder
+ */
+ Builder drop();
+
+ /**
+ * Adds a punt-to-controller instruction.
+ *
+ * @return a treatment builder
+ */
+ Builder punt();
+
+ /**
+ * Set the output port.
+ *
+ * @param number the out port
+ * @return a treatment builder
+ */
+ Builder setOutput(PortNumber number);
+
+ /**
+ * Sets the src l2 address.
+ *
+ * @param addr a macaddress
+ * @return a treatment builder
+ */
+ Builder setEthSrc(MacAddress addr);
+
+ /**
+ * Sets the dst l2 address.
+ *
+ * @param addr a macaddress
+ * @return a treatment builder
+ */
+ Builder setEthDst(MacAddress addr);
+
+ /**
+ * Sets the vlan id.
+ *
+ * @param id a vlanid
+ * @return a treatment builder
+ */
+ Builder setVlanId(VlanId id);
+
+ /**
+ * Sets the vlan priority.
+ *
+ * @param pcp a vlan priority
+ * @return a treatment builder
+ */
+ Builder setVlanPcp(Byte pcp);
+
+ /**
+ * Sets the src l3 address.
+ *
+ * @param addr an ip
+ * @return a treatment builder
+ */
+ Builder setIpSrc(IpAddress addr);
+
+ /**
+ * Sets the dst l3 address.
+ *
+ * @param addr an ip
+ * @return a treatment builder
+ */
+ Builder setIpDst(IpAddress addr);
+
+ /**
+ * Decrement the TTL in IP header by one.
+ *
+ * @return a treatment builder
+ */
+ Builder decNwTtl();
+
+ /**
+ * Copy the TTL to outer protocol layer.
+ *
+ * @return a treatment builder
+ */
+ Builder copyTtlOut();
+
+ /**
+ * Copy the TTL to inner protocol layer.
+ *
+ * @return a treatment builder
+ */
+ Builder copyTtlIn();
+
+ /**
+ * Push MPLS ether type.
+ *
+ * @return a treatment builder.
+ */
+ Builder pushMpls();
+
+ /**
+ * Pops MPLS ether type.
+ *
+ * @return a treatment builder.
+ */
+ Builder popMpls();
+
+ /**
+ * Pops MPLS ether type and set the new ethertype.
+ *
+ * @param etherType an ether type
+ * @return a treatment builder.
+ * @deprecated in Drake Release
+ */
+ @Deprecated
+ Builder popMpls(int etherType);
+
+ /**
+ * Pops MPLS ether type and set the new ethertype.
+ *
+ * @param etherType an ether type
+ * @return a treatment builder.
+ */
+ Builder popMpls(EthType etherType);
+
+ /**
+ * Sets the mpls label.
+ *
+ * @param mplsLabel MPLS label.
+ * @return a treatment builder.
+ */
+ Builder setMpls(MplsLabel mplsLabel);
+
+ /**
+ * Sets the mpls bottom-of-stack indicator bit.
+ *
+ * @param mplsBos boolean to set BOS=1 (true) or BOS=0 (false).
+ * @return a treatment builder.
+ */
+ Builder setMplsBos(boolean mplsBos);
+
+ /**
+ * Decrement MPLS TTL.
+ *
+ * @return a treatment builder
+ */
+ Builder decMplsTtl();
+
+ /**
+ * Sets the optical channel ID or lambda.
+ *
+ * @param lambda optical channel ID
+ * @return a treatment builder
+ * @deprecated in Drake Release
+ */
+ @Deprecated
+ Builder setLambda(short lambda);
+
+ /**
+ * Sets the group ID.
+ *
+ * @param groupId group ID
+ * @return a treatment builder
+ */
+ Builder group(GroupId groupId);
+
+ /**
+ * Sets a meter to be used by this flow.
+ *
+ * @param meterId a meter id
+ * @return a treatment builder
+ */
+ Builder meter(MeterId meterId);
+
+ /**
+ * Sets the next table type to transition to.
+ *
+ * @param type the table type
+ * @return a treatement builder
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ Builder transition(FlowRule.Type type);
+
+ /**
+ * Sets the next table id to transition to.
+ *
+ * @param tableId the table table
+ * @return a treatement builder
+ */
+ Builder transition(Integer tableId);
+
+
+ /**
+ * Pops outermost VLAN tag.
+ *
+ * @return a treatment builder.
+ */
+ Builder popVlan();
+
+ /**
+ * Pushes a new VLAN tag.
+ *
+ * @return a treatment builder.
+ */
+ Builder pushVlan();
+
+ /**
+ * Any instructions preceded by this method call will be deferred.
+ * @return a treatment builder
+ */
+ Builder deferred();
+
+ /**
+ * Any instructions preceded by this method call will be immediate.
+ * @return a treatment builder
+ */
+ Builder immediate();
+
+
+ /**
+ * Instructs the device to clear the deferred instructions set.
+ * @return a treatment builder
+ */
+ Builder wipeDeferred();
+
+ /**
+ * Writes metadata to associate with a packet.
+ * <pre>
+ * {@code
+ * new_metadata = (old_metadata & ̃mask) | (value & mask)
+ * }
+ * </pre>
+ *
+ * @param value the metadata to write
+ * @param mask the masked bits for the value
+ * @return a treatment builder
+ */
+ Builder writeMetadata(long value, long mask);
+
+ /**
+ * Sets the tunnel id.
+ *
+ * @param tunnelId a tunnel id.
+ * @return a treatment builder.
+ */
+ Builder setTunnelId(long tunnelId);
+
+ /**
+ * Sets the src TCP port.
+ *
+ * @param port a port number
+ * @return a treatment builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder setTcpSrc(short port);
+
+ /**
+ * Sets the src TCP port.
+ *
+ * @param port a port number
+ * @return a treatment builder
+ */
+ Builder setTcpSrc(TpPort port);
+
+ /**
+ * Sets the dst TCP port.
+ *
+ * @param port a port number
+ * @return a treatment builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder setTcpDst(short port);
+
+ /**
+ * Sets the dst TCP port.
+ *
+ * @param port a port number
+ * @return a treatment builder
+ */
+ Builder setTcpDst(TpPort port);
+
+ /**
+ * Sets the src UDP port.
+ *
+ * @param port a port number
+ * @return a treatment builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder setUdpSrc(short port);
+
+ /**
+ * Sets the src UDP port.
+ *
+ * @param port a port number
+ * @return a treatment builder
+ */
+ Builder setUdpSrc(TpPort port);
+
+ /**
+ * Sets the dst UDP port.
+ *
+ * @param port a port number
+ * @return a treatment builder
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ Builder setUdpDst(short port);
+
+ /**
+ * Sets the dst UDP port.
+ *
+ * @param port a port number
+ * @return a treatment builder
+ */
+ Builder setUdpDst(TpPort port);
+
+ /**
+ * Builds an immutable traffic treatment descriptor.
+ * <p>
+ * If the treatment is empty when build() is called, it will add a default
+ * drop rule automatically. For a treatment that is actually empty, use
+ * {@link org.onosproject.net.flow.DefaultTrafficTreatment#emptyTreatment}.
+ * </p>
+ *
+ * @return traffic treatment
+ */
+ TrafficTreatment build();
+
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java
new file mode 100644
index 00000000..a77079ce
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow;
+
+import org.onosproject.net.PortNumber;
+
+/**
+ * Abstraction of different kinds of treatment that can be applied to an
+ * outbound packet.
+ */
+public interface Treatment {
+
+ // TODO: implement these later: modifications, group
+ // TODO: elsewhere provide factory methods for some default treatments
+
+ /**
+ * Returns the port number where the packet should be emitted.
+ *
+ * @return output port number
+ */
+ PortNumber output();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
new file mode 100644
index 00000000..0252cfbc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.EthType;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.IndexedLambda;
+import org.onosproject.net.Lambda;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.criteria.Criterion.Type;
+import org.onosproject.net.OchSignalType;
+
+/**
+ * Factory class to create various traffic selection criteria.
+ */
+public final class Criteria {
+
+ //TODO: incomplete type implementation. Need to implement complete list from Criterion
+
+ // Ban construction
+ private Criteria() {
+ }
+
+ /**
+ * Creates a match on IN_PORT field using the specified value.
+ *
+ * @param port inport value
+ * @return match criterion
+ */
+ public static Criterion matchInPort(PortNumber port) {
+ return new PortCriterion(port, Type.IN_PORT);
+ }
+
+ /**
+ * Creates a match on IN_PHY_PORT field using the specified value.
+ *
+ * @param port inport value
+ * @return match criterion
+ */
+ public static Criterion matchInPhyPort(PortNumber port) {
+ return new PortCriterion(port, Type.IN_PHY_PORT);
+ }
+
+ /**
+ * Creates a match on METADATA field using the specified value.
+ *
+ * @param metadata metadata value (64 bits data)
+ * @return match criterion
+ */
+ public static Criterion matchMetadata(long metadata) {
+ return new MetadataCriterion(metadata);
+ }
+
+ /**
+ * Creates a match on ETH_DST field using the specified value. This value
+ * may be a wildcard mask.
+ *
+ * @param mac MAC address value or wildcard mask
+ * @return match criterion
+ */
+ public static Criterion matchEthDst(MacAddress mac) {
+ return new EthCriterion(mac, Type.ETH_DST);
+ }
+
+ /**
+ * Creates a match on ETH_SRC field using the specified value. This value
+ * may be a wildcard mask.
+ *
+ * @param mac MAC address value or wildcard mask
+ * @return match criterion
+ */
+ public static Criterion matchEthSrc(MacAddress mac) {
+ return new EthCriterion(mac, Type.ETH_SRC);
+ }
+
+ /**
+ * Creates a match on ETH_TYPE field using the specified value.
+ *
+ * @param ethType eth type value (16 bits unsigned integer)
+ * @return match criterion
+ */
+ public static Criterion matchEthType(int ethType) {
+ return new EthTypeCriterion(ethType);
+ }
+
+ /**
+ * Creates a match on ETH_TYPE field using the specified value.
+ *
+ * @param ethType eth type value
+ * @return match criterion
+ */
+ public static Criterion matchEthType(EthType ethType) {
+ return new EthTypeCriterion(ethType);
+ }
+
+ /**
+ * Creates a match on VLAN ID field using the specified value.
+ *
+ * @param vlanId vlan id value
+ * @return match criterion
+ */
+ public static Criterion matchVlanId(VlanId vlanId) {
+ return new VlanIdCriterion(vlanId);
+ }
+
+ /**
+ * Creates a match on VLAN PCP field using the specified value.
+ *
+ * @param vlanPcp vlan pcp value (3 bits)
+ * @return match criterion
+ */
+ public static Criterion matchVlanPcp(byte vlanPcp) {
+ return new VlanPcpCriterion(vlanPcp);
+ }
+
+ /**
+ * Creates a match on IP DSCP field using the specified value.
+ *
+ * @param ipDscp ip dscp value (6 bits)
+ * @return match criterion
+ */
+ public static Criterion matchIPDscp(byte ipDscp) {
+ return new IPDscpCriterion(ipDscp);
+ }
+
+ /**
+ * Creates a match on IP ECN field using the specified value.
+ *
+ * @param ipEcn ip ecn value (2 bits)
+ * @return match criterion
+ */
+ public static Criterion matchIPEcn(byte ipEcn) {
+ return new IPEcnCriterion(ipEcn);
+ }
+
+ /**
+ * Creates a match on IP proto field using the specified value.
+ *
+ * @param proto ip protocol value (8 bits unsigned integer)
+ * @return match criterion
+ */
+ public static Criterion matchIPProtocol(short proto) {
+ return new IPProtocolCriterion(proto);
+ }
+
+ /**
+ * Creates a match on IPv4 source field using the specified value.
+ *
+ * @param ip ipv4 source value
+ * @return match criterion
+ */
+ public static Criterion matchIPSrc(IpPrefix ip) {
+ return new IPCriterion(ip, Type.IPV4_SRC);
+ }
+
+ /**
+ * Creates a match on IPv4 destination field using the specified value.
+ *
+ * @param ip ipv4 source value
+ * @return match criterion
+ */
+ public static Criterion matchIPDst(IpPrefix ip) {
+ return new IPCriterion(ip, Type.IPV4_DST);
+ }
+
+ /**
+ * Creates a match on TCP source port field using the specified value.
+ *
+ * @param tcpPort TCP source port
+ * @return match criterion
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static Criterion matchTcpSrc(short tcpPort) {
+ return new TcpPortCriterion(TpPort.tpPort(tcpPort), Type.TCP_SRC);
+ }
+
+ /**
+ * Creates a match on TCP source port field using the specified value.
+ *
+ * @param tcpPort TCP source port
+ * @return match criterion
+ */
+ public static Criterion matchTcpSrc(TpPort tcpPort) {
+ return new TcpPortCriterion(tcpPort, Type.TCP_SRC);
+ }
+
+ /**
+ * Creates a match on TCP destination port field using the specified value.
+ *
+ * @param tcpPort TCP destination port
+ * @return match criterion
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static Criterion matchTcpDst(short tcpPort) {
+ return new TcpPortCriterion(TpPort.tpPort(tcpPort), Type.TCP_DST);
+ }
+
+ /**
+ * Creates a match on TCP destination port field using the specified value.
+ *
+ * @param tcpPort TCP destination port
+ * @return match criterion
+ */
+ public static Criterion matchTcpDst(TpPort tcpPort) {
+ return new TcpPortCriterion(tcpPort, Type.TCP_DST);
+ }
+
+ /**
+ * Creates a match on UDP source port field using the specified value.
+ *
+ * @param udpPort UDP source port
+ * @return match criterion
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static Criterion matchUdpSrc(short udpPort) {
+ return new UdpPortCriterion(TpPort.tpPort(udpPort), Type.UDP_SRC);
+ }
+
+ /**
+ * Creates a match on UDP source port field using the specified value.
+ *
+ * @param udpPort UDP source port
+ * @return match criterion
+ */
+ public static Criterion matchUdpSrc(TpPort udpPort) {
+ return new UdpPortCriterion(udpPort, Type.UDP_SRC);
+ }
+
+ /**
+ * Creates a match on UDP destination port field using the specified value.
+ *
+ * @param udpPort UDP destination port
+ * @return match criterion
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static Criterion matchUdpDst(short udpPort) {
+ return new UdpPortCriterion(TpPort.tpPort(udpPort), Type.UDP_DST);
+ }
+
+ /**
+ * Creates a match on UDP destination port field using the specified value.
+ *
+ * @param udpPort UDP destination port
+ * @return match criterion
+ */
+ public static Criterion matchUdpDst(TpPort udpPort) {
+ return new UdpPortCriterion(udpPort, Type.UDP_DST);
+ }
+
+ /**
+ * Creates a match on SCTP source port field using the specified value.
+ *
+ * @param sctpPort SCTP source port
+ * @return match criterion
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static Criterion matchSctpSrc(short sctpPort) {
+ return new SctpPortCriterion(TpPort.tpPort(sctpPort), Type.SCTP_SRC);
+ }
+
+ /**
+ * Creates a match on SCTP source port field using the specified value.
+ *
+ * @param sctpPort SCTP source port
+ * @return match criterion
+ */
+ public static Criterion matchSctpSrc(TpPort sctpPort) {
+ return new SctpPortCriterion(sctpPort, Type.SCTP_SRC);
+ }
+
+ /**
+ * Creates a match on SCTP destination port field using the specified
+ * value.
+ *
+ * @param sctpPort SCTP destination port
+ * @return match criterion
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static Criterion matchSctpDst(short sctpPort) {
+ return new SctpPortCriterion(TpPort.tpPort(sctpPort), Type.SCTP_DST);
+ }
+
+ /**
+ * Creates a match on SCTP destination port field using the specified
+ * value.
+ *
+ * @param sctpPort SCTP destination port
+ * @return match criterion
+ */
+ public static Criterion matchSctpDst(TpPort sctpPort) {
+ return new SctpPortCriterion(sctpPort, Type.SCTP_DST);
+ }
+
+ /**
+ * Creates a match on ICMP type field using the specified value.
+ *
+ * @param icmpType ICMP type (8 bits unsigned integer)
+ * @return match criterion
+ */
+ public static Criterion matchIcmpType(short icmpType) {
+ return new IcmpTypeCriterion(icmpType);
+ }
+
+ /**
+ * Creates a match on ICMP code field using the specified value.
+ *
+ * @param icmpCode ICMP code (8 bits unsigned integer)
+ * @return match criterion
+ */
+ public static Criterion matchIcmpCode(short icmpCode) {
+ return new IcmpCodeCriterion(icmpCode);
+ }
+
+ /**
+ * Creates a match on IPv6 source field using the specified value.
+ *
+ * @param ip ipv6 source value
+ * @return match criterion
+ */
+ public static Criterion matchIPv6Src(IpPrefix ip) {
+ return new IPCriterion(ip, Type.IPV6_SRC);
+ }
+
+ /**
+ * Creates a match on IPv6 destination field using the specified value.
+ *
+ * @param ip ipv6 destination value
+ * @return match criterion
+ */
+ public static Criterion matchIPv6Dst(IpPrefix ip) {
+ return new IPCriterion(ip, Type.IPV6_DST);
+ }
+
+ /**
+ * Creates a match on IPv6 flow label field using the specified value.
+ *
+ * @param flowLabel IPv6 flow label (20 bits)
+ * @return match criterion
+ */
+ public static Criterion matchIPv6FlowLabel(int flowLabel) {
+ return new IPv6FlowLabelCriterion(flowLabel);
+ }
+
+ /**
+ * Creates a match on ICMPv6 type field using the specified value.
+ *
+ * @param icmpv6Type ICMPv6 type (8 bits unsigned integer)
+ * @return match criterion
+ */
+ public static Criterion matchIcmpv6Type(short icmpv6Type) {
+ return new Icmpv6TypeCriterion(icmpv6Type);
+ }
+
+ /**
+ * Creates a match on ICMPv6 code field using the specified value.
+ *
+ * @param icmpv6Code ICMPv6 code (8 bits unsigned integer)
+ * @return match criterion
+ */
+ public static Criterion matchIcmpv6Code(short icmpv6Code) {
+ return new Icmpv6CodeCriterion(icmpv6Code);
+ }
+
+ /**
+ * Creates a match on IPv6 Neighbor Discovery target address using the
+ * specified value.
+ *
+ * @param targetAddress IPv6 Neighbor Discovery target address
+ * @return match criterion
+ */
+ public static Criterion matchIPv6NDTargetAddress(Ip6Address targetAddress) {
+ return new IPv6NDTargetAddressCriterion(targetAddress);
+ }
+
+ /**
+ * Creates a match on IPv6 Neighbor Discovery source link-layer address
+ * using the specified value.
+ *
+ * @param mac IPv6 Neighbor Discovery source link-layer address
+ * @return match criterion
+ */
+ public static Criterion matchIPv6NDSourceLinkLayerAddress(MacAddress mac) {
+ return new IPv6NDLinkLayerAddressCriterion(mac, Type.IPV6_ND_SLL);
+ }
+
+ /**
+ * Creates a match on IPv6 Neighbor Discovery target link-layer address
+ * using the specified value.
+ *
+ * @param mac IPv6 Neighbor Discovery target link-layer address
+ * @return match criterion
+ */
+ public static Criterion matchIPv6NDTargetLinkLayerAddress(MacAddress mac) {
+ return new IPv6NDLinkLayerAddressCriterion(mac, Type.IPV6_ND_TLL);
+ }
+
+ /**
+ * Creates a match on MPLS label.
+ *
+ * @param mplsLabel MPLS label (20 bits)
+ * @return match criterion
+ */
+ public static Criterion matchMplsLabel(MplsLabel mplsLabel) {
+ return new MplsCriterion(mplsLabel);
+ }
+
+ /**
+ * Creates a match on MPLS Bottom-of-Stack indicator bit.
+ *
+ * @param mplsBos boolean value indicating true (BOS=1) or false (BOS=0)
+ * @return match criterion
+ */
+ public static Criterion matchMplsLabel(boolean mplsBos) {
+ return new MplsBosCriterion(mplsBos);
+ }
+
+ /**
+ * Creates a match on Tunnel ID.
+ *
+ * @param tunnelId Tunnel ID (64 bits)
+ * @return match criterion
+ */
+ public static Criterion matchTunnelId(long tunnelId) {
+ return new TunnelIdCriterion(tunnelId);
+ }
+
+ /**
+ * Creates a match on IPv6 Extension Header pseudo-field fiags.
+ * Those are defined in Criterion.IPv6ExthdrFlags.
+ *
+ * @param exthdrFlags IPv6 Extension Header pseudo-field flags (16 bits)
+ * @return match criterion
+ */
+ public static Criterion matchIPv6ExthdrFlags(int exthdrFlags) {
+ return new IPv6ExthdrFlagsCriterion(exthdrFlags);
+ }
+
+ /**
+ * Creates a match on lambda field using the specified value.
+ *
+ * @param lambda lambda to match on (16 bits unsigned integer)
+ * @return match criterion
+ * @deprecated in Cardinal Release. Use {@link #matchLambda(Lambda)} instead.
+ */
+ @Deprecated
+ public static Criterion matchLambda(int lambda) {
+ return new LambdaCriterion(lambda, Type.OCH_SIGID);
+ }
+
+ /**
+ * Creates a match on lambda using the specified value.
+ *
+ * @param lambda lambda
+ * @return match criterion
+ */
+ public static Criterion matchLambda(Lambda lambda) {
+ if (lambda instanceof IndexedLambda) {
+ return new IndexedLambdaCriterion((IndexedLambda) lambda);
+ } else if (lambda instanceof OchSignal) {
+ return new OchSignalCriterion((OchSignal) lambda);
+ } else {
+ throw new UnsupportedOperationException(String.format("Unsupported type of Lambda: %s", lambda));
+ }
+ }
+
+ /**
+ * Creates a match on optical signal type using the specified value.
+ *
+ * @param sigType optical signal type (8 bits unsigned integer)
+ * @return match criterion
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ public static Criterion matchOpticalSignalType(short sigType) {
+ return new OpticalSignalTypeCriterion(sigType, Type.OCH_SIGTYPE);
+ }
+
+ /**
+ * Create a match on OCh (Optical Channel) signal type.
+ *
+ * @param signalType OCh signal type
+ * @return match criterion
+ */
+ public static Criterion matchOchSignalType(OchSignalType signalType) {
+ return new OchSignalTypeCriterion(signalType);
+ }
+
+ public static Criterion dummy() {
+ return new DummyCriterion();
+ }
+
+ /**
+ * Dummy Criterion used with @see{FilteringObjective}.
+ */
+ private static class DummyCriterion implements Criterion {
+
+ @Override
+ public Type type() {
+ return Type.DUMMY;
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java
new file mode 100644
index 00000000..12ab57de
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+
+/**
+ * Representation of a single header field selection.
+ */
+public interface Criterion {
+
+ /**
+ * Types of fields to which the selection criterion may apply.
+ */
+ // From page 75 of OpenFlow 1.5.0 spec
+ enum Type {
+ /** Switch input port. */
+ IN_PORT,
+ /** Switch physical input port. */
+ IN_PHY_PORT,
+ /** Metadata passed between tables. */
+ METADATA,
+ /** Ethernet destination address. */
+ ETH_DST,
+ /** Ethernet source address. */
+ ETH_SRC,
+ /** Ethernet frame type. */
+ ETH_TYPE,
+ /** VLAN id. */
+ VLAN_VID,
+ /** VLAN priority. */
+ VLAN_PCP,
+ /** IP DSCP (6 bits in ToS field). */
+ IP_DSCP,
+ /** IP ECN (2 bits in ToS field). */
+ IP_ECN,
+ /** IP protocol. */
+ IP_PROTO,
+ /** IPv4 source address. */
+ IPV4_SRC,
+ /** IPv4 destination address. */
+ IPV4_DST,
+ /** TCP source port. */
+ TCP_SRC,
+ /** TCP destination port. */
+ TCP_DST,
+ /** UDP source port. */
+ UDP_SRC,
+ /** UDP destination port. */
+ UDP_DST,
+ /** SCTP source port. */
+ SCTP_SRC,
+ /** SCTP destination port. */
+ SCTP_DST,
+ /** ICMP type. */
+ ICMPV4_TYPE,
+ /** ICMP code. */
+ ICMPV4_CODE,
+ /** ARP opcode. */
+ ARP_OP,
+ /** ARP source IPv4 address. */
+ ARP_SPA,
+ /** ARP target IPv4 address. */
+ ARP_TPA,
+ /** ARP source hardware address. */
+ ARP_SHA,
+ /** ARP target hardware address. */
+ ARP_THA,
+ /** IPv6 source address. */
+ IPV6_SRC,
+ /** IPv6 destination address. */
+ IPV6_DST,
+ /** IPv6 Flow Label. */
+ IPV6_FLABEL,
+ /** ICMPv6 type. */
+ ICMPV6_TYPE,
+ /** ICMPv6 code. */
+ ICMPV6_CODE,
+ /** Target address for ND. */
+ IPV6_ND_TARGET,
+ /** Source link-layer for ND. */
+ IPV6_ND_SLL,
+ /** Target link-layer for ND. */
+ IPV6_ND_TLL,
+ /** MPLS label. */
+ MPLS_LABEL,
+ /** MPLS TC. */
+ MPLS_TC,
+ /** MPLS BoS bit. */
+ MPLS_BOS,
+ /** PBB I-SID. */
+ PBB_ISID,
+ /** Logical Port Metadata. */
+ TUNNEL_ID,
+ /** IPv6 Extension Header pseudo-field. */
+ IPV6_EXTHDR,
+ /** Unassigned value: 40. */
+ UNASSIGNED_40,
+ /** PBB UCA header field. */
+ PBB_UCA,
+ /** TCP flags. */
+ TCP_FLAGS,
+ /** Output port from action set metadata. */
+ ACTSET_OUTPUT,
+ /** Packet type value. */
+ PACKET_TYPE,
+
+ //
+ // NOTE: Everything below is defined elsewhere: ONOS-specific,
+ // extensions, etc.
+ //
+ /** Optical channel signal ID (lambda). */
+ OCH_SIGID,
+ /** Optical channel signal type (fixed or flexible). */
+ OCH_SIGTYPE,
+
+ /**
+ * An empty criterion.
+ */
+ DUMMY
+ }
+
+ /**
+ * Returns the type of criterion.
+ *
+ * @return type of criterion
+ */
+ Type type();
+
+ /**
+ * Bit definitions for IPv6 Extension Header pseudo-field.
+ * From page 79 of OpenFlow 1.5.0 spec.
+ */
+ enum IPv6ExthdrFlags {
+ /** "No next header" encountered. */
+ NONEXT((short) (1 << 0)),
+ /** Encrypted Sec Payload header present. */
+ ESP((short) (1 << 1)),
+ /** Authentication header present. */
+ AUTH((short) (1 << 2)),
+ /** 1 or 2 dest headers present. */
+ DEST((short) (1 << 3)),
+ /** Fragment header present. */
+ FRAG((short) (1 << 4)),
+ /** Router header present. */
+ ROUTER((short) (1 << 5)),
+ /** Hop-by-hop header present. */
+ HOP((short) (1 << 6)),
+ /** Unexpected repeats encountered. */
+ UNREP((short) (1 << 7)),
+ /** Unexpected sequencing encountered. */
+ UNSEQ((short) (1 << 8));
+
+ private short value;
+
+ IPv6ExthdrFlags(short value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value as an integer.
+ *
+ * @return the value as an integer
+ */
+ public short getValue() {
+ return this.value;
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/EthCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/EthCriterion.java
new file mode 100644
index 00000000..6020974d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/EthCriterion.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.MacAddress;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of MAC address criterion.
+ */
+public final class EthCriterion implements Criterion {
+ private final MacAddress mac;
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param mac the source or destination MAC address to match
+ * @param type the match type. Should be either Type.ETH_DST or
+ * Type.ETH_SRC
+ */
+ EthCriterion(MacAddress mac, Type type) {
+ this.mac = mac;
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the MAC address to match.
+ *
+ * @return the MAC address to match
+ */
+ public MacAddress mac() {
+ return this.mac;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("mac", mac).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type.ordinal(), mac);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof EthCriterion) {
+ EthCriterion that = (EthCriterion) obj;
+ return Objects.equals(mac, that.mac) &&
+ Objects.equals(type, that.type);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/EthTypeCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/EthTypeCriterion.java
new file mode 100644
index 00000000..b2666d4d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/EthTypeCriterion.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.EthType;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of Ethernet type criterion (16 bits unsigned integer).
+ */
+public final class EthTypeCriterion implements Criterion {
+
+
+ private final EthType ethType;
+
+ /**
+ * Constructor.
+ *
+ * @param ethType the Ethernet frame type to match (16 bits unsigned
+ * integer)
+ */
+ EthTypeCriterion(int ethType) {
+ this.ethType = new EthType(ethType);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param ethType the Ethernet frame type to match
+ */
+ EthTypeCriterion(EthType ethType) {
+ this.ethType = ethType;
+ }
+
+ @Override
+ public Type type() {
+ return Type.ETH_TYPE;
+ }
+
+ /**
+ * Gets the Ethernet frame type to match.
+ *
+ * @return the Ethernet frame type to match (16 bits unsigned integer)
+ */
+ public EthType ethType() {
+ return ethType;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("ethType", ethType.toString())
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), ethType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof EthTypeCriterion) {
+ EthTypeCriterion that = (EthTypeCriterion) obj;
+ return Objects.equals(ethType, that.ethType) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPCriterion.java
new file mode 100644
index 00000000..018afe80
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPCriterion.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.IpPrefix;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of IP address criterion.
+ */
+public final class IPCriterion implements Criterion {
+ private final IpPrefix ip;
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param ip the IP prefix to match. Could be either IPv4 or IPv6
+ * @param type the match type. Should be one of the following:
+ * Type.IPV4_SRC, Type.IPV4_DST, Type.IPV6_SRC, Type.IPV6_DST
+ */
+ IPCriterion(IpPrefix ip, Type type) {
+ this.ip = ip;
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the IP prefix to match.
+ *
+ * @return the IP prefix to match
+ */
+ public IpPrefix ip() {
+ return this.ip;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("ip", ip).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), ip);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IPCriterion) {
+ IPCriterion that = (IPCriterion) obj;
+ return Objects.equals(ip, that.ip) &&
+ Objects.equals(type, that.type);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPDscpCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPDscpCriterion.java
new file mode 100644
index 00000000..8634aa66
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPDscpCriterion.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of IP DSCP (Differentiated Services Code Point)
+ * criterion (6 bits).
+ */
+public final class IPDscpCriterion implements Criterion {
+ private static final byte MASK = 0x3f;
+ private final byte ipDscp; // IP DSCP value: 6 bits
+
+ /**
+ * Constructor.
+ *
+ * @param ipDscp the IP DSCP value to match
+ */
+ IPDscpCriterion(byte ipDscp) {
+ this.ipDscp = (byte) (ipDscp & MASK);
+ }
+
+ @Override
+ public Type type() {
+ return Type.IP_DSCP;
+ }
+
+ /**
+ * Gets the IP DSCP value to match.
+ *
+ * @return the IP DSCP value to match
+ */
+ public byte ipDscp() {
+ return ipDscp;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("ipDscp", Long.toHexString(ipDscp)).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), ipDscp);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IPDscpCriterion) {
+ IPDscpCriterion that = (IPDscpCriterion) obj;
+ return Objects.equals(ipDscp, that.ipDscp) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPEcnCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPEcnCriterion.java
new file mode 100644
index 00000000..48b3fbf6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPEcnCriterion.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of IP ECN (Explicit Congestion Notification) criterion
+ * (2 bits).
+ */
+public final class IPEcnCriterion implements Criterion {
+ private static final byte MASK = 0x3;
+ private final byte ipEcn; // IP ECN value: 2 bits
+
+ /**
+ * Constructor.
+ *
+ * @param ipEcn the IP ECN value to match (2 bits)
+ */
+ IPEcnCriterion(byte ipEcn) {
+ this.ipEcn = (byte) (ipEcn & MASK);
+ }
+
+ @Override
+ public Type type() {
+ return Type.IP_ECN;
+ }
+
+ /**
+ * Gets the IP ECN value to match.
+ *
+ * @return the IP ECN value to match (2 bits)
+ */
+ public byte ipEcn() {
+ return ipEcn;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("ipEcn", Long.toHexString(ipEcn)).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), ipEcn);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IPEcnCriterion) {
+ IPEcnCriterion that = (IPEcnCriterion) obj;
+ return Objects.equals(ipEcn, that.ipEcn) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPProtocolCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPProtocolCriterion.java
new file mode 100644
index 00000000..6879f802
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPProtocolCriterion.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of Internet Protocol Number criterion (8 bits unsigned)
+ * integer.
+ */
+public final class IPProtocolCriterion implements Criterion {
+ private static final short MASK = 0xff;
+ private final short proto; // IP protocol number: 8 bits
+
+ /**
+ * Constructor.
+ *
+ * @param protocol the IP protocol (e.g., TCP=6, UDP=17) to match
+ * (8 bits unsigned integer)
+ */
+ IPProtocolCriterion(short protocol) {
+ this.proto = (short) (protocol & MASK);
+ }
+
+ @Override
+ public Type type() {
+ return Type.IP_PROTO;
+ }
+
+ /**
+ * Gets the IP protocol to match.
+ *
+ * @return the IP protocol to match (8 bits unsigned integer)
+ */
+ public short protocol() {
+ return proto;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("protocol", proto).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), proto);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IPProtocolCriterion) {
+ IPProtocolCriterion that = (IPProtocolCriterion) obj;
+ return Objects.equals(proto, that.proto);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6ExthdrFlagsCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6ExthdrFlagsCriterion.java
new file mode 100644
index 00000000..2463bf64
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6ExthdrFlagsCriterion.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of IPv6 Extension Header pseudo-field criterion
+ * (16 bits). Those are defined in Criterion.IPv6ExthdrFlags.
+ */
+public final class IPv6ExthdrFlagsCriterion implements Criterion {
+ private static final int MASK = 0xffff;
+ private final int exthdrFlags; // IPv6 Exthdr flags: 16 bits
+
+ /**
+ * Constructor.
+ *
+ * @param exthdrFlags the IPv6 Extension Header pseudo-field flags
+ * to match (16 bits). Those are defined in Criterion.IPv6ExthdrFlags
+ */
+ IPv6ExthdrFlagsCriterion(int exthdrFlags) {
+ this.exthdrFlags = exthdrFlags & MASK;
+ }
+
+ @Override
+ public Type type() {
+ return Type.IPV6_EXTHDR;
+ }
+
+ /**
+ * Gets the IPv6 Extension Header pseudo-field flags to match.
+ *
+ * @return the IPv6 Extension Header pseudo-field flags to match
+ * (16 bits). Those are defined in Criterion.IPv6ExthdrFlags
+ */
+ public int exthdrFlags() {
+ return exthdrFlags;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("exthdrFlags", Long.toHexString(exthdrFlags)).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), exthdrFlags);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IPv6ExthdrFlagsCriterion) {
+ IPv6ExthdrFlagsCriterion that = (IPv6ExthdrFlagsCriterion) obj;
+ return Objects.equals(exthdrFlags, that.exthdrFlags) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6FlowLabelCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6FlowLabelCriterion.java
new file mode 100644
index 00000000..6e1021d9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6FlowLabelCriterion.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of IPv6 Flow Label (RFC 6437) criterion (20 bits unsigned
+ * integer).
+ */
+public final class IPv6FlowLabelCriterion implements Criterion {
+ private static final int MASK = 0xfffff;
+ private final int flowLabel; // IPv6 flow label: 20 bits
+
+ /**
+ * Constructor.
+ *
+ * @param flowLabel the IPv6 flow label to match (20 bits)
+ */
+ IPv6FlowLabelCriterion(int flowLabel) {
+ this.flowLabel = flowLabel & MASK;
+ }
+
+ @Override
+ public Type type() {
+ return Type.IPV6_FLABEL;
+ }
+
+ /**
+ * Gets the IPv6 flow label to match.
+ *
+ * @return the IPv6 flow label to match (20 bits)
+ */
+ public int flowLabel() {
+ return flowLabel;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("flowLabel", Long.toHexString(flowLabel)).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), flowLabel);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IPv6FlowLabelCriterion) {
+ IPv6FlowLabelCriterion that = (IPv6FlowLabelCriterion) obj;
+ return Objects.equals(flowLabel, that.flowLabel) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6NDLinkLayerAddressCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6NDLinkLayerAddressCriterion.java
new file mode 100644
index 00000000..9f310d4a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6NDLinkLayerAddressCriterion.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.MacAddress;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of IPv6 Neighbor Discovery link-layer address criterion.
+ */
+public final class IPv6NDLinkLayerAddressCriterion implements Criterion {
+ private final MacAddress mac;
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param mac the source or destination link-layer address to match
+ * @param type the match type. Should be either Type.IPV6_ND_SLL or
+ * Type.IPV6_ND_TLL
+ */
+ IPv6NDLinkLayerAddressCriterion(MacAddress mac, Type type) {
+ this.mac = mac;
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the MAC link-layer address to match.
+ *
+ * @return the MAC link-layer address to match
+ */
+ public MacAddress mac() {
+ return this.mac;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("mac", mac).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), mac);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IPv6NDLinkLayerAddressCriterion) {
+ IPv6NDLinkLayerAddressCriterion that =
+ (IPv6NDLinkLayerAddressCriterion) obj;
+ return Objects.equals(mac, that.mac) &&
+ Objects.equals(type, that.type);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6NDTargetAddressCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6NDTargetAddressCriterion.java
new file mode 100644
index 00000000..ffef044a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IPv6NDTargetAddressCriterion.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.Ip6Address;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of IPv6 Neighbor Discovery target address criterion.
+ */
+public final class IPv6NDTargetAddressCriterion implements Criterion {
+ private final Ip6Address targetAddress;
+
+ /**
+ * Constructor.
+ *
+ * @param targetAddress the IPv6 target address to match
+ */
+ IPv6NDTargetAddressCriterion(Ip6Address targetAddress) {
+ this.targetAddress = targetAddress;
+ }
+
+ @Override
+ public Type type() {
+ return Type.IPV6_ND_TARGET;
+ }
+
+ /**
+ * Gets the IPv6 target address to match.
+ *
+ * @return the IPv6 target address to match
+ */
+ public Ip6Address targetAddress() {
+ return this.targetAddress;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("targetAddress", targetAddress).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), targetAddress);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IPv6NDTargetAddressCriterion) {
+ IPv6NDTargetAddressCriterion that =
+ (IPv6NDTargetAddressCriterion) obj;
+ return Objects.equals(targetAddress, that.targetAddress) &&
+ Objects.equals(type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IcmpCodeCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IcmpCodeCriterion.java
new file mode 100644
index 00000000..516f61b3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IcmpCodeCriterion.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of ICMP code criterion (8 bits unsigned integer).
+ */
+public final class IcmpCodeCriterion implements Criterion {
+ private static final short MASK = 0xff;
+ private final short icmpCode; // The ICMP code: 8 bits
+
+ /**
+ * Constructor.
+ *
+ * @param icmpCode the ICMP code to match (8 bits unsigned integer)
+ */
+ IcmpCodeCriterion(short icmpCode) {
+ this.icmpCode = (short) (icmpCode & MASK);
+ }
+
+ @Override
+ public Type type() {
+ return Type.ICMPV4_CODE;
+ }
+
+ /**
+ * Gets the ICMP code to match.
+ *
+ * @return the ICMP code to match (8 bits unsigned integer)
+ */
+ public short icmpCode() {
+ return icmpCode;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("icmpCode", icmpCode).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), icmpCode);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IcmpCodeCriterion) {
+ IcmpCodeCriterion that = (IcmpCodeCriterion) obj;
+ return Objects.equals(icmpCode, that.icmpCode) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IcmpTypeCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IcmpTypeCriterion.java
new file mode 100644
index 00000000..63251425
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IcmpTypeCriterion.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of ICMP type criterion (8 bits unsigned integer).
+ */
+public final class IcmpTypeCriterion implements Criterion {
+ private static final short MASK = 0xff;
+ private final short icmpType; // The ICMP type: 8 bits
+
+ /**
+ * Constructor.
+ *
+ * @param icmpType the ICMP type to match (8 bits unsigned integer)
+ */
+ IcmpTypeCriterion(short icmpType) {
+ this.icmpType = (short) (icmpType & MASK);
+ }
+
+ @Override
+ public Type type() {
+ return Type.ICMPV4_TYPE;
+ }
+
+ /**
+ * Gets the ICMP type to match.
+ *
+ * @return the ICMP type to match (8 bits unsigned integer)
+ */
+ public short icmpType() {
+ return icmpType;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("icmpType", icmpType).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), icmpType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof IcmpTypeCriterion) {
+ IcmpTypeCriterion that = (IcmpTypeCriterion) obj;
+ return Objects.equals(icmpType, that.icmpType) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Icmpv6CodeCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Icmpv6CodeCriterion.java
new file mode 100644
index 00000000..a41b6fef
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Icmpv6CodeCriterion.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of ICMPv6 code criterion (8 bits unsigned integer).
+ */
+public final class Icmpv6CodeCriterion implements Criterion {
+ private static final short MASK = 0xff;
+ private final short icmpv6Code; // ICMPv6 code: 8 bits
+
+ /**
+ * Constructor.
+ *
+ * @param icmpv6Code the ICMPv6 code to match (8 bits unsigned integer)
+ */
+ Icmpv6CodeCriterion(short icmpv6Code) {
+ this.icmpv6Code = (short) (icmpv6Code & MASK);
+ }
+
+ @Override
+ public Type type() {
+ return Type.ICMPV6_CODE;
+ }
+
+ /**
+ * Gets the ICMPv6 code to match.
+ *
+ * @return the ICMPv6 code to match (8 bits unsigned integer)
+ */
+ public short icmpv6Code() {
+ return icmpv6Code;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("icmpv6Code", icmpv6Code).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), icmpv6Code);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Icmpv6CodeCriterion) {
+ Icmpv6CodeCriterion that = (Icmpv6CodeCriterion) obj;
+ return Objects.equals(icmpv6Code, that.icmpv6Code) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Icmpv6TypeCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Icmpv6TypeCriterion.java
new file mode 100644
index 00000000..7410ba17
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Icmpv6TypeCriterion.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of ICMPv6 type criterion (8 bits unsigned integer).
+ */
+public final class Icmpv6TypeCriterion implements Criterion {
+ private static final short MASK = 0xff;
+ private final short icmpv6Type; // ICMPv6 type: 8 bits
+
+ /**
+ * Constructor.
+ *
+ * @param icmpv6Type the ICMPv6 type to match (8 bits unsigned integer)
+ */
+ Icmpv6TypeCriterion(short icmpv6Type) {
+ this.icmpv6Type = (short) (icmpv6Type & MASK);
+ }
+
+ @Override
+ public Type type() {
+ return Type.ICMPV6_TYPE;
+ }
+
+ /**
+ * Gets the ICMPv6 type to match.
+ *
+ * @return the ICMPv6 type to match (8 bits unsigned integer)
+ */
+ public short icmpv6Type() {
+ return icmpv6Type;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("icmpv6Type", icmpv6Type).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), icmpv6Type);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Icmpv6TypeCriterion) {
+ Icmpv6TypeCriterion that = (Icmpv6TypeCriterion) obj;
+ return Objects.equals(icmpv6Type, that.icmpv6Type) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IndexedLambdaCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IndexedLambdaCriterion.java
new file mode 100644
index 00000000..88a6fe10
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/IndexedLambdaCriterion.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.IndexedLambda;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Implementation of indexed lambda criterion.
+ */
+public class IndexedLambdaCriterion implements Criterion {
+
+ private final IndexedLambda lambda;
+
+ /**
+ * Creates a criterion with the specified value.
+ *
+ * @param lambda lambda index number
+ */
+ IndexedLambdaCriterion(IndexedLambda lambda) {
+ this.lambda = checkNotNull(lambda);
+ }
+
+ @Override
+ public Type type() {
+ // TODO: consider defining a new specific type
+ // Now OCH_SIGID is used due to compatibility concerns
+ return Type.OCH_SIGID;
+ }
+
+ /**
+ * Returns the indexed lambda to match.
+ *
+ * @return the indexed lambda to match
+ */
+ public IndexedLambda lambda() {
+ return lambda;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), lambda);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof IndexedLambdaCriterion)) {
+ return false;
+ }
+ final IndexedLambdaCriterion that = (IndexedLambdaCriterion) obj;
+ return Objects.equals(this.lambda, that.lambda);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("lambda", lambda)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/LambdaCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/LambdaCriterion.java
new file mode 100644
index 00000000..656800b1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/LambdaCriterion.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of lambda (wavelength) criterion (16 bits unsigned
+ * integer).
+ */
+public final class LambdaCriterion implements Criterion {
+ private static final int MASK = 0xffff;
+ private final int lambda; // Lambda value: 16 bits
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param lambda the lambda (wavelength) to match (16 bits unsigned
+ * integer)
+ * @param type the match type. Should be Type.OCH_SIGID
+ */
+ LambdaCriterion(int lambda, Type type) {
+ this.lambda = lambda & MASK;
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the lambda (wavelength) to match.
+ *
+ * @return the lambda (wavelength) to match (16 bits unsigned integer)
+ */
+ public int lambda() {
+ return lambda;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("lambda", lambda).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), lambda);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof LambdaCriterion) {
+ LambdaCriterion that = (LambdaCriterion) obj;
+ return Objects.equals(lambda, that.lambda) &&
+ Objects.equals(type, that.type);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MetadataCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MetadataCriterion.java
new file mode 100644
index 00000000..8177b483
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MetadataCriterion.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of Metadata criterion.
+ */
+public final class MetadataCriterion implements Criterion {
+ private final long metadata;
+
+ /**
+ * Constructor.
+ *
+ * @param metadata the metadata to match (64 bits data)
+ */
+ MetadataCriterion(long metadata) {
+ this.metadata = metadata;
+ }
+
+ @Override
+ public Type type() {
+ return Type.METADATA;
+ }
+
+ /**
+ * Gets the metadata to match.
+ *
+ * @return the metadata to match (64 bits data)
+ */
+ public long metadata() {
+ return metadata;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("metadata", Long.toHexString(metadata))
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), metadata);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof MetadataCriterion) {
+ MetadataCriterion that = (MetadataCriterion) obj;
+ return Objects.equals(metadata, that.metadata) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MplsBosCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MplsBosCriterion.java
new file mode 100644
index 00000000..1ace8931
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MplsBosCriterion.java
@@ -0,0 +1,48 @@
+package org.onosproject.net.flow.criteria;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import java.util.Objects;
+
+/**
+ * Implementation of MPLS BOS criterion (1 bit).
+ */
+public class MplsBosCriterion implements Criterion {
+ private boolean mplsBos;
+
+ MplsBosCriterion(boolean mplsBos) {
+ this.mplsBos = mplsBos;
+ }
+
+ @Override
+ public Type type() {
+ return Type.MPLS_BOS;
+ }
+
+ public boolean mplsBos() {
+ return mplsBos;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("bos", mplsBos).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), mplsBos);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof MplsBosCriterion) {
+ MplsBosCriterion that = (MplsBosCriterion) obj;
+ return Objects.equals(mplsBos, that.mplsBos()) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MplsCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MplsCriterion.java
new file mode 100644
index 00000000..34d384f1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/MplsCriterion.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.MplsLabel;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of MPLS tag criterion (20 bits).
+ */
+public final class MplsCriterion implements Criterion {
+ private static final int MASK = 0xfffff;
+ private final MplsLabel mplsLabel;
+
+ MplsCriterion(MplsLabel mplsLabel) {
+ this.mplsLabel = mplsLabel;
+ }
+
+ @Override
+ public Type type() {
+ return Type.MPLS_LABEL;
+ }
+
+ public MplsLabel label() {
+ return mplsLabel;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("mpls", mplsLabel).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), mplsLabel);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof MplsCriterion) {
+ MplsCriterion that = (MplsCriterion) obj;
+ return Objects.equals(mplsLabel, that.mplsLabel) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OchSignalCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OchSignalCriterion.java
new file mode 100644
index 00000000..3a51a6bd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OchSignalCriterion.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.OchSignal;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Implementation of OCh (Optical Channel) signal criterion.
+ * This criterion is based on the specification of "OFPXMT_EXP_OCH_SIGID" in
+ * Open Networking Foundation "Optical Transport Protocol Extension Version 1.0", but
+ * defined in protocol agnostic way.
+ */
+public final class OchSignalCriterion implements Criterion {
+
+ private final OchSignal lambda;
+
+ /**
+ * Create an instance with the specified OCh signal.
+ *
+ * @param lambda OCh signal
+ */
+ OchSignalCriterion(OchSignal lambda) {
+ this.lambda = checkNotNull(lambda);
+ }
+
+ @Override
+ public Type type() {
+ return Type.OCH_SIGID;
+ }
+
+ /**
+ * Returns the OCh signal to match.
+ *
+ * @return the OCh signal to match
+ */
+ public OchSignal lambda() {
+ return lambda;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), lambda);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof OchSignalCriterion)) {
+ return false;
+ }
+ final OchSignalCriterion that = (OchSignalCriterion) obj;
+ return Objects.equals(this.lambda, that.lambda);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("lambda", lambda)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OchSignalTypeCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OchSignalTypeCriterion.java
new file mode 100644
index 00000000..cf838bf3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OchSignalTypeCriterion.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.OchSignalType;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Implementation of OCh (Optical Channel) signal type criterion.
+ */
+public class OchSignalTypeCriterion implements Criterion {
+
+ private final OchSignalType signalType;
+
+ /**
+ * Creates a criterion with the specified value.
+ *
+ * @param signalType OCh signal type
+ */
+ OchSignalTypeCriterion(OchSignalType signalType) {
+ this.signalType = checkNotNull(signalType);
+ }
+
+ @Override
+ public Type type() {
+ return Type.OCH_SIGTYPE;
+ }
+
+ /**
+ * Returns the OCh signal type to match.
+ *
+ * @return the OCh signal type to match
+ */
+ public OchSignalType signalType() {
+ return signalType;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), signalType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof OchSignalTypeCriterion)) {
+ return false;
+ }
+ final OchSignalTypeCriterion that = (OchSignalTypeCriterion) obj;
+ return Objects.equals(this.signalType, that.signalType);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("signalType", signalType)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OpticalSignalTypeCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OpticalSignalTypeCriterion.java
new file mode 100644
index 00000000..b712675b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/OpticalSignalTypeCriterion.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of optical signal type criterion (8 bits unsigned
+ * integer).
+ *
+ * @deprecated in Cardinal Release
+ */
+@Deprecated
+public final class OpticalSignalTypeCriterion implements Criterion {
+ private static final short MASK = 0xff;
+ private final short signalType; // Signal type value: 8 bits
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param signalType the optical signal type to match (8 bits unsigned
+ * integer)
+ * @param type the match type. Should be Type.OCH_SIGTYPE
+ */
+ OpticalSignalTypeCriterion(short signalType, Type type) {
+ this.signalType = (short) (signalType & MASK);
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the optical signal type to match.
+ *
+ * @return the optical signal type to match (8 bits unsigned integer)
+ */
+ public short signalType() {
+ return signalType;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("signalType", signalType).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), signalType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof OpticalSignalTypeCriterion) {
+ OpticalSignalTypeCriterion that = (OpticalSignalTypeCriterion) obj;
+ return Objects.equals(signalType, that.signalType) &&
+ Objects.equals(type, that.type);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/PortCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/PortCriterion.java
new file mode 100644
index 00000000..f07cd500
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/PortCriterion.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onosproject.net.PortNumber;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of input port criterion.
+ */
+public final class PortCriterion implements Criterion {
+ private final PortNumber port;
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param port the input port number to match
+ * @param type the match type. Should be either Type.IN_PORT or
+ * Type.IN_PHY_PORT
+ */
+ PortCriterion(PortNumber port, Type type) {
+ this.port = port;
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the input port number to match.
+ *
+ * @return the input port number to match
+ */
+ public PortNumber port() {
+ return this.port;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("port", port).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), port);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof PortCriterion) {
+ PortCriterion that = (PortCriterion) obj;
+ return Objects.equals(port, that.port) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/SctpPortCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/SctpPortCriterion.java
new file mode 100644
index 00000000..2d4cf15a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/SctpPortCriterion.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.TpPort;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of SCTP port criterion (16 bits unsigned integer).
+ */
+public final class SctpPortCriterion implements Criterion {
+ private final TpPort sctpPort;
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param sctpPort the SCTP port to match
+ * @param type the match type. Should be either Type.SCTP_SRC or
+ * Type.SCTP_DST
+ */
+ SctpPortCriterion(TpPort sctpPort, Type type) {
+ this.sctpPort = sctpPort;
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the SCTP port to match.
+ *
+ * @return the SCTP port to match
+ */
+ public TpPort sctpPort() {
+ return this.sctpPort;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("sctpPort", sctpPort).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), sctpPort);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof SctpPortCriterion) {
+ SctpPortCriterion that = (SctpPortCriterion) obj;
+ return Objects.equals(sctpPort, that.sctpPort) &&
+ Objects.equals(type, that.type);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/TcpPortCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/TcpPortCriterion.java
new file mode 100644
index 00000000..e682b238
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/TcpPortCriterion.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.TpPort;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of TCP port criterion (16 bits unsigned integer).
+ */
+public final class TcpPortCriterion implements Criterion {
+ private final TpPort tcpPort;
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param tcpPort the TCP port to match
+ * @param type the match type. Should be either Type.TCP_SRC or
+ * Type.TCP_DST
+ */
+ TcpPortCriterion(TpPort tcpPort, Type type) {
+ this.tcpPort = tcpPort;
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the TCP port to match.
+ *
+ * @return the TCP port to match
+ */
+ public TpPort tcpPort() {
+ return this.tcpPort;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("tcpPort", tcpPort).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), tcpPort);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof TcpPortCriterion) {
+ TcpPortCriterion that = (TcpPortCriterion) obj;
+ return Objects.equals(tcpPort, that.tcpPort) &&
+ Objects.equals(type, that.type);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/TunnelIdCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/TunnelIdCriterion.java
new file mode 100644
index 00000000..3362c73f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/TunnelIdCriterion.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+/**
+ * Implementation of Tunnel ID criterion.
+ */
+public class TunnelIdCriterion implements Criterion {
+ private final long tunnelId;
+
+ /**
+ * Constructor.
+ *
+ * @param tunnelId a Tunnel ID to match(64 bits)
+ */
+ TunnelIdCriterion(long tunnelId) {
+ this.tunnelId = tunnelId;
+ }
+
+ @Override
+ public Type type() {
+ return Type.TUNNEL_ID;
+ }
+
+ /**
+ * Gets the Tunnel ID to match.
+ *
+ * @return the Tunnel ID to match (64 bits)
+ */
+ public long tunnelId() {
+ return tunnelId;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("tunnelId", Long.toHexString(tunnelId))
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), tunnelId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof TunnelIdCriterion) {
+ TunnelIdCriterion that = (TunnelIdCriterion) obj;
+ return Objects.equals(tunnelId, that.tunnelId) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/UdpPortCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/UdpPortCriterion.java
new file mode 100644
index 00000000..8a29f471
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/UdpPortCriterion.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.TpPort;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of UDP port criterion (16 bits unsigned integer).
+ */
+public final class UdpPortCriterion implements Criterion {
+ private final TpPort udpPort;
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param udpPort the UDP port to match
+ * @param type the match type. Should be either Type.UDP_SRC or
+ * Type.UDP_DST
+ */
+ UdpPortCriterion(TpPort udpPort, Type type) {
+ this.udpPort = udpPort;
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the UDP port to match.
+ *
+ * @return the UDP port to match
+ */
+ public TpPort udpPort() {
+ return this.udpPort;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("udpPort", udpPort).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), udpPort);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof UdpPortCriterion) {
+ UdpPortCriterion that = (UdpPortCriterion) obj;
+ return Objects.equals(udpPort, that.udpPort) &&
+ Objects.equals(type, that.type);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/VlanIdCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/VlanIdCriterion.java
new file mode 100644
index 00000000..c73edb12
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/VlanIdCriterion.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import org.onlab.packet.VlanId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of VLAN ID criterion.
+ */
+public final class VlanIdCriterion implements Criterion {
+ private final VlanId vlanId;
+
+ /**
+ * Constructor.
+ *
+ * @param vlanId the VLAN ID to match
+ */
+ VlanIdCriterion(VlanId vlanId) {
+ this.vlanId = vlanId;
+ }
+
+ @Override
+ public Type type() {
+ return Type.VLAN_VID;
+ }
+
+ /**
+ * Gets the VLAN ID to match.
+ *
+ * @return the VLAN ID to match
+ */
+ public VlanId vlanId() {
+ return vlanId;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("vlanId", vlanId).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), vlanId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof VlanIdCriterion) {
+ VlanIdCriterion that = (VlanIdCriterion) obj;
+ return Objects.equals(vlanId, that.vlanId) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/VlanPcpCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/VlanPcpCriterion.java
new file mode 100644
index 00000000..0c83e141
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/VlanPcpCriterion.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.criteria;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of VLAN priority criterion (3 bits).
+ */
+public final class VlanPcpCriterion implements Criterion {
+ private static final byte MASK = 0x7;
+ private final byte vlanPcp; // VLAN pcp value: 3 bits
+
+ /**
+ * Constructor.
+ *
+ * @param vlanPcp the VLAN priority to match (3 bits)
+ */
+ VlanPcpCriterion(byte vlanPcp) {
+ this.vlanPcp = (byte) (vlanPcp & MASK);
+ }
+
+ @Override
+ public Type type() {
+ return Type.VLAN_PCP;
+ }
+
+ /**
+ * Gets the VLAN priority to match.
+ *
+ * @return the VLAN priority to match (3 bits)
+ */
+ public byte priority() {
+ return vlanPcp;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("priority", Long.toHexString(vlanPcp)).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), vlanPcp);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof VlanPcpCriterion) {
+ VlanPcpCriterion that = (VlanPcpCriterion) obj;
+ return Objects.equals(vlanPcp, that.vlanPcp) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/package-info.java
new file mode 100644
index 00000000..1f091928
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Traffic selection criteria model.
+ */
+package org.onosproject.net.flow.criteria;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
new file mode 100644
index 00000000..6f2cac6b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.instructions;
+
+/**
+ * Abstraction of a single traffic treatment step.
+ */
+public interface Instruction {
+
+ /**
+ * Represents the type of traffic treatment.
+ */
+ enum Type {
+ /**
+ * Signifies that the traffic should be dropped.
+ */
+ DROP,
+
+ /**
+ * Signifies that the traffic should be output to a port.
+ */
+ OUTPUT,
+
+ /**
+ * Signifies that traffic should be sent out of a group.
+ */
+ GROUP,
+
+ /**
+ * Signifies that traffic should be metered according to a meter.
+ */
+ METER,
+
+ /**
+ * Signifies that the traffic should be modified in L0 way.
+ */
+ L0MODIFICATION,
+
+ /**
+ * Signifies that the traffic should be modified in L2 way.
+ */
+ L2MODIFICATION,
+
+ /**
+ * Signifies that the traffic should be passed to another table.
+ */
+ TABLE,
+
+ /**
+ * Signifies that the traffic should be modified in L3 way.
+ */
+ L3MODIFICATION,
+
+ /**
+ * Signifies that metadata be attached to traffic.
+ */
+ METADATA,
+
+ /**
+ * Signifies that the traffic should be modified in L4 way.
+ */
+ L4MODIFICATION
+ }
+
+ /**
+ * Returns the type of instruction.
+ * @return type of instruction
+ */
+ Type type();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
new file mode 100644
index 00000000..c5358a29
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
@@ -0,0 +1,742 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.instructions;
+
+import org.onlab.packet.EthType;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.IndexedLambda;
+import org.onosproject.net.Lambda;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.L0SubType;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModTtlInstruction;
+import org.onosproject.net.flow.instructions.L4ModificationInstruction.L4SubType;
+import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
+import org.onosproject.net.meter.MeterId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Factory class for creating various traffic treatment instructions.
+ */
+public final class Instructions {
+
+
+ // Ban construction
+ private Instructions() {}
+
+ /**
+ * Creates an output instruction using the specified port number. This can
+ * include logical ports such as CONTROLLER, FLOOD, etc.
+ *
+ * @param number port number
+ * @return output instruction
+ */
+ public static OutputInstruction createOutput(final PortNumber number) {
+ checkNotNull(number, "PortNumber cannot be null");
+ return new OutputInstruction(number);
+ }
+
+ /**
+ * Creates a drop instruction.
+ *
+ * @return drop instruction
+ */
+ public static DropInstruction createDrop() {
+ return new DropInstruction();
+ }
+
+ /**
+ * Creates a group instruction.
+ *
+ * @param groupId Group Id
+ * @return group instruction
+ */
+ public static GroupInstruction createGroup(final GroupId groupId) {
+ checkNotNull(groupId, "GroupId cannot be null");
+ return new GroupInstruction(groupId);
+ }
+
+ public static MeterInstruction meterTraffic(final MeterId meterId) {
+ checkNotNull(meterId, "meter id cannot be null");
+ return new MeterInstruction(meterId);
+ }
+
+ /**
+ * Creates a l0 modification.
+ *
+ * @param lambda the lambda to modify to
+ * @return a l0 modification
+ * @deprecated in Cardinal Release. Use {@link #modL0Lambda(Lambda)} instead.
+ */
+ @Deprecated
+ public static L0ModificationInstruction modL0Lambda(short lambda) {
+ checkNotNull(lambda, "L0 lambda cannot be null");
+ return new ModLambdaInstruction(L0SubType.LAMBDA, lambda);
+ }
+
+ /**
+ * Creates an L0 modification with the specified OCh signal.
+ *
+ * @param lambda OCh signal
+ * @return an L0 modification
+ */
+ public static L0ModificationInstruction modL0Lambda(Lambda lambda) {
+ checkNotNull(lambda, "L0 OCh signal cannot be null");
+
+ if (lambda instanceof IndexedLambda) {
+ return new ModLambdaInstruction(L0SubType.LAMBDA, (short) ((IndexedLambda) lambda).index());
+ } else if (lambda instanceof OchSignal) {
+ return new ModOchSignalInstruction((OchSignal) lambda);
+ } else {
+ throw new UnsupportedOperationException(String.format("Unsupported type: %s", lambda));
+ }
+ }
+
+ /**
+ * Creates a l2 src modification.
+ *
+ * @param addr the mac address to modify to
+ * @return a l2 modification
+ */
+ public static L2ModificationInstruction modL2Src(MacAddress addr) {
+ checkNotNull(addr, "Src l2 address cannot be null");
+ return new L2ModificationInstruction.ModEtherInstruction(
+ L2ModificationInstruction.L2SubType.ETH_SRC, addr);
+ }
+
+ /**
+ * Creates a L2 dst modification.
+ *
+ * @param addr the mac address to modify to
+ * @return a L2 modification
+ */
+ public static L2ModificationInstruction modL2Dst(MacAddress addr) {
+ checkNotNull(addr, "Dst l2 address cannot be null");
+ return new L2ModificationInstruction.ModEtherInstruction(
+ L2ModificationInstruction.L2SubType.ETH_DST, addr);
+ }
+
+ /**
+ * Creates a VLAN ID modification.
+ *
+ * @param vlanId the VLAN ID to modify to
+ * @return a L2 modification
+ */
+ public static L2ModificationInstruction modVlanId(VlanId vlanId) {
+ checkNotNull(vlanId, "VLAN id cannot be null");
+ return new L2ModificationInstruction.ModVlanIdInstruction(vlanId);
+ }
+
+ /**
+ * Creates a VLAN PCP modification.
+ *
+ * @param vlanPcp the PCP to modify to
+ * @return a L2 modification
+ */
+ public static L2ModificationInstruction modVlanPcp(Byte vlanPcp) {
+ checkNotNull(vlanPcp, "VLAN Pcp cannot be null");
+ return new L2ModificationInstruction.ModVlanPcpInstruction(vlanPcp);
+ }
+
+ /**
+ * Creates a MPLS label modification.
+ *
+ * @param mplsLabel MPLS label to set
+ * @return a L2 Modification
+ */
+ public static L2ModificationInstruction modMplsLabel(MplsLabel mplsLabel) {
+ checkNotNull(mplsLabel, "MPLS label cannot be null");
+ return new L2ModificationInstruction.ModMplsLabelInstruction(mplsLabel);
+ }
+
+ /**
+ * Creates a MPLS BOS bit modification.
+ *
+ * @param mplsBos MPLS BOS bit to set (true) or unset (false)
+ * @return a L2 Modification
+ */
+ public static L2ModificationInstruction modMplsBos(boolean mplsBos) {
+ return new L2ModificationInstruction.ModMplsBosInstruction(mplsBos);
+ }
+
+ /**
+ * Creates a MPLS decrement TTL modification.
+ *
+ * @return a L2 Modification
+ */
+ public static L2ModificationInstruction decMplsTtl() {
+ return new L2ModificationInstruction.ModMplsTtlInstruction();
+ }
+
+ /**
+ * Creates a L3 IPv4 src modification.
+ *
+ * @param addr the IPv4 address to modify to
+ * @return a L3 modification
+ */
+ public static L3ModificationInstruction modL3Src(IpAddress addr) {
+ checkNotNull(addr, "Src l3 IPv4 address cannot be null");
+ return new ModIPInstruction(L3SubType.IPV4_SRC, addr);
+ }
+
+ /**
+ * Creates a L3 IPv4 dst modification.
+ *
+ * @param addr the IPv4 address to modify to
+ * @return a L3 modification
+ */
+ public static L3ModificationInstruction modL3Dst(IpAddress addr) {
+ checkNotNull(addr, "Dst l3 IPv4 address cannot be null");
+ return new ModIPInstruction(L3SubType.IPV4_DST, addr);
+ }
+
+ /**
+ * Creates a L3 IPv6 src modification.
+ *
+ * @param addr the IPv6 address to modify to
+ * @return a L3 modification
+ */
+ public static L3ModificationInstruction modL3IPv6Src(IpAddress addr) {
+ checkNotNull(addr, "Src l3 IPv6 address cannot be null");
+ return new ModIPInstruction(L3SubType.IPV6_SRC, addr);
+ }
+
+ /**
+ * Creates a L3 IPv6 dst modification.
+ *
+ * @param addr the IPv6 address to modify to
+ * @return a L3 modification
+ */
+ public static L3ModificationInstruction modL3IPv6Dst(IpAddress addr) {
+ checkNotNull(addr, "Dst l3 IPv6 address cannot be null");
+ return new ModIPInstruction(L3SubType.IPV6_DST, addr);
+ }
+
+ /**
+ * Creates a L3 IPv6 Flow Label modification.
+ *
+ * @param flowLabel the IPv6 flow label to modify to (20 bits)
+ * @return a L3 modification
+ */
+ public static L3ModificationInstruction modL3IPv6FlowLabel(int flowLabel) {
+ return new ModIPv6FlowLabelInstruction(flowLabel);
+ }
+
+ /**
+ * Creates a L3 decrement TTL modification.
+ *
+ * @return a L3 modification
+ */
+ public static L3ModificationInstruction decNwTtl() {
+ return new ModTtlInstruction(L3SubType.DEC_TTL);
+ }
+
+ /**
+ * Creates a L3 copy TTL to outer header modification.
+ *
+ * @return a L3 modification
+ */
+ public static L3ModificationInstruction copyTtlOut() {
+ return new ModTtlInstruction(L3SubType.TTL_OUT);
+ }
+
+ /**
+ * Creates a L3 copy TTL to inner header modification.
+ *
+ * @return a L3 modification
+ */
+ public static L3ModificationInstruction copyTtlIn() {
+ return new ModTtlInstruction(L3SubType.TTL_IN);
+ }
+
+ /**
+ * Creates a push MPLS header instruction.
+ *
+ * @return a L2 modification.
+ */
+ public static Instruction pushMpls() {
+ return new L2ModificationInstruction.PushHeaderInstructions(
+ L2ModificationInstruction.L2SubType.MPLS_PUSH,
+ EthType.EtherType.MPLS_UNICAST.ethType());
+ }
+
+ /**
+ * Creates a pop MPLS header instruction.
+ *
+ * @return a L2 modification.
+ */
+ public static Instruction popMpls() {
+ return new L2ModificationInstruction.PushHeaderInstructions(
+ L2ModificationInstruction.L2SubType.MPLS_POP,
+ EthType.EtherType.MPLS_UNICAST.ethType());
+ }
+
+ /**
+ * Creates a pop MPLS header instruction with a particular ethertype.
+ *
+ * @param etherType Ethernet type to set
+ * @return a L2 modification.
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ public static Instruction popMpls(int etherType) {
+ checkNotNull(etherType, "Ethernet type cannot be null");
+ return new L2ModificationInstruction.PushHeaderInstructions(
+ L2ModificationInstruction.L2SubType.MPLS_POP, new EthType(etherType));
+ }
+
+
+ /**
+ * Creates a pop MPLS header instruction with a particular ethertype.
+ *
+ * @param etherType Ethernet type to set
+ * @return a L2 modification.
+ */
+ public static Instruction popMpls(EthType etherType) {
+ checkNotNull(etherType, "Ethernet type cannot be null");
+ return new L2ModificationInstruction.PushHeaderInstructions(
+ L2ModificationInstruction.L2SubType.MPLS_POP, etherType);
+ }
+
+ /**
+ * Creates a pop VLAN header instruction.
+ *
+ * @return a L2 modification
+ */
+ public static Instruction popVlan() {
+ return new L2ModificationInstruction.PopVlanInstruction(
+ L2ModificationInstruction.L2SubType.VLAN_POP);
+ }
+
+ /**
+ * Creates a push VLAN header instruction.
+ *
+ * @return a L2 modification
+ */
+ public static Instruction pushVlan() {
+ return new L2ModificationInstruction.PushHeaderInstructions(
+ L2ModificationInstruction.L2SubType.VLAN_PUSH,
+ EthType.EtherType.VLAN.ethType());
+ }
+
+ /**
+ * Sends the packet to the table id.
+ *
+ * @param tableId flow rule table id
+ * @return table type transition instruction
+ */
+ public static Instruction transition(Integer tableId) {
+ checkNotNull(tableId, "Table id cannot be null");
+ return new TableTypeTransition(tableId);
+ }
+
+ /**
+ * Writes metadata to associate with a packet.
+ *
+ * @param metadata the metadata value to write
+ * @param metadataMask the bits to mask for the metadata value
+ * @return metadata instruction
+ */
+ public static Instruction writeMetadata(long metadata, long metadataMask) {
+ return new MetadataInstruction(metadata, metadataMask);
+ }
+
+ /**
+ * Creates a Tunnel ID modification.
+ *
+ * @param tunnelId the Tunnel ID to modify to
+ * @return a L2 modification
+ */
+ public static L2ModificationInstruction modTunnelId(long tunnelId) {
+ checkNotNull(tunnelId, "Tunnel id cannot be null");
+ return new L2ModificationInstruction.ModTunnelIdInstruction(tunnelId);
+ }
+
+ /**
+ * Creates a TCP src modification.
+ *
+ * @param port the TCP port number to modify to
+ * @return a L4 modification
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static L4ModificationInstruction modTcpSrc(short port) {
+ checkNotNull(port, "Src TCP port cannot be null");
+ return new ModTransportPortInstruction(L4SubType.TCP_SRC, TpPort.tpPort(port));
+ }
+
+ /**
+ * Creates a TCP src modification.
+ *
+ * @param port the TCP port number to modify to
+ * @return a L4 modification
+ */
+ public static L4ModificationInstruction modTcpSrc(TpPort port) {
+ checkNotNull(port, "Src TCP port cannot be null");
+ return new ModTransportPortInstruction(L4SubType.TCP_SRC, port);
+ }
+
+ /**
+ * Creates a TCP dst modification.
+ *
+ * @param port the TCP port number to modify to
+ * @return a L4 modification
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static L4ModificationInstruction modTcpDst(short port) {
+ checkNotNull(port, "Dst TCP port cannot be null");
+ return new ModTransportPortInstruction(L4SubType.TCP_DST, TpPort.tpPort(port));
+ }
+
+ /**
+ * Creates a TCP dst modification.
+ *
+ * @param port the TCP port number to modify to
+ * @return a L4 modification
+ */
+ public static L4ModificationInstruction modTcpDst(TpPort port) {
+ checkNotNull(port, "Dst TCP port cannot be null");
+ return new ModTransportPortInstruction(L4SubType.TCP_DST, port);
+ }
+
+ /**
+ * Creates a UDP src modification.
+ *
+ * @param port the UDP port number to modify to
+ * @return a L4 modification
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static L4ModificationInstruction modUdpSrc(short port) {
+ checkNotNull(port, "Src UDP port cannot be null");
+ return new ModTransportPortInstruction(L4SubType.UDP_SRC, TpPort.tpPort(port));
+ }
+
+ /**
+ * Creates a UDP src modification.
+ *
+ * @param port the UDP port number to modify to
+ * @return a L4 modification
+ */
+ public static L4ModificationInstruction modUdpSrc(TpPort port) {
+ checkNotNull(port, "Src UDP port cannot be null");
+ return new ModTransportPortInstruction(L4SubType.UDP_SRC, port);
+ }
+
+ /**
+ * Creates a UDP dst modification.
+ *
+ * @param port the UDP port number to modify to
+ * @return a L4 modification
+ * @deprecated in Drake release
+ */
+ @Deprecated
+ public static L4ModificationInstruction modUdpDst(short port) {
+ checkNotNull(port, "Dst UDP port cannot be null");
+ return new ModTransportPortInstruction(L4SubType.UDP_DST, TpPort.tpPort(port));
+ }
+
+ /**
+ * Creates a UDP dst modification.
+ *
+ * @param port the UDP port number to modify to
+ * @return a L4 modification
+ */
+ public static L4ModificationInstruction modUdpDst(TpPort port) {
+ checkNotNull(port, "Dst UDP port cannot be null");
+ return new ModTransportPortInstruction(L4SubType.UDP_DST, port);
+ }
+
+ /**
+ * Drop instruction.
+ */
+ public static final class DropInstruction implements Instruction {
+
+ private DropInstruction() {}
+
+ @Override
+ public Type type() {
+ return Type.DROP;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString()).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DropInstruction) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Output Instruction.
+ */
+ public static final class OutputInstruction implements Instruction {
+ private final PortNumber port;
+
+ private OutputInstruction(PortNumber port) {
+ this.port = port;
+ }
+
+ public PortNumber port() {
+ return port;
+ }
+
+ @Override
+ public Type type() {
+ return Type.OUTPUT;
+ }
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("port", port).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), port);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof OutputInstruction) {
+ OutputInstruction that = (OutputInstruction) obj;
+ return Objects.equals(port, that.port);
+
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Group Instruction.
+ */
+ public static final class GroupInstruction implements Instruction {
+ private final GroupId groupId;
+
+ private GroupInstruction(GroupId groupId) {
+ this.groupId = groupId;
+ }
+
+ public GroupId groupId() {
+ return groupId;
+ }
+
+ @Override
+ public Type type() {
+ return Type.GROUP;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("group ID", groupId.id()).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), groupId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof GroupInstruction) {
+ GroupInstruction that = (GroupInstruction) obj;
+ return Objects.equals(groupId, that.groupId);
+
+ }
+ return false;
+ }
+ }
+
+ /**
+ * A meter instruction.
+ */
+ public static final class MeterInstruction implements Instruction {
+ private final MeterId meterId;
+
+ private MeterInstruction(MeterId meterId) {
+ this.meterId = meterId;
+ }
+
+ public MeterId meterId() {
+ return meterId;
+ }
+
+ @Override
+ public Type type() {
+ return Type.METER;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("meter ID", meterId.id()).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), meterId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof MeterInstruction) {
+ MeterInstruction that = (MeterInstruction) obj;
+ return Objects.equals(meterId, that.meterId);
+
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Transition instruction.
+ */
+ public static class TableTypeTransition implements Instruction {
+ private final Integer tableId;
+
+ TableTypeTransition(Integer tableId) {
+ this.tableId = tableId;
+ }
+
+ @Override
+ public Type type() {
+ return Type.TABLE;
+ }
+
+ public Integer tableId() {
+ return this.tableId;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("tableId", this.tableId).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), tableId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof TableTypeTransition) {
+ TableTypeTransition that = (TableTypeTransition) obj;
+ return Objects.equals(tableId, that.tableId);
+
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Metadata instruction.
+ */
+ public static class MetadataInstruction implements Instruction {
+ private final long metadata;
+ private final long metadataMask;
+
+ MetadataInstruction(long metadata, long metadataMask) {
+ this.metadata = metadata;
+ this.metadataMask = metadataMask;
+ }
+
+ @Override
+ public Type type() {
+ return Type.METADATA;
+ }
+
+ public long metadata() {
+ return this.metadata;
+ }
+
+ public long metadataMask() {
+ return this.metadataMask;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("metadata", Long.toHexString(this.metadata))
+ .add("metadata mask", Long.toHexString(this.metadataMask))
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), metadata, metadataMask);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof MetadataInstruction) {
+ MetadataInstruction that = (MetadataInstruction) obj;
+ return Objects.equals(metadata, that.metadata) &&
+ Objects.equals(metadataMask, that.metadataMask);
+
+ }
+ return false;
+ }
+ }
+
+}
+
+
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L0ModificationInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L0ModificationInstruction.java
new file mode 100644
index 00000000..a6e5903c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L0ModificationInstruction.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.instructions;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.OchSignal;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import java.util.Objects;
+
+public abstract class L0ModificationInstruction implements Instruction {
+
+ /**
+ * Represents the type of traffic treatment.
+ */
+ public enum L0SubType {
+ /**
+ * Lambda modification.
+ */
+ LAMBDA,
+ /**
+ * OCh (Optical Channel) modification.
+ */
+ OCH,
+ }
+
+ public abstract L0SubType subtype();
+
+ @Override
+ public final Type type() {
+ return Type.L0MODIFICATION;
+ }
+
+ /**
+ * Represents a L0 lambda modification instruction.
+ */
+ public static final class ModLambdaInstruction extends L0ModificationInstruction {
+
+ private final L0SubType subtype;
+ private final short lambda;
+
+ ModLambdaInstruction(L0SubType subType, short lambda) {
+ this.subtype = subType;
+ this.lambda = lambda;
+ }
+
+ @Override
+ public L0SubType subtype() {
+ return this.subtype;
+ }
+
+ public short lambda() {
+ return this.lambda;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("lambda", lambda).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype, lambda);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModLambdaInstruction) {
+ ModLambdaInstruction that = (ModLambdaInstruction) obj;
+ return Objects.equals(lambda, that.lambda) &&
+ Objects.equals(subtype, that.subtype);
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents an L0 OCh (Optical Channel) modification instruction.
+ */
+ public static final class ModOchSignalInstruction extends L0ModificationInstruction {
+
+ private final OchSignal lambda;
+
+ ModOchSignalInstruction(OchSignal lambda) {
+ this.lambda = lambda;
+ }
+
+ @Override
+ public L0SubType subtype() {
+ return L0SubType.OCH;
+ }
+
+ public OchSignal lambda() {
+ return lambda;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(lambda);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof ModOchSignalInstruction)) {
+ return false;
+ }
+ final ModOchSignalInstruction that = (ModOchSignalInstruction) obj;
+ return Objects.equals(this.lambda, that.lambda);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("lambda", lambda)
+ .toString();
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java
new file mode 100644
index 00000000..0dbbb451
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L2ModificationInstruction.java
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.instructions;
+
+import org.onlab.packet.EthType;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.VlanId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Abstraction of a single traffic treatment step.
+ */
+public abstract class L2ModificationInstruction implements Instruction {
+
+ /**
+ * Represents the type of traffic treatment.
+ */
+ public enum L2SubType {
+ /**
+ * Ether src modification.
+ */
+ ETH_SRC,
+
+ /**
+ * Ether dst modification.
+ */
+ ETH_DST,
+
+ /**
+ * VLAN id modification.
+ */
+ VLAN_ID,
+
+ /**
+ * VLAN priority modification.
+ */
+ VLAN_PCP,
+
+ /**
+ * MPLS Label modification.
+ */
+ MPLS_LABEL,
+
+ /**
+ * MPLS Push modification.
+ */
+ MPLS_PUSH,
+
+ /**
+ * MPLS Pop modification.
+ */
+ MPLS_POP,
+
+ /**
+ * MPLS TTL modification.
+ */
+ DEC_MPLS_TTL,
+
+ /**
+ * VLAN Pop modification.
+ */
+ VLAN_POP,
+
+ /**
+ * VLAN Push modification.
+ */
+ VLAN_PUSH,
+
+ /**
+ * Tunnel id modification.
+ */
+ TUNNEL_ID,
+
+ /**
+ * MPLS BOS instruction.
+ */
+ MPLS_BOS
+ }
+
+ // TODO: Create factory class 'Instructions' that will have various factory
+ // to create specific instructions.
+
+ public abstract L2SubType subtype();
+
+ @Override
+ public final Type type() {
+ return Type.L2MODIFICATION;
+ }
+
+ /**
+ * Represents a L2 src/dst modification instruction.
+ */
+ public static final class ModEtherInstruction extends L2ModificationInstruction {
+
+ private final L2SubType subtype;
+ private final MacAddress mac;
+
+ ModEtherInstruction(L2SubType subType, MacAddress addr) {
+
+ this.subtype = subType;
+ this.mac = addr;
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return this.subtype;
+ }
+
+ public MacAddress mac() {
+ return this.mac;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("mac", mac).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype, mac);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModEtherInstruction) {
+ ModEtherInstruction that = (ModEtherInstruction) obj;
+ return Objects.equals(mac, that.mac) &&
+ Objects.equals(subtype, that.subtype);
+ }
+ return false;
+ }
+ }
+
+ // TODO This instruction is reused for Pop-Mpls. Consider renaming.
+ public static final class PushHeaderInstructions extends
+ L2ModificationInstruction {
+
+
+ private final L2SubType subtype;
+ private final EthType ethernetType; // Ethernet type value: 16 bits
+
+ PushHeaderInstructions(L2SubType subType, EthType ethernetType) {
+ this.subtype = subType;
+ this.ethernetType = ethernetType;
+ }
+
+ public EthType ethernetType() {
+ return ethernetType;
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return this.subtype;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("ethernetType", ethernetType())
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype, ethernetType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof PushHeaderInstructions) {
+ PushHeaderInstructions that = (PushHeaderInstructions) obj;
+ return Objects.equals(subtype, that.subtype) &&
+ Objects.equals(this.ethernetType, that.ethernetType);
+ }
+ return false;
+ }
+ }
+
+
+
+ /**
+ * Represents a VLAN id modification instruction.
+ */
+ public static final class ModVlanIdInstruction extends L2ModificationInstruction {
+
+ private final VlanId vlanId;
+
+ ModVlanIdInstruction(VlanId vlanId) {
+ this.vlanId = vlanId;
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return L2SubType.VLAN_ID;
+ }
+
+ public VlanId vlanId() {
+ return this.vlanId;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("id", vlanId).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype(), vlanId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModVlanIdInstruction) {
+ ModVlanIdInstruction that = (ModVlanIdInstruction) obj;
+ return Objects.equals(vlanId, that.vlanId);
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a VLAN PCP modification instruction.
+ */
+ public static final class ModVlanPcpInstruction extends L2ModificationInstruction {
+
+ private static final byte MASK = 0x7;
+ private final byte vlanPcp;
+
+ ModVlanPcpInstruction(byte vlanPcp) {
+ this.vlanPcp = (byte) (vlanPcp & MASK);
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return L2SubType.VLAN_PCP;
+ }
+
+ public byte vlanPcp() {
+ return this.vlanPcp;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("pcp", Long.toHexString(vlanPcp)).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype(), vlanPcp);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModVlanPcpInstruction) {
+ ModVlanPcpInstruction that = (ModVlanPcpInstruction) obj;
+ return Objects.equals(vlanPcp, that.vlanPcp);
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a VLAN POP modification instruction.
+ */
+ public static final class PopVlanInstruction extends L2ModificationInstruction {
+ private final L2SubType subtype;
+
+ PopVlanInstruction(L2SubType subType) {
+ this.subtype = subType;
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return subtype;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof PopVlanInstruction) {
+ PopVlanInstruction that = (PopVlanInstruction) obj;
+ return Objects.equals(subtype, that.subtype);
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a MPLS label modification.
+ */
+ public static final class ModMplsLabelInstruction
+ extends L2ModificationInstruction {
+
+ private final MplsLabel mplsLabel;
+
+ ModMplsLabelInstruction(MplsLabel mplsLabel) {
+ this.mplsLabel = mplsLabel;
+ }
+
+ /**
+ * @deprecated in Drake Release.
+ * @return integer value of label
+ */
+ // Consider changing return value to MplsLabel
+ // after deprecation process so that it'll be symmetric to
+ // MplsCriterion#label()
+ @Deprecated
+ public Integer label() {
+ return mplsLabel.toInt();
+ }
+
+ public MplsLabel mplsLabel() {
+ return mplsLabel;
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return L2SubType.MPLS_LABEL;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("mpls", mplsLabel).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype(), mplsLabel);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModMplsLabelInstruction) {
+ ModMplsLabelInstruction that = (ModMplsLabelInstruction) obj;
+ return Objects.equals(mplsLabel, that.mplsLabel);
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a MPLS BOS modification.
+ */
+ public static final class ModMplsBosInstruction
+ extends L2ModificationInstruction {
+
+ private final boolean mplsBos;
+
+ ModMplsBosInstruction(boolean mplsBos) {
+ this.mplsBos = mplsBos;
+ }
+
+ public boolean mplsBos() {
+ return mplsBos;
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return L2SubType.MPLS_BOS;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString()).add("bos", mplsBos)
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype(), mplsBos);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModMplsBosInstruction) {
+ ModMplsBosInstruction that = (ModMplsBosInstruction) obj;
+ return Objects.equals(mplsBos, that.mplsBos());
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a MPLS TTL modification.
+ */
+ public static final class ModMplsTtlInstruction
+ extends L2ModificationInstruction {
+
+ ModMplsTtlInstruction() {
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return L2SubType.DEC_MPLS_TTL;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModMplsTtlInstruction) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a Tunnel id modification.
+ */
+ public static final class ModTunnelIdInstruction
+ extends L2ModificationInstruction {
+
+ private final long tunnelId;
+
+ ModTunnelIdInstruction(long tunnelId) {
+ this.tunnelId = tunnelId;
+ }
+
+ public long tunnelId() {
+ return this.tunnelId;
+ }
+
+ @Override
+ public L2SubType subtype() {
+ return L2SubType.TUNNEL_ID;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("id", Long.toHexString(tunnelId))
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype(), tunnelId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModTunnelIdInstruction) {
+ ModTunnelIdInstruction that = (ModTunnelIdInstruction) obj;
+ return Objects.equals(tunnelId, that.tunnelId);
+ }
+ return false;
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java
new file mode 100644
index 00000000..41819504
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L3ModificationInstruction.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.instructions;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import java.util.Objects;
+
+import org.onlab.packet.IpAddress;
+
+/**
+ * Abstraction of a single traffic treatment step.
+ */
+public abstract class L3ModificationInstruction implements Instruction {
+
+ /**
+ * Represents the type of traffic treatment.
+ */
+ public enum L3SubType {
+ /**
+ * IPv4 src modification.
+ */
+ IPV4_SRC,
+
+ /**
+ * IPv4 dst modification.
+ */
+ IPV4_DST,
+
+ /**
+ * IPv6 src modification.
+ */
+ IPV6_SRC,
+
+ /**
+ * IPv6 dst modification.
+ */
+ IPV6_DST,
+
+ /**
+ * IPv6 flow label modification.
+ */
+ IPV6_FLABEL,
+
+ /**
+ * Decrement TTL.
+ */
+ DEC_TTL,
+
+ /**
+ * Copy TTL out.
+ */
+ TTL_OUT,
+
+ /**
+ * Copy TTL in.
+ */
+ TTL_IN
+
+ //TODO: remaining types
+ }
+
+ /**
+ * Returns the subtype of the modification instruction.
+ * @return type of instruction
+ */
+ public abstract L3SubType subtype();
+
+ @Override
+ public final Type type() {
+ return Type.L3MODIFICATION;
+ }
+
+ /**
+ * Represents a L3 src/dst modification instruction.
+ */
+ public static final class ModIPInstruction extends L3ModificationInstruction {
+
+ private final L3SubType subtype;
+ private final IpAddress ip;
+
+ ModIPInstruction(L3SubType subType, IpAddress addr) {
+
+ this.subtype = subType;
+ this.ip = addr;
+ }
+
+ @Override
+ public L3SubType subtype() {
+ return this.subtype;
+ }
+
+ public IpAddress ip() {
+ return this.ip;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("ip", ip).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype(), ip);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModIPInstruction) {
+ ModIPInstruction that = (ModIPInstruction) obj;
+ return Objects.equals(ip, that.ip) &&
+ Objects.equals(this.subtype(), that.subtype());
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a L3 IPv6 Flow Label (RFC 6437) modification instruction
+ * (20 bits unsigned integer).
+ */
+ public static final class ModIPv6FlowLabelInstruction
+ extends L3ModificationInstruction {
+ private static final int MASK = 0xfffff;
+ private final int flowLabel; // IPv6 flow label: 20 bits
+
+ /**
+ * Creates a new flow mod instruction.
+ *
+ * @param flowLabel the IPv6 flow label to set in the treatment (20 bits)
+ */
+ ModIPv6FlowLabelInstruction(int flowLabel) {
+ this.flowLabel = flowLabel & MASK;
+ }
+
+ @Override
+ public L3SubType subtype() {
+ return L3SubType.IPV6_FLABEL;
+ }
+
+ /**
+ * Gets the IPv6 flow label to set in the treatment.
+ *
+ * @return the IPv6 flow label to set in the treatment (20 bits)
+ */
+ public int flowLabel() {
+ return this.flowLabel;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("flowLabel", Long.toHexString(flowLabel)).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype(), flowLabel);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModIPv6FlowLabelInstruction) {
+ ModIPv6FlowLabelInstruction that =
+ (ModIPv6FlowLabelInstruction) obj;
+ return Objects.equals(flowLabel, that.flowLabel);
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Represents a L3 TTL modification instruction.
+ */
+ public static final class ModTtlInstruction extends L3ModificationInstruction {
+
+ private final L3SubType subtype;
+
+ ModTtlInstruction(L3SubType subtype) {
+ this.subtype = subtype;
+ }
+
+ @Override
+ public L3SubType subtype() {
+ return this.subtype;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModTtlInstruction) {
+ ModTtlInstruction that = (ModTtlInstruction) obj;
+ return Objects.equals(this.subtype(), that.subtype());
+ }
+ return false;
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L4ModificationInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L4ModificationInstruction.java
new file mode 100644
index 00000000..441a2c5f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L4ModificationInstruction.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flow.instructions;
+
+import org.onlab.packet.TpPort;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Abstraction of a single traffic treatment step.
+ */
+public abstract class L4ModificationInstruction implements Instruction {
+
+ /**
+ * Represents the type of traffic treatment.
+ */
+ public enum L4SubType {
+ /**
+ * TCP src modification.
+ */
+ TCP_SRC,
+
+ /**
+ * TCP dst modification.
+ */
+ TCP_DST,
+
+ /**
+ * UDP src modification.
+ */
+ UDP_SRC,
+
+ /**
+ * UDP dst modification.
+ */
+ UDP_DST
+
+ //TODO: remaining types
+ }
+
+ /**
+ * Returns the subtype of the modification instruction.
+ *
+ * @return type of instruction
+ */
+ public abstract L4SubType subtype();
+
+ @Override
+ public Type type() {
+ return Type.L4MODIFICATION;
+ }
+
+ /**
+ * Represents a L4 src/dst modification instruction.
+ */
+ public static final class ModTransportPortInstruction extends L4ModificationInstruction {
+
+ private final L4SubType subtype;
+ private final TpPort port;
+
+ public ModTransportPortInstruction(L4SubType subtype, TpPort port) {
+ this.subtype = subtype;
+ this.port = port;
+ }
+
+ @Override
+ public L4SubType subtype() {
+ return this.subtype;
+ }
+
+ public TpPort port() {
+ return this.port;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(subtype().toString())
+ .add("port", port).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subtype(), port);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ModTransportPortInstruction) {
+ ModTransportPortInstruction that = (ModTransportPortInstruction) obj;
+ return Objects.equals(port, that.port) &&
+ Objects.equals(this.subtype(), that.subtype());
+ }
+ return false;
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/package-info.java
new file mode 100644
index 00000000..65f58a40
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Traffic treatment model.
+ */
+package org.onosproject.net.flow.instructions;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/package-info.java
new file mode 100644
index 00000000..6068b6f2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Flow rule model &amp; related services API definitions.
+ *
+ * <p>
+ * The figure below depicts the general interactions between different
+ * components of the intent subsystem.<br>
+ * <img src="doc-files/flow-design.png" alt="ONOS flow rule subsystem design">
+ * </p>
+ */
+package org.onosproject.net.flow;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java
new file mode 100644
index 00000000..7b5924fb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.Criterion;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of a filtering objective.
+ */
+@Beta
+public final class DefaultFilteringObjective implements FilteringObjective {
+
+
+ private final Type type;
+ private final boolean permanent;
+ private final int timeout;
+ private final ApplicationId appId;
+ private final int priority;
+ private final Criterion key;
+ private final List<Criterion> conditions;
+ private final int id;
+ private final Operation op;
+ private final Optional<ObjectiveContext> context;
+
+ private DefaultFilteringObjective(Builder builder) {
+ this.key = builder.key;
+ this.type = builder.type;
+ this.permanent = builder.permanent;
+ this.timeout = builder.timeout;
+ this.appId = builder.appId;
+ this.priority = builder.priority;
+ this.conditions = builder.conditions;
+ this.op = builder.op;
+ this.context = Optional.ofNullable(builder.context);
+
+ this.id = Objects.hash(type, key, conditions, permanent,
+ timeout, appId, priority);
+ }
+
+ @Override
+ public Criterion key() {
+ return key;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ @Override
+ public Collection<Criterion> conditions() {
+ return conditions;
+ }
+
+ @Override
+ public int id() {
+ return id;
+ }
+
+ @Override
+ public int priority() {
+ return priority;
+ }
+
+ @Override
+ public ApplicationId appId() {
+ return appId;
+ }
+
+ @Override
+ public int timeout() {
+ return timeout;
+ }
+
+ @Override
+ public boolean permanent() {
+ return permanent;
+ }
+
+ @Override
+ public Operation op() {
+ return op;
+ }
+
+ @Override
+ public Optional<ObjectiveContext> context() {
+ return context;
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+
+ public static final class Builder implements FilteringObjective.Builder {
+ private final ImmutableList.Builder<Criterion> listBuilder
+ = ImmutableList.builder();
+
+ private Type type;
+ private boolean permanent = DEFAULT_PERMANENT;
+ private int timeout = DEFAULT_TIMEOUT;
+ private ApplicationId appId;
+ private int priority = DEFAULT_PRIORITY;
+ private Criterion key = Criteria.dummy();
+ private List<Criterion> conditions;
+ private Operation op;
+ private ObjectiveContext context;
+
+ @Override
+ public Builder withKey(Criterion key) {
+ this.key = key;
+ return this;
+ }
+
+ @Override
+ public Builder addCondition(Criterion criterion) {
+ listBuilder.add(criterion);
+ return this;
+ }
+
+ @Override
+ public Builder permit() {
+ this.type = Type.PERMIT;
+ return this;
+ }
+
+ @Override
+ public Builder deny() {
+ this.type = Type.DENY;
+ return this;
+ }
+
+ @Override
+ public Builder makeTemporary(int timeout) {
+ this.timeout = timeout;
+ permanent = false;
+ return this;
+ }
+
+ @Override
+ public Builder makePermanent() {
+ permanent = true;
+ return this;
+ }
+
+ @Override
+ public Builder fromApp(ApplicationId appId) {
+ this.appId = appId;
+ return this;
+ }
+
+ @Override
+ public Builder withPriority(int priority) {
+ this.priority = priority;
+ return this;
+ }
+
+ @Override
+ public FilteringObjective add() {
+ conditions = listBuilder.build();
+ op = Operation.ADD;
+ checkNotNull(type, "Must have a type.");
+ checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
+ checkNotNull(appId, "Must supply an application id");
+
+ return new DefaultFilteringObjective(this);
+
+ }
+
+ @Override
+ public FilteringObjective remove() {
+ conditions = listBuilder.build();
+ checkNotNull(type, "Must have a type.");
+ checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
+ checkNotNull(appId, "Must supply an application id");
+ op = Operation.REMOVE;
+
+ return new DefaultFilteringObjective(this);
+
+ }
+
+ @Override
+ public FilteringObjective add(ObjectiveContext context) {
+ conditions = listBuilder.build();
+ checkNotNull(type, "Must have a type.");
+ checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
+ checkNotNull(appId, "Must supply an application id");
+ op = Operation.ADD;
+ this.context = context;
+
+ return new DefaultFilteringObjective(this);
+ }
+
+ @Override
+ public FilteringObjective remove(ObjectiveContext context) {
+ conditions = listBuilder.build();
+ checkNotNull(type, "Must have a type.");
+ checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
+ checkNotNull(appId, "Must supply an application id");
+ op = Operation.REMOVE;
+ this.context = context;
+
+ return new DefaultFilteringObjective(this);
+ }
+
+
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultForwardingObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultForwardingObjective.java
new file mode 100644
index 00000000..0abf5abe
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultForwardingObjective.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of a forwarding objective.
+ */
+@Beta
+public final class DefaultForwardingObjective implements ForwardingObjective {
+
+ private final TrafficSelector selector;
+ private final Flag flag;
+ private final boolean permanent;
+ private final int timeout;
+ private final ApplicationId appId;
+ private final int priority;
+ private final Integer nextId;
+ private final TrafficTreatment treatment;
+ private final Operation op;
+ private final Optional<ObjectiveContext> context;
+
+ private final int id;
+
+ private DefaultForwardingObjective(Builder builder) {
+ this.selector = builder.selector;
+ this.flag = builder.flag;
+ this.permanent = builder.permanent;
+ this.timeout = builder.timeout;
+ this.appId = builder.appId;
+ this.priority = builder.priority;
+ this.nextId = builder.nextId;
+ this.treatment = builder.treatment;
+ this.op = builder.op;
+ this.context = Optional.ofNullable(builder.context);
+
+ this.id = Objects.hash(selector, flag, permanent,
+ timeout, appId, priority, nextId,
+ treatment, op);
+ }
+
+
+ @Override
+ public TrafficSelector selector() {
+ return selector;
+ }
+
+ @Override
+ public Integer nextId() {
+ return nextId;
+ }
+
+ @Override
+ public TrafficTreatment treatment() {
+ return treatment;
+ }
+
+
+ @Override
+ public Flag flag() {
+ return flag;
+ }
+
+ @Override
+ public int id() {
+ return id;
+ }
+
+ @Override
+ public int priority() {
+ return priority;
+ }
+
+ @Override
+ public ApplicationId appId() {
+ return appId;
+ }
+
+ @Override
+ public int timeout() {
+ return timeout;
+ }
+
+ @Override
+ public boolean permanent() {
+ return permanent;
+ }
+
+ @Override
+ public Operation op() {
+ return op;
+ }
+
+ @Override
+ public Optional<ObjectiveContext> context() {
+ return context;
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder implements ForwardingObjective.Builder {
+
+ private TrafficSelector selector;
+ private Flag flag;
+ private boolean permanent = DEFAULT_PERMANENT;
+ private int timeout = DEFAULT_TIMEOUT;
+ private int priority = DEFAULT_PRIORITY;
+ private ApplicationId appId;
+ private Integer nextId;
+ private TrafficTreatment treatment;
+ private Operation op;
+ private ObjectiveContext context;
+
+ @Override
+ public Builder withSelector(TrafficSelector selector) {
+ this.selector = selector;
+ return this;
+ }
+
+ @Override
+ public Builder nextStep(int nextId) {
+ this.nextId = nextId;
+ return this;
+ }
+
+ @Override
+ public Builder withTreatment(TrafficTreatment treatment) {
+ this.treatment = treatment;
+ return this;
+ }
+
+ @Override
+ public Builder withFlag(Flag flag) {
+ this.flag = flag;
+ return this;
+ }
+
+ @Override
+ public Builder makeTemporary(int timeout) {
+ this.timeout = timeout;
+ this.permanent = false;
+ return this;
+ }
+
+ @Override
+ public Builder makePermanent() {
+ this.permanent = true;
+ return this;
+ }
+
+ @Override
+ public Builder fromApp(ApplicationId appId) {
+ this.appId = appId;
+ return this;
+ }
+
+ @Override
+ public Builder withPriority(int priority) {
+ this.priority = priority;
+ return this;
+ }
+
+ @Override
+ public ForwardingObjective add() {
+ checkNotNull(selector, "Must have a selector");
+ checkNotNull(flag, "A flag must be set");
+ checkArgument(nextId != null || treatment != null, "Must supply at " +
+ "least a treatment and/or a nextId");
+ checkNotNull(appId, "Must supply an application id");
+ op = Operation.ADD;
+ return new DefaultForwardingObjective(this);
+ }
+
+ @Override
+ public ForwardingObjective remove() {
+ checkNotNull(selector, "Must have a selector");
+ checkNotNull(flag, "A flag must be set");
+ checkArgument(nextId != null || treatment != null, "Must supply at " +
+ "least a treatment and/or a nextId");
+ checkNotNull(appId, "Must supply an application id");
+ op = Operation.REMOVE;
+ return new DefaultForwardingObjective(this);
+ }
+
+ @Override
+ public ForwardingObjective add(ObjectiveContext context) {
+ checkNotNull(selector, "Must have a selector");
+ checkNotNull(flag, "A flag must be set");
+ checkArgument(nextId != null || treatment != null, "Must supply at " +
+ "least a treatment and/or a nextId");
+ checkNotNull(appId, "Must supply an application id");
+ op = Operation.ADD;
+ this.context = context;
+
+ return new DefaultForwardingObjective(this);
+ }
+
+ @Override
+ public ForwardingObjective remove(ObjectiveContext context) {
+ checkNotNull(selector, "Must have a selector");
+ checkNotNull(flag, "A flag must be set");
+ checkArgument(nextId != null || treatment != null, "Must supply at " +
+ "least a treatment and/or a nextId");
+ checkNotNull(appId, "Must supply an application id");
+ op = Operation.REMOVE;
+ this.context = context;
+
+ return new DefaultForwardingObjective(this);
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultNextObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultNextObjective.java
new file mode 100644
index 00000000..20e89295
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultNextObjective.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of a next objective.
+ */
+@Beta
+public final class DefaultNextObjective implements NextObjective {
+
+ private final List<TrafficTreatment> treatments;
+ private final ApplicationId appId;
+ private final Type type;
+ private final Integer id;
+ private final Operation op;
+ private final Optional<ObjectiveContext> context;
+
+ private DefaultNextObjective(Builder builder) {
+ this.treatments = builder.treatments;
+ this.appId = builder.appId;
+ this.type = builder.type;
+ this.id = builder.id;
+ this.op = builder.op;
+ this.context = Optional.ofNullable(builder.context);
+ }
+
+ @Override
+ public Collection<TrafficTreatment> next() {
+ return treatments;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public int id() {
+ return id;
+ }
+
+ @Override
+ public int priority() {
+ return 0;
+ }
+
+ @Override
+ public ApplicationId appId() {
+ return appId;
+ }
+
+ @Override
+ public int timeout() {
+ return 0;
+ }
+
+ @Override
+ public boolean permanent() {
+ return false;
+ }
+
+ @Override
+ public Operation op() {
+ return op;
+ }
+
+ @Override
+ public Optional<ObjectiveContext> context() {
+ return context;
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder implements NextObjective.Builder {
+
+ private ApplicationId appId;
+ private Type type;
+ private Integer id;
+ private List<TrafficTreatment> treatments;
+ private Operation op;
+ private ObjectiveContext context;
+
+ private final ImmutableList.Builder<TrafficTreatment> listBuilder
+ = ImmutableList.builder();
+
+ @Override
+ public Builder withId(int nextId) {
+ this.id = nextId;
+ return this;
+ }
+
+ @Override
+ public Builder withType(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public Builder addTreatment(TrafficTreatment treatment) {
+ listBuilder.add(treatment);
+ return this;
+ }
+
+ /**
+ * Noop. This method has no effect.
+ *
+ * @param timeout a timeout
+ * @return a next objective builder
+ */
+ @Override
+ public Builder makeTemporary(int timeout) {
+ return this;
+ }
+
+ /**
+ * Noop. This method has no effect.
+ *
+ * @return a next objective builder
+ */
+ @Override
+ public Builder makePermanent() {
+ return this;
+ }
+
+ @Override
+ public Builder fromApp(ApplicationId appId) {
+ this.appId = appId;
+ return this;
+ }
+
+ /**
+ * Noop. This method has no effect.
+ *
+ * @param priority an integer
+ * @return a next objective builder
+ */
+ @Override
+ public Builder withPriority(int priority) {
+ return this;
+ }
+
+ @Override
+ public NextObjective add() {
+ treatments = listBuilder.build();
+ op = Operation.ADD;
+ checkNotNull(appId, "Must supply an application id");
+ checkNotNull(id, "id cannot be null");
+ checkNotNull(type, "The type cannot be null");
+ checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
+
+ return new DefaultNextObjective(this);
+ }
+
+ @Override
+ public NextObjective remove() {
+ treatments = listBuilder.build();
+ op = Operation.REMOVE;
+ checkNotNull(appId, "Must supply an application id");
+ checkNotNull(id, "id cannot be null");
+ checkNotNull(type, "The type cannot be null");
+
+ return new DefaultNextObjective(this);
+ }
+
+ @Override
+ public NextObjective add(ObjectiveContext context) {
+ treatments = listBuilder.build();
+ op = Operation.ADD;
+ this.context = context;
+ checkNotNull(appId, "Must supply an application id");
+ checkNotNull(id, "id cannot be null");
+ checkNotNull(type, "The type cannot be null");
+ checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
+
+ return new DefaultNextObjective(this);
+ }
+
+ @Override
+ public NextObjective remove(ObjectiveContext context) {
+ treatments = listBuilder.build();
+ op = Operation.REMOVE;
+ this.context = context;
+ checkNotNull(appId, "Must supply an application id");
+ checkNotNull(id, "id cannot be null");
+ checkNotNull(type, "The type cannot be null");
+
+ return new DefaultNextObjective(this);
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java
new file mode 100644
index 00000000..58304571
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.criteria.Criterion;
+
+import java.util.Collection;
+
+/**
+ * Represents a filtering flow objective. Each filtering flow objective
+ * is made up of a key (criterion) to a set of criteria. Using this information
+ * a pipeline aware driver will decide how this objective should be mapped
+ * to the specific device pipeline. For example, consider the following
+ * filtering objective:
+ *
+ * portX -&gt; {MAC1, IP1, MAC2}
+ *
+ * The driver could decide to pass L3 packet to the L3 table and L2 packets to
+ * the L2 table for packets arriving on portX.
+ *
+ * Filtering objectives do not only represent what should be permitted into the
+ * pipeline but can also be used to deny or drop unwanted packets by specifying
+ * the appropriate type of filtering objective. It is also important to note
+ * that submitting a filtering objective does not necessarily result in rules
+ * programmed at the switch, the driver is free to decide when these rules are
+ * programmed. For example, a filtering rule may only be programmed once a
+ * corresponding forwarding objective has been received.
+ */
+@Beta
+public interface FilteringObjective extends Objective {
+
+ enum Type {
+ /**
+ * Enables the filtering condition.
+ */
+ PERMIT,
+
+ /**
+ * Disables the filtering condition.
+ */
+ DENY
+ }
+
+ /**
+ * Obtain the key for this filter.
+ *
+ * @return a criterion
+ */
+ Criterion key();
+
+ /**
+ * Obtain this filtering type.
+ *
+ * @return the type
+ */
+ Type type();
+
+ /**
+ * The set of conditions the filter must provision at the device.
+ *
+ * @return a collection of criteria
+ */
+ Collection<Criterion> conditions();
+
+ /**
+ * Builder of Filtering objective entities.
+ */
+ interface Builder extends Objective.Builder {
+
+ /**
+ * Specify the key for the filter.
+ *
+ * @param key a criterion
+ * @return a filter objective builder
+ */
+ Builder withKey(Criterion key);
+
+ /**
+ * Add a filtering condition.
+ *
+ * @param criterion new criterion
+ * @return a filtering builder
+ */
+ Builder addCondition(Criterion criterion);
+
+ /**
+ * Permit this filtering condition set.
+ *
+ * @return a filtering builder
+ */
+ Builder permit();
+
+ /**
+ * Deny this filtering condition set.
+ *
+ * @return a filtering builder
+ */
+ Builder deny();
+
+ /**
+ * Assigns an application id.
+ *
+ * @param appId an application id
+ * @return a filtering builder
+ */
+ Builder fromApp(ApplicationId appId);
+
+ /**
+ * Builds the filtering objective that will be added.
+ *
+ * @return a filtering objective
+ */
+ FilteringObjective add();
+
+ /**
+ * Builds the filtering objective that will be removed.
+ *
+ * @return a filtering objective.
+ */
+ FilteringObjective remove();
+
+ /**
+ * Builds the filtering objective that will be added.
+ * The context will be used to notify the calling application.
+ *
+ * @param context an objective context
+ * @return a filtering objective
+ */
+ FilteringObjective add(ObjectiveContext context);
+
+ /**
+ * Builds the filtering objective that will be removed.
+ * The context will be used to notify the calling application.
+ *
+ * @param context an objective context
+ * @return a filtering objective
+ */
+ FilteringObjective remove(ObjectiveContext context);
+
+
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveService.java
new file mode 100644
index 00000000..d3254151
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveService.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Service for programming data plane flow rules in manner independent of
+ * specific device table pipeline configuration.
+ */
+@Beta
+public interface FlowObjectiveService {
+
+ /**
+ * Installs the filtering rules onto the specified device.
+ *
+ * @param deviceId device identifier
+ * @param filteringObjective the filtering objective
+ */
+ void filter(DeviceId deviceId, FilteringObjective filteringObjective);
+
+ /**
+ * Installs the forwarding rules onto the specified device.
+ *
+ * @param deviceId device identifier
+ * @param forwardingObjective the forwarding objective
+ */
+ void forward(DeviceId deviceId, ForwardingObjective forwardingObjective);
+
+ /**
+ * Installs the next hop elements into the specified device.
+ *
+ * @param deviceId device identifier
+ * @param nextObjective a next objective
+ */
+ void next(DeviceId deviceId, NextObjective nextObjective);
+
+ /**
+ * Obtains a globally unique next objective.
+ *
+ * @return an integer
+ */
+ int allocateNextId();
+
+ /**
+ * Installs the filtering rules onto the specified device.
+ *
+ * @param policy policy expression
+ */
+ void initPolicy(String policy);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveStore.java
new file mode 100644
index 00000000..ecf5d733
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveStore.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.behaviour.NextGroup;
+import org.onosproject.store.Store;
+
+/**
+ * The flow objective store.
+ */
+@Beta
+public interface FlowObjectiveStore
+ extends Store<ObjectiveEvent, FlowObjectiveStoreDelegate> {
+
+ /**
+ * Adds a NextGroup to the store.
+ *
+ * @param nextId an integer
+ * @param group a next group opaque object
+ */
+ void putNextGroup(Integer nextId, NextGroup group);
+
+ /**
+ * Fetch a next group from the store.
+ * @param nextId an integer
+ * @return a next group
+ */
+ NextGroup getNextGroup(Integer nextId);
+
+ /**
+ * Allocates a next objective id. This id is globally unique
+ *
+ * @return an integer
+ */
+ int allocateNextId();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveStoreDelegate.java
new file mode 100644
index 00000000..2189af1b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveStoreDelegate.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Flow Objective store delegate abstraction.
+ */
+@Beta
+public interface FlowObjectiveStoreDelegate extends StoreDelegate<ObjectiveEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ForwardingObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ForwardingObjective.java
new file mode 100644
index 00000000..9857a710
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ForwardingObjective.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+/**
+ * Represents a description of which types of traffic need to
+ * be forwarded through the device. A forwarding objective may
+ * result in multiple rules at the device. There are two main types
+ * of forwarding objectives:
+ *
+ * - Versatile
+ * - Specific
+ *
+ * A versatile forwarding objective represents a composite rule that matches
+ * two or more header fields. The use of versatile usually indicates that this
+ * rule should be inserted in its entirety into the ACL table. Although,
+ * drivers for some devices are free to implement this differently.
+ *
+ * A specific forwarding objective represents a specific rule matching one or
+ * more header fields. The installation of this rule may result in several rules
+ * at the device. For example, one per table type.
+ */
+@Beta
+public interface ForwardingObjective extends Objective {
+
+ /**
+ * Represents whether this objective is monolithic or
+ * may be broken down into parts.
+ */
+ enum Flag {
+ /**
+ * A decomposable objective.
+ */
+ SPECIFIC,
+
+ /**
+ * A monolithic objective.
+ */
+ VERSATILE
+ }
+
+ /**
+ * Obtain the selector for this objective.
+ *
+ * @return a traffic selector
+ */
+ TrafficSelector selector();
+
+ /**
+ * Obtain the traffic treatment for this objective. Mutually exclusive with
+ * 'treatment'.
+ *
+ * @return an integer
+ */
+ Integer nextId();
+
+ /**
+ * A traffic treatment for this forwarding objective. Mutually exclusive
+ * with a nextId.
+ *
+ * @return a traffic treatment
+ */
+ TrafficTreatment treatment();
+
+ /**
+ * Obtain the type of this objective.
+ *
+ * @return a flag type
+ */
+ Flag flag();
+
+ /**
+ * A forwarding objective builder.
+ */
+ interface Builder extends Objective.Builder {
+
+ /**
+ * Assigns a selector to the forwarding objective.
+ *
+ * @param selector a traffic selector
+ * @return a forwarding objective builder
+ */
+ Builder withSelector(TrafficSelector selector);
+
+ /**
+ * Assigns a next step to the forwarding objective.
+ *
+ * @param nextId a next objective id.
+ * @return a forwarding objective builder
+ */
+ Builder nextStep(int nextId);
+
+ /**
+ * Assigns the treatment for this forwarding objective.
+ *
+ * @param treatment a traffic treatment
+ * @return a forwarding objective
+ */
+ Builder withTreatment(TrafficTreatment treatment);
+
+ /**
+ * Assigns the flag to the forwarding objective.
+ *
+ * @param flag a flag
+ * @return a forwarding objective builder
+ */
+ Builder withFlag(Flag flag);
+
+ /**
+ * Builds the forwarding objective that will be added.
+ *
+ * @return a forwarding objective
+ */
+ ForwardingObjective add();
+
+ /**
+ * Builds the forwarding objective that will be removed.
+ *
+ * @return a forwarding objective.
+ */
+ ForwardingObjective remove();
+
+ /**
+ * Builds the forwarding objective that will be added.
+ * The context will be used to notify the calling application.
+ *
+ * @param context an objective context
+ * @return a forwarding objective
+ */
+ ForwardingObjective add(ObjectiveContext context);
+
+ /**
+ * Builds the forwarding objective that will be removed.
+ * The context will be used to notify the calling application.
+ *
+ * @param context an objective context
+ * @return a forwarding objective
+ */
+ ForwardingObjective remove(ObjectiveContext context);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/NextObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/NextObjective.java
new file mode 100644
index 00000000..1350d7a1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/NextObjective.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.util.Collection;
+
+/**
+ * Represents a nexthop which will be translated by a driver
+ * into the appropriate group or actions needed to implement
+ * the egress function.
+ *
+ * A next objective is made up of a collection of traffic treatments
+ * associated with a type. These types are:
+ *
+ * - Hashed
+ * - Broadcast
+ * - Failover
+ * - Simple
+ *
+ * These types will indicate to the driver what the intended behaviour is.
+ * For example, a broadcast next objective with a collection of output
+ * treatments will indicate to a driver that all output actions are expected
+ * to be executed simultaneously. The driver is then free to implement this
+ * as a group or a simple action list.
+ */
+@Beta
+public interface NextObjective extends Objective {
+
+ /**
+ * Represents the type of next phase to build.
+ */
+ enum Type {
+ /**
+ * A hashed packet processing.
+ */
+ HASHED,
+
+ /**
+ * Broadcast packet process.
+ */
+ BROADCAST,
+
+ /**
+ * Failover handling.
+ */
+ FAILOVER,
+
+ /**
+ * Simple processing. Could be a group or a treatment.
+ */
+ SIMPLE
+ }
+
+ /**
+ * The collection of treatments that need to be applied to a set of traffic.
+ *
+ * @return a collection of traffic treatments
+ */
+ Collection<TrafficTreatment> next();
+
+ /**
+ * The type of operation that will be applied to the traffic using the collection
+ * of treatments.
+ *
+ * @return a type
+ */
+ Type type();
+
+ /**
+ * A next step builder.
+ */
+ interface Builder extends Objective.Builder {
+
+ /**
+ * Specifies the id for this next objective.
+ *
+ * @param nextId an integer
+ * @return a next objective builder
+ */
+ Builder withId(int nextId);
+
+ /**
+ * Sets the type of next step.
+ *
+ * @param type a type
+ * @return a next step builder
+ */
+ Builder withType(Type type);
+
+ /**
+ * Adds a treatment to this next step.
+ *
+ * @param treatment a traffic treatment
+ * @return a next step builder
+ */
+ Builder addTreatment(TrafficTreatment treatment);
+
+ /**
+ * Specifies the application which applied the filter.
+ *
+ * @param appId an application id
+ * @return an objective builder
+ */
+ @Override
+ Builder fromApp(ApplicationId appId);
+
+ /**
+ * Sets the priority for this objective.
+ *
+ * @param priority an integer
+ * @return an objective builder
+ */
+ @Override
+ Builder withPriority(int priority);
+
+ /**
+ * Builds the next objective that will be added.
+ *
+ * @return a next objective
+ */
+ NextObjective add();
+
+ /**
+ * Builds the next objective that will be removed.
+ *
+ * @return a next objective.
+ */
+ NextObjective remove();
+
+ /**
+ * Builds the next objective that will be added.
+ * The context will be used to notify the calling application.
+ *
+ * @param context an objective context
+ * @return a next objective
+ */
+ NextObjective add(ObjectiveContext context);
+
+ /**
+ * Builds the next objective that will be removed.
+ * The context will be used to notify the calling application.
+ *
+ * @param context an objective context
+ * @return a next objective
+ */
+ NextObjective remove(ObjectiveContext context);
+
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/Objective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/Objective.java
new file mode 100644
index 00000000..090c298c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/Objective.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+
+import java.util.Optional;
+
+/**
+ * Base representation of an flow description.
+ */
+@Beta
+public interface Objective {
+
+ static final boolean DEFAULT_PERMANENT = true;
+ static final int DEFAULT_TIMEOUT = 0;
+ static final int DEFAULT_PRIORITY = 32768;
+
+ /**
+ * Type of operation.
+ */
+ enum Operation {
+ /**
+ * Adds the objective.
+ */
+ ADD,
+
+ /**
+ * Removes the objective.
+ */
+ REMOVE
+ }
+
+ /**
+ * An identifier for this objective.
+ *
+ * @return an integer
+ */
+ int id();
+
+ /**
+ * The priority for this objective.
+ *
+ * @return an integer
+ */
+ int priority();
+
+ /**
+ * The application which applied this objective.
+ *
+ * @return an application id
+ */
+ ApplicationId appId();
+
+ /**
+ * The timeout for this objective.
+ *
+ * @return an integer
+ */
+ int timeout();
+
+ /**
+ * Whether this objective is permanent.
+ *
+ * @return a boolean
+ */
+ boolean permanent();
+
+ /**
+ * The type of operation for this objective.
+ *
+ * @return an operation
+ */
+ Operation op();
+
+ /**
+ * Obtains an optional context.
+ *
+ * @return optional; which will be empty if there is no context.
+ * Otherwise it will return the context.
+ */
+ Optional<ObjectiveContext> context();
+
+ /**
+ * An objective builder.
+ */
+ interface Builder {
+ /**
+ * Makes the filtering objective temporary.
+ *
+ * @param timeout a timeout
+ * @return an objective builder
+ */
+ Builder makeTemporary(int timeout);
+
+ /**
+ * Makes the filtering objective permanent.
+ *
+ * @return an objective builder
+ */
+ Builder makePermanent();
+
+ /**
+ * Specifies the application which applied the filter.
+ *
+ * @param appId an application id
+ * @return an objective builder
+ */
+ Builder fromApp(ApplicationId appId);
+
+ /**
+ * Sets the priority for this objective.
+ *
+ * @param priority an integer
+ * @return an objective builder
+ */
+ Builder withPriority(int priority);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveContext.java
new file mode 100644
index 00000000..f3d23e4a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveContext.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * The context of a objective that will become the subject of
+ * the notification.
+ * <p>
+ * Implementations of this class must be serializable.
+ * </p>
+ */
+@Beta
+public interface ObjectiveContext {
+
+ /**
+ * Invoked on successful execution of the flow objective.
+ *
+ * @param objective objective to execute
+ */
+ default void onSuccess(Objective objective) {
+ }
+
+ /**
+ * Invoked when error is encountered while executing the flow objective.
+ *
+ * @param objective objective to execute
+ * @param error error encountered
+ */
+ default void onError(Objective objective, ObjectiveError error) {
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveError.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveError.java
new file mode 100644
index 00000000..fd159d7e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveError.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents the set of errors possible when processing an objective.
+ */
+@Beta
+public enum ObjectiveError {
+
+ /**
+ * The driver processing this objective does not know how to process it.
+ */
+ UNSUPPORTED,
+
+ /**
+ * The flow installation for this objective failed.
+ */
+ FLOWINSTALLATIONFAILED,
+
+ /**
+ * THe group installation for this objective failed.
+ */
+ GROUPINSTALLATIONFAILED,
+
+ /**
+ * The group was reported as installed but is missing.
+ */
+ GROUPMISSING,
+
+ /**
+ * The device was not available to install objectives to.
+ */
+ DEVICEMISSING,
+
+ /**
+ * Incorrect Objective parameters passed in by the caller.
+ */
+ BADPARAMS,
+
+ /**
+ * An unknown error occurred.
+ */
+ UNKNOWN
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveEvent.java
new file mode 100644
index 00000000..c6937e31
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveEvent.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.flowobjective;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes a objective event.
+ */
+@Beta
+public class ObjectiveEvent extends AbstractEvent<ObjectiveEvent.Type, Integer> {
+
+ /**
+ * Type of objective events.
+ */
+ public enum Type {
+ /**
+ * Signifies that the objective has been added to the store.
+ */
+ ADD,
+
+ /**
+ * Signifies that the objective has been removed.
+ */
+ REMOVE
+ }
+
+ /**
+ * Creates an event of the given type for the specified objective id.
+ *
+ * @param type the type of the event
+ * @param objective the objective id the event is about
+ */
+ public ObjectiveEvent(Type type, Integer objective) {
+ super(type, objective);
+ }
+
+ /**
+ * Creates an event of the given type for the specified objective id at the given
+ * time.
+ *
+ * @param type the type of the event
+ * @param objective the objective id the event is about
+ * @param time the time of the event
+ */
+ public ObjectiveEvent(Type type, Integer objective, long time) {
+ super(type, objective, time);
+ }
+}
+
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/package-info.java
new file mode 100644
index 00000000..105f7b59
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Abstractions for objective-based flow programming of data plane without
+ * requiring device pipeline structure awareness.&nbsp; This subsystem is
+ * experimental and its interfaces will change in the upcoming release.
+ */
+package org.onosproject.net.flowobjective; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java
new file mode 100644
index 00000000..546a4513
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import java.util.Objects;
+
+import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
+
+/**
+ * ONOS implementation of default group that is stored in the system.
+ */
+public class DefaultGroup extends DefaultGroupDescription
+ implements Group, StoredGroupEntry {
+
+ private GroupState state;
+ private boolean isGroupStateAddedFirstTime;
+ private long life;
+ private long packets;
+ private long bytes;
+ private long referenceCount;
+ private GroupId id;
+
+ /**
+ * Initializes default values.
+ *
+ * @param newId group id for new group
+ */
+ private void initialize(GroupId newId) {
+ id = newId;
+ state = GroupState.PENDING_ADD;
+ life = 0;
+ packets = 0;
+ bytes = 0;
+ referenceCount = 0;
+ }
+
+ /**
+ * Default group object constructor with the parameters.
+ *
+ * @param id group identifier
+ * @param groupDesc group description parameters
+ */
+ public DefaultGroup(GroupId id, GroupDescription groupDesc) {
+ super(groupDesc);
+ initialize(id);
+ }
+
+ /**
+ * Default group object constructor with the available information
+ * from data plane.
+ *
+ * @param id group identifier
+ * @param deviceId device identifier
+ * @param type type of the group
+ * @param buckets immutable list of group bucket
+ */
+ public DefaultGroup(GroupId id,
+ DeviceId deviceId,
+ GroupDescription.Type type,
+ GroupBuckets buckets) {
+ super(deviceId, type, buckets);
+ initialize(id);
+ }
+
+ /**
+ * Returns group identifier associated with a group object.
+ *
+ * @return GroupId Group Identifier
+ */
+ @Override
+ public GroupId id() {
+ return this.id;
+ }
+
+ /**
+ * Returns current state of a group object.
+ *
+ * @return GroupState Group State
+ */
+ @Override
+ public GroupState state() {
+ return this.state;
+ }
+
+ /**
+ * Returns the number of milliseconds this group has been alive.
+ *
+ * @return number of millis
+ */
+ @Override
+ public long life() {
+ return this.life;
+ }
+
+ /**
+ * Returns the number of packets processed by this group.
+ *
+ * @return number of packets
+ */
+ @Override
+ public long packets() {
+ return this.packets;
+ }
+
+ /**
+ * Returns the number of bytes processed by this group.
+ *
+ * @return number of bytes
+ */
+ @Override
+ public long bytes() {
+ return this.bytes;
+ }
+
+ /**
+ * Sets the new state for this entry.
+ *
+ * @param newState new group entry state.
+ */
+ @Override
+ public void setState(Group.GroupState newState) {
+ this.state = newState;
+ }
+
+ /**
+ * Sets how long this entry has been entered in the system.
+ *
+ * @param life epoch time
+ */
+ @Override
+ public void setLife(long life) {
+ this.life = life;
+ }
+
+ /**
+ * Sets number of packets processed by this group entry.
+ *
+ * @param packets a long value
+ */
+ @Override
+ public void setPackets(long packets) {
+ this.packets = packets;
+ }
+
+ /**
+ * Sets number of bytes processed by this group entry.
+ *
+ * @param bytes a long value
+ */
+ @Override
+ public void setBytes(long bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public void setReferenceCount(long referenceCount) {
+ this.referenceCount = referenceCount;
+ }
+
+ @Override
+ public long referenceCount() {
+ return referenceCount;
+ }
+
+ /*
+ * The deviceId, type and buckets are used for hash.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public int hashCode() {
+ return super.hashCode() + Objects.hash(id);
+ }
+
+ /*
+ * The deviceId, groupId, type and buckets should be same.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultGroup) {
+ DefaultGroup that = (DefaultGroup) obj;
+ return super.equals(obj) &&
+ Objects.equals(id, that.id);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("description", super.toString())
+ .add("groupid", id)
+ .add("state", state)
+ .toString();
+ }
+
+ @Override
+ public void setIsGroupStateAddedFirstTime(boolean isGroupStateAddedFirstTime) {
+ this.isGroupStateAddedFirstTime = isGroupStateAddedFirstTime;
+ }
+
+ @Override
+ public boolean isGroupStateAddedFirstTime() {
+ return isGroupStateAddedFirstTime;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
new file mode 100644
index 00000000..6efd3e79
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.core.GroupId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instruction;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Group bucket implementation. A group bucket is collection of
+ * instructions that can be performed on a traffic flow. A select
+ * Group can have one or more Buckets where traffic will be
+ * processed by a single bucket in the group, based on device
+ * specific selection algorithm (e.g. hash on some fields of the
+ * incoming traffic flows or round robin) and hence can contains
+ * optional weight field to define the weights among the buckets
+ * in the group. A failover group bucket is associated with a
+ * specific port or group that controls its liveness.
+ */
+public final class DefaultGroupBucket implements GroupBucket, StoredGroupBucketEntry {
+ private final GroupDescription.Type type;
+ private final TrafficTreatment treatment;
+ private final short weight;
+ private final PortNumber watchPort;
+ private final GroupId watchGroup;
+ private long packets;
+ private long bytes;
+
+ /**
+ * Group bucket constructor with the parameters.
+ *
+ * @param type group bucket type
+ * @param treatment traffic treatment associated with group bucket
+ * @param weight optional weight associated with group bucket
+ * @param watchPort port that determines the liveness of group bucket
+ * @param watchGroup group that determines the liveness of group bucket
+ */
+ private DefaultGroupBucket(GroupDescription.Type type,
+ TrafficTreatment treatment,
+ short weight,
+ PortNumber watchPort,
+ GroupId watchGroup) {
+ this.type = type;
+ this.treatment = checkNotNull(treatment);
+ this.weight = weight;
+ this.watchPort = watchPort;
+ this.watchGroup = watchGroup;
+ }
+
+ /**
+ * Creates indirect group bucket.
+ *
+ * @param treatment traffic treatment associated with group bucket
+ * @return indirect group bucket object
+ */
+ public static GroupBucket createIndirectGroupBucket(
+ TrafficTreatment treatment) {
+ return new DefaultGroupBucket(GroupDescription.Type.INDIRECT,
+ treatment,
+ (short) -1,
+ null,
+ null);
+ }
+
+ /**
+ * Creates select group bucket with weight as 1.
+ *
+ * @param treatment traffic treatment associated with group bucket
+ * @return select group bucket object
+ */
+ public static GroupBucket createSelectGroupBucket(
+ TrafficTreatment treatment) {
+ return new DefaultGroupBucket(GroupDescription.Type.SELECT,
+ treatment,
+ (short) 1,
+ null,
+ null);
+ }
+
+ /**
+ * Creates select group bucket with specified weight.
+ *
+ * @param treatment traffic treatment associated with group bucket
+ * @param weight weight associated with group bucket
+ * @return select group bucket object
+ */
+ public static GroupBucket createSelectGroupBucket(
+ TrafficTreatment treatment,
+ short weight) {
+ if (weight == 0) {
+ return null;
+ }
+
+ return new DefaultGroupBucket(GroupDescription.Type.SELECT,
+ treatment,
+ weight,
+ null,
+ null);
+ }
+
+ /**
+ * Creates failover group bucket with watchport or watchgroup.
+ *
+ * @param treatment traffic treatment associated with group bucket
+ * @param watchPort port that determines the liveness of group bucket
+ * @param watchGroup group that determines the liveness of group bucket
+ * @return failover group bucket object
+ */
+ public static GroupBucket createFailoverGroupBucket(
+ TrafficTreatment treatment,
+ PortNumber watchPort,
+ GroupId watchGroup) {
+ checkArgument(((watchPort != null) || (watchGroup != null)));
+ return new DefaultGroupBucket(GroupDescription.Type.FAILOVER,
+ treatment,
+ (short) -1,
+ watchPort,
+ watchGroup);
+ }
+
+ @Override
+ public GroupDescription.Type type() {
+ return this.type;
+ }
+
+ /**
+ * Returns list of Traffic instructions that are part of the bucket.
+ *
+ * @return TrafficTreatment Traffic instruction list
+ */
+ @Override
+ public TrafficTreatment treatment() {
+ return treatment;
+ }
+
+ /**
+ * Returns weight of select group bucket.
+ *
+ * @return short weight associated with a bucket
+ */
+ @Override
+ public short weight() {
+ return weight;
+ }
+
+ /**
+ * Returns port number used for liveness detection for a
+ * failover bucket.
+ *
+ * @return PortNumber port number used for liveness detection
+ */
+ @Override
+ public PortNumber watchPort() {
+ return watchPort;
+ }
+
+ /**
+ * Returns group identifier used for liveness detection for a
+ * failover bucket.
+ *
+ * @return GroupId group identifier to be used for liveness detection
+ */
+ @Override
+ public GroupId watchGroup() {
+ return watchGroup;
+ }
+
+ /*
+ * The type and treatment can change on a given bucket
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, treatment);
+ }
+
+ /*
+ * The priority and statistics can change on a given treatment and selector
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultGroupBucket) {
+ DefaultGroupBucket that = (DefaultGroupBucket) obj;
+ List<Instruction> myInstructions = this.treatment.allInstructions();
+ List<Instruction> theirInstructions = that.treatment.allInstructions();
+
+ return Objects.equals(type, that.type) &&
+ myInstructions.containsAll(theirInstructions) &&
+ theirInstructions.containsAll(myInstructions);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("type", type)
+ .add("treatment", treatment)
+ .add("packets", packets)
+ .add("bytes", bytes)
+ .toString();
+ }
+
+ @Override
+ public long packets() {
+ return packets;
+ }
+
+ @Override
+ public long bytes() {
+ return bytes;
+ }
+
+ @Override
+ public void setPackets(long packets) {
+ this.packets = packets;
+ }
+
+ @Override
+ public void setBytes(long bytes) {
+ this.bytes = bytes;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
new file mode 100644
index 00000000..1580d835
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Default implementation of group description interface.
+ */
+public class DefaultGroupDescription implements GroupDescription {
+ private final GroupDescription.Type type;
+ private final GroupBuckets buckets;
+ private final GroupKey appCookie;
+ private final ApplicationId appId;
+ private final DeviceId deviceId;
+ private final Integer givenGroupId;
+
+ /**
+ * Constructor to be used by north bound applications.
+ * NOTE: The caller of this subsystem MUST ensure the appCookie
+ * provided in this API is immutable.
+ * NOTE: The caller may choose to pass in 'null' for the groupId. This is
+ * the typical case, where the caller allows the group subsystem to choose
+ * the groupId in a globally unique way. If the caller passes in the groupId,
+ * the caller MUST ensure that the id is globally unique (not just unique
+ * per device).
+ *
+ * @param deviceId device identifier
+ * @param type type of the group
+ * @param buckets immutable list of group bucket
+ * @param appCookie immutable application cookie of type DefaultGroupKey
+ * to be associated with the group
+ * @param groupId group identifier
+ * @param appId application id
+ */
+ public DefaultGroupDescription(DeviceId deviceId,
+ GroupDescription.Type type,
+ GroupBuckets buckets,
+ GroupKey appCookie,
+ Integer groupId,
+ ApplicationId appId) {
+ this.type = checkNotNull(type);
+ this.deviceId = checkNotNull(deviceId);
+ this.buckets = checkNotNull(buckets);
+ this.appCookie = appCookie;
+ this.givenGroupId = groupId;
+ this.appId = appId;
+ }
+
+ /**
+ * Constructor to be used by group subsystem internal components.
+ * Creates group description object from another object of same type.
+ *
+ * @param groupDesc group description object
+ *
+ */
+ public DefaultGroupDescription(GroupDescription groupDesc) {
+ this.type = groupDesc.type();
+ this.deviceId = groupDesc.deviceId();
+ this.buckets = groupDesc.buckets();
+ this.appCookie = groupDesc.appCookie();
+ this.appId = groupDesc.appId();
+ this.givenGroupId = groupDesc.givenGroupId();
+ }
+
+ /**
+ * Constructor to be used by group subsystem internal components.
+ * Creates group description object from the information retrieved
+ * from data plane.
+ *
+ * @param deviceId device identifier
+ * @param type type of the group
+ * @param buckets immutable list of group bucket
+ *
+ */
+ public DefaultGroupDescription(DeviceId deviceId,
+ GroupDescription.Type type,
+ GroupBuckets buckets) {
+ this(deviceId, type, buckets, null, null, null);
+ }
+
+ /**
+ * Returns type of a group object.
+ *
+ * @return GroupType group type
+ */
+ @Override
+ public GroupDescription.Type type() {
+ return this.type;
+ }
+
+ /**
+ * Returns device identifier on which this group object is created.
+ *
+ * @return DeviceId device identifier
+ */
+ @Override
+ public DeviceId deviceId() {
+ return this.deviceId;
+ }
+
+ /**
+ * Returns application identifier that has created this group object.
+ *
+ * @return ApplicationId application identifier
+ */
+ @Override
+ public ApplicationId appId() {
+ return this.appId;
+ }
+
+ /**
+ * Returns application cookie associated with a group object.
+ *
+ * @return GroupKey application cookie
+ */
+ @Override
+ public GroupKey appCookie() {
+ return this.appCookie;
+ }
+
+ /**
+ * Returns group buckets of a group.
+ *
+ * @return GroupBuckets immutable list of group bucket
+ */
+ @Override
+ public GroupBuckets buckets() {
+ return this.buckets;
+ }
+
+ /**
+ * Returns groupId passed in by application.
+ *
+ * @return Integer group Id passed in by caller. May be null if caller passed
+ * in null during GroupDescription creation.
+ */
+ @Override
+ public Integer givenGroupId() {
+ return this.givenGroupId;
+ }
+
+ @Override
+ /*
+ * The deviceId, type and buckets are used for hash.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public int hashCode() {
+ return Objects.hash(deviceId, type, buckets);
+ }
+
+ @Override
+ /*
+ * The deviceId, type and buckets should be same.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultGroupDescription) {
+ DefaultGroupDescription that = (DefaultGroupDescription) obj;
+ return Objects.equals(deviceId, that.deviceId) &&
+ Objects.equals(type, that.type) &&
+ Objects.equals(buckets, that.buckets);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("deviceId", deviceId)
+ .add("type", type)
+ .add("buckets", buckets)
+ .add("appId", appId)
+ .add("givenGroupId", givenGroupId)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupKey.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupKey.java
new file mode 100644
index 00000000..7f00ae70
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupKey.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Arrays;
+
+/**
+ * Default implementation of group key interface.
+ */
+public class DefaultGroupKey implements GroupKey {
+
+ private final byte[] key;
+
+ public DefaultGroupKey(byte[] key) {
+ this.key = checkNotNull(key);
+ }
+
+ @Override
+ public byte[] key() {
+ return key;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof DefaultGroupKey)) {
+ return false;
+ }
+ DefaultGroupKey that = (DefaultGroupKey) o;
+ return (Arrays.equals(this.key, that.key));
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(this.key);
+ }
+
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/Group.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/Group.java
new file mode 100644
index 00000000..54407752
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/Group.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.core.GroupId;
+
+/**
+ * ONOS representation of group that is stored in the system.
+ */
+public interface Group extends GroupDescription {
+ /**
+ * State of the group object in ONOS.
+ */
+ enum GroupState {
+ /**
+ * Group create request is queued as group AUDIT is in progress.
+ */
+ WAITING_AUDIT_COMPLETE,
+ /**
+ * Group create request is processed by ONOS and not yet
+ * received the confirmation from data plane.
+ */
+ PENDING_ADD,
+ /**
+ * Group is missing in data plane and retrying GROUP ADD request.
+ */
+ PENDING_ADD_RETRY,
+ /**
+ * Group is created in the data plane.
+ */
+ ADDED,
+ /**
+ * Group update request is processed by ONOS and not
+ * received the confirmation from data plane post which
+ * state moves to ADDED state.
+ */
+ PENDING_UPDATE,
+ /**
+ * Group delete request is processed by ONOS and not
+ * received the confirmation from data plane.
+ */
+ PENDING_DELETE
+ }
+
+ /**
+ * Returns group identifier associated with a group object.
+ *
+ * @return GroupId Group Identifier
+ */
+ GroupId id();
+
+ /**
+ * Returns current state of a group object.
+ *
+ * @return GroupState Group State
+ */
+ GroupState state();
+
+ /**
+ * Returns the number of milliseconds this group has been alive.
+ *
+ * @return number of millis
+ */
+ long life();
+
+ /**
+ * Returns the number of packets processed by this group.
+ *
+ * @return number of packets
+ */
+ long packets();
+
+ /**
+ * Returns the number of bytes processed by this group.
+ *
+ * @return number of bytes
+ */
+ long bytes();
+
+ /**
+ * Returns the number of flow rules or other groups reference this group.
+ *
+ * @return number of flow rules or other groups pointing to this group
+ */
+ long referenceCount();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupBucket.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupBucket.java
new file mode 100644
index 00000000..a503c154
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupBucket.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.core.GroupId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.TrafficTreatment;
+
+/**
+ * Group Bucket definition. A default group Bucket is collection of
+ * Instructions that can be performed on a traffic flow. A failover
+ * group bucket is associated with a specific port or group that
+ * controls its liveness. A select group bucket contains optional
+ * weight field to define the weights among the buckets in the group.
+ */
+public interface GroupBucket {
+ /**
+ * Returns group type of the bucket.
+ *
+ * @return GroupType group type
+ */
+ GroupDescription.Type type();
+
+ /**
+ * Returns list of Traffic instructions that are part of the bucket.
+ *
+ * @return TrafficTreatment traffic instruction list
+ */
+ TrafficTreatment treatment();
+
+ /**
+ * Returns weight of select group bucket.
+ *
+ * @return short weight associated with a bucket
+ */
+ short weight();
+
+ /**
+ * Returns port number used for liveness detection for a
+ * failover bucket.
+ *
+ * @return PortNumber port number used for liveness detection
+ */
+ PortNumber watchPort();
+
+ /**
+ * Returns group identifier used for liveness detection for a
+ * failover bucket.
+ *
+ * @return GroupId group identifier to be used for liveness detection
+ */
+ GroupId watchGroup();
+
+ /**
+ * Returns the number of packets processed by this group bucket.
+ *
+ * @return number of packets
+ */
+ long packets();
+
+ /**
+ * Returns the number of bytes processed by this group bucket.
+ *
+ * @return number of bytes
+ */
+ long bytes();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupBuckets.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupBuckets.java
new file mode 100644
index 00000000..c0b5e5c6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupBuckets.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Immutable collection of group bucket.
+ */
+public final class GroupBuckets {
+ private final List<GroupBucket> buckets;
+
+ /**
+ * Creates a immutable list of group bucket.
+ *
+ * @param buckets list of group bucket
+ */
+ public GroupBuckets(List<GroupBucket> buckets) {
+ this.buckets = ImmutableList.copyOf(checkNotNull(buckets));
+ }
+
+ /**
+ * Returns immutable list of group buckets.
+ *
+ * @return list of group bucket
+ */
+ public List<GroupBucket> buckets() {
+ return buckets;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ int combinedHash = 0;
+ for (GroupBucket bucket:buckets) {
+ combinedHash = combinedHash + bucket.hashCode();
+ }
+ result = 31 * result + combinedHash;
+
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof GroupBuckets) {
+ return (this.buckets.containsAll(((GroupBuckets) obj).buckets) &&
+ ((GroupBuckets) obj).buckets.containsAll(this.buckets));
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("buckets", buckets.toString())
+ .toString();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupDescription.java
new file mode 100644
index 00000000..671b9a54
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupDescription.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+
+/**
+ * ONOS representation of group description that is used to create
+ * a group. It contains immutable properties of a ONOS group construct
+ * such as "type", "DeviceId", "appCookie", "appId" and "buckets"
+ */
+public interface GroupDescription {
+ /**
+ * Types of the group supported by ONOS.
+ */
+ enum Type {
+ /**
+ * Load-balancing among different buckets in a group.
+ */
+ SELECT,
+ /**
+ * Single Bucket Group.
+ */
+ INDIRECT,
+ /**
+ * Multicast to all buckets in a group.
+ */
+ ALL,
+ /**
+ * Uses the first live bucket in a group.
+ */
+ FAILOVER
+ }
+
+ /**
+ * Returns type of a group object.
+ *
+ * @return GroupType group type
+ */
+ Type type();
+
+ /**
+ * Returns device identifier on which this group object is created.
+ *
+ * @return DeviceId device identifier
+ */
+ DeviceId deviceId();
+
+ /**
+ * Returns application identifier that has created this group object.
+ *
+ * @return ApplicationId application identifier
+ */
+ ApplicationId appId();
+
+ /**
+ * Returns application cookie associated with a group object.
+ *
+ * @return GroupKey application cookie
+ */
+ GroupKey appCookie();
+
+ /**
+ * Returns groupId passed in by caller.
+ *
+ * @return Integer group id passed in by caller. May be null if caller
+ * passed in null to let groupService determin the group id.
+ */
+ Integer givenGroupId();
+
+ /**
+ * Returns group buckets of a group.
+ *
+ * @return GroupBuckets immutable list of group bucket
+ */
+ GroupBuckets buckets();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupEvent.java
new file mode 100644
index 00000000..45fbb3ed
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupEvent.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes group events.
+ */
+public class GroupEvent extends AbstractEvent<GroupEvent.Type, Group> {
+
+ /**
+ * Type of flow rule events.
+ */
+ public enum Type {
+ /**
+ * Signifies that a new Group has been detected.
+ */
+ GROUP_ADDED,
+
+ /**
+ * Signifies that a Group has been removed.
+ */
+ GROUP_REMOVED,
+
+ /**
+ * Signifies that a Group has been updated.
+ */
+ GROUP_UPDATED,
+
+ /**
+ * Signifies that a request to create Group has failed.
+ */
+ GROUP_ADD_FAILED,
+
+ /**
+ * Signifies that a request to remove Group has failed.
+ */
+ GROUP_REMOVE_FAILED,
+
+ /**
+ * Signifies that a request to update Group has failed.
+ */
+ GROUP_UPDATE_FAILED,
+
+ // internal event between Manager <-> Store
+
+ /*
+ * Signifies that a request to create Group has been added to the store.
+ */
+ GROUP_ADD_REQUESTED,
+ /*
+ * Signifies that a request to update Group has been added to the store.
+ */
+ GROUP_UPDATE_REQUESTED,
+ /*
+ * Signifies that a request to delete Group has been added to the store.
+ */
+ GROUP_REMOVE_REQUESTED,
+
+
+ }
+
+ /**
+ * Creates an event of a given type and for the specified Group and the
+ * current time.
+ *
+ * @param type Group event type
+ * @param group event subject
+ */
+ public GroupEvent(Type type, Group group) {
+ super(type, group);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified Group and time.
+ *
+ * @param type Group event type
+ * @param group event subject
+ * @param time occurrence time
+ */
+ public GroupEvent(Type type, Group group, long time) {
+ super(type, group, time);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupKey.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupKey.java
new file mode 100644
index 00000000..a63bee27
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupKey.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+/**
+ * Representation of generalized Key that would be used to store
+ * groups in &lt; Key, Value &gt; store. This key uses a generic
+ * byte array so that applications can associate their groups with
+ * any of their data by translating it into a byte array.
+ */
+public interface GroupKey {
+ /**
+ * Returns the byte representation of key.
+ *
+ * @return byte array
+ */
+ byte[] key();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupListener.java
new file mode 100644
index 00000000..349ce6a7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving Group related events.
+ */
+public interface GroupListener extends EventListener<GroupEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupOperation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupOperation.java
new file mode 100644
index 00000000..e4173b30
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupOperation.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+import org.onosproject.core.GroupId;
+
+/**
+ * Group operation definition to be used between core and provider
+ * layers of group subsystem.
+ *
+ */
+public final class GroupOperation {
+ private final Type opType;
+ private final GroupId groupId;
+ private final GroupDescription.Type groupType;
+ private final GroupBuckets buckets;
+
+ public enum Type {
+ /**
+ * Create a group in a device with the specified parameters.
+ */
+ ADD,
+ /**
+ * Modify a group in a device with the specified parameters.
+ */
+ MODIFY,
+ /**
+ * Delete a specified group.
+ */
+ DELETE
+ }
+
+ /**
+ * Group operation constructor with the parameters.
+ *
+ * @param opType group operation type
+ * @param groupId group Identifier
+ * @param groupType type of the group
+ * @param buckets immutable list of group buckets to be part of group
+ */
+ private GroupOperation(Type opType,
+ GroupId groupId,
+ GroupDescription.Type groupType,
+ GroupBuckets buckets) {
+ this.opType = checkNotNull(opType);
+ this.groupId = checkNotNull(groupId);
+ this.groupType = checkNotNull(groupType);
+ this.buckets = buckets;
+ }
+
+ /**
+ * Creates ADD group operation object.
+ *
+ * @param groupId group Identifier
+ * @param groupType type of the group
+ * @param buckets immutable list of group buckets to be part of group
+ * @return add group operation object
+ */
+ public static GroupOperation createAddGroupOperation(GroupId groupId,
+ GroupDescription.Type groupType,
+ GroupBuckets buckets) {
+ checkNotNull(buckets);
+ return new GroupOperation(Type.ADD, groupId, groupType, buckets);
+ }
+
+ /**
+ * Creates MODIFY group operation object.
+ *
+ * @param groupId group Identifier
+ * @param groupType type of the group
+ * @param buckets immutable list of group buckets to be part of group
+ * @return modify group operation object
+ */
+ public static GroupOperation createModifyGroupOperation(GroupId groupId,
+ GroupDescription.Type groupType,
+ GroupBuckets buckets) {
+ checkNotNull(buckets);
+ return new GroupOperation(Type.MODIFY, groupId, groupType, buckets);
+
+ }
+
+ /**
+ * Creates DELETE group operation object.
+ *
+ * @param groupId group Identifier
+ * @param groupType type of the group
+ * @return delete group operation object
+ */
+ public static GroupOperation createDeleteGroupOperation(GroupId groupId,
+ GroupDescription.Type groupType) {
+ return new GroupOperation(Type.DELETE, groupId, groupType, null);
+
+ }
+
+ /**
+ * Returns group operation type.
+ *
+ * @return GroupOpType group operation type
+ */
+ public Type opType() {
+ return this.opType;
+ }
+
+ /**
+ * Returns group identifier attribute of the operation.
+ *
+ * @return GroupId group identifier
+ */
+ public GroupId groupId() {
+ return this.groupId;
+ }
+
+ /**
+ * Returns group type attribute of the operation.
+ *
+ * @return GroupType group type
+ */
+ public GroupDescription.Type groupType() {
+ return this.groupType;
+ }
+
+ /**
+ * Returns group buckets associated with the operation.
+ *
+ * @return GroupBuckets group buckets
+ */
+ public GroupBuckets buckets() {
+ return this.buckets;
+ }
+
+ @Override
+ /*
+ * The deviceId, type and buckets are used for hash.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public int hashCode() {
+ return (buckets != null) ? Objects.hash(groupId, opType, buckets) :
+ Objects.hash(groupId, opType);
+ }
+
+ @Override
+ /*
+ * The deviceId, type and buckets should be same.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof GroupOperation) {
+ GroupOperation that = (GroupOperation) obj;
+ return Objects.equals(groupId, that.groupId) &&
+ Objects.equals(groupType, that.groupType) &&
+ Objects.equals(opType, that.opType) &&
+ Objects.equals(buckets, that.buckets);
+
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupOperations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupOperations.java
new file mode 100644
index 00000000..bc03628d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupOperations.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Immutable collection of group operation to be used between
+ * core and provider layers of group subsystem.
+ *
+ */
+public final class GroupOperations {
+ private final List<GroupOperation> operations;
+
+ /**
+ * Creates a immutable list of group operation.
+ *
+ * @param operations list of group operation
+ */
+ public GroupOperations(List<GroupOperation> operations) {
+ this.operations = ImmutableList.copyOf(checkNotNull(operations));
+ }
+
+ /**
+ * Returns immutable list of group operation.
+ *
+ * @return list of group operation
+ */
+ public List<GroupOperation> operations() {
+ return operations;
+ }
+
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProvider.java
new file mode 100644
index 00000000..6757e669
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProvider.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Abstraction of group provider.
+ */
+public interface GroupProvider extends Provider {
+
+ /**
+ * Performs a batch of group operation in the specified device with the
+ * specified parameters.
+ *
+ * @param deviceId device identifier on which the batch of group
+ * operations to be executed
+ * @param groupOps immutable list of group operation
+ */
+ void performGroupOperation(DeviceId deviceId,
+ GroupOperations groupOps);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProviderRegistry.java
new file mode 100644
index 00000000..d45789db
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction for a group provider registry.
+ */
+public interface GroupProviderRegistry
+ extends ProviderRegistry<GroupProvider, GroupProviderService> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProviderService.java
new file mode 100644
index 00000000..076de498
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupProviderService.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import java.util.Collection;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.ProviderService;
+
+/**
+ * Service through which Group providers can inject information into
+ * the core.
+ */
+public interface GroupProviderService extends ProviderService<GroupProvider> {
+
+ /**
+ * Notifies core if any failure from data plane during group operations.
+ *
+ * @param deviceId the device ID
+ * @param operation offended group operation
+ */
+ void groupOperationFailed(DeviceId deviceId, GroupOperation operation);
+
+ /**
+ * Pushes the collection of group detected in the data plane along
+ * with statistics.
+ *
+ * @param deviceId device identifier
+ * @param groupEntries collection of group entries as seen in data plane
+ */
+ void pushGroupMetrics(DeviceId deviceId,
+ Collection<Group> groupEntries);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupService.java
new file mode 100644
index 00000000..4163248f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupService.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Service for create/update/delete "group" in the devices.
+ * Flow entries can point to a "group" defined in the devices that enables
+ * to represent additional methods of forwarding like load-balancing or
+ * failover among different group of ports or multicast to all ports
+ * specified in a group.
+ * "group" can also be used for grouping common actions of different flows,
+ * so that in some scenarios only one group entry required to be modified
+ * for all the referencing flow entries instead of modifying all of them.
+ *
+ * This implements semantics of a distributed authoritative group store
+ * where the master copy of the groups lies with the controller and
+ * the devices hold only the 'cached' copy.
+ */
+public interface GroupService
+ extends ListenerService<GroupEvent, GroupListener> {
+
+ /**
+ * Creates a group in the specified device with the provided buckets.
+ * This API provides an option for application to associate a cookie
+ * while creating a group, so that applications can look-up the
+ * groups based on the cookies. These Groups will be retained by
+ * the core system and re-applied if any groups found missing in the
+ * device when it reconnects. This API would immediately return after
+ * submitting the request locally or to a remote Master controller
+ * instance. As a response to this API invocation, GROUP_ADDED or
+ * GROUP_ADD_FAILED notifications would be provided along with cookie
+ * depending on the result of the operation on the device in the
+ * data plane. The caller may also use "getGroup" API to get the
+ * Group object created as part of this request.
+ *
+ * @param groupDesc group creation parameters
+ *
+ */
+ void addGroup(GroupDescription groupDesc);
+
+ /**
+ * Returns a group object associated to an application cookie.
+ *
+ * NOTE1: The presence of group object in the system does not
+ * guarantee that the "group" is actually created in device.
+ * GROUP_ADDED notification would confirm the creation of
+ * this group in data plane.
+ *
+ * @param deviceId device identifier
+ * @param appCookie application cookie to be used for lookup
+ * @return group associated with the application cookie or
+ * NULL if Group is not found for the provided cookie
+ */
+ Group getGroup(DeviceId deviceId, GroupKey appCookie);
+
+ /**
+ * Appends buckets to existing group. The caller can optionally
+ * associate a new cookie during this updation. GROUP_UPDATED or
+ * GROUP_UPDATE_FAILED notifications would be provided along with
+ * cookie depending on the result of the operation on the device.
+ *
+ * @param deviceId device identifier
+ * @param oldCookie cookie to be used to retrieve the existing group
+ * @param buckets immutable list of group bucket to be added
+ * @param newCookie immutable cookie to be used post update operation
+ * @param appId Application Id
+ */
+ void addBucketsToGroup(DeviceId deviceId,
+ GroupKey oldCookie,
+ GroupBuckets buckets,
+ GroupKey newCookie,
+ ApplicationId appId);
+
+ /**
+ * Removes buckets from existing group. The caller can optionally
+ * associate a new cookie during this updation. GROUP_UPDATED or
+ * GROUP_UPDATE_FAILED notifications would be provided along with
+ * cookie depending on the result of the operation on the device.
+ *
+ * @param deviceId device identifier
+ * @param oldCookie cookie to be used to retrieve the existing group
+ * @param buckets immutable list of group bucket to be removed
+ * @param newCookie immutable cookie to be used post update operation
+ * @param appId Application Id
+ */
+ void removeBucketsFromGroup(DeviceId deviceId,
+ GroupKey oldCookie,
+ GroupBuckets buckets,
+ GroupKey newCookie,
+ ApplicationId appId);
+
+ /**
+ * Deletes a group associated to an application cookie.
+ * GROUP_DELETED or GROUP_DELETE_FAILED notifications would be
+ * provided along with cookie depending on the result of the
+ * operation on the device.
+ *
+ * @param deviceId device identifier
+ * @param appCookie application cookie to be used for lookup
+ * @param appId Application Id
+ */
+ void removeGroup(DeviceId deviceId, GroupKey appCookie, ApplicationId appId);
+
+ /**
+ * Retrieves all groups created by an application in the specified device
+ * as seen by current controller instance.
+ *
+ * @param deviceId device identifier
+ * @param appId application id
+ * @return collection of immutable group objects created by the application
+ */
+ Iterable<Group> getGroups(DeviceId deviceId, ApplicationId appId);
+
+ /**
+ * Returns all groups associated with the given device.
+ *
+ * @param deviceId device ID to get groups for
+ * @return iterable of device's groups
+ */
+ Iterable<Group> getGroups(DeviceId deviceId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupStore.java
new file mode 100644
index 00000000..8b6df5d9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupStore.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import java.util.Collection;
+
+import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.Store;
+
+/**
+ * Manages inventory of groups per device; not intended for direct use.
+ */
+public interface GroupStore extends Store<GroupEvent, GroupStoreDelegate> {
+
+ enum UpdateType {
+ /**
+ * Modify existing group entry by adding provided information.
+ */
+ ADD,
+ /**
+ * Modify existing group by removing provided information from it.
+ */
+ REMOVE
+ }
+
+ /**
+ * Returns the number of groups for the specified device in the store.
+ *
+ * @param deviceId the device ID
+ * @return number of groups for the specified device
+ */
+ int getGroupCount(DeviceId deviceId);
+
+ /**
+ * Returns the groups associated with a device.
+ *
+ * @param deviceId the device ID
+ * @return the group entries
+ */
+ Iterable<Group> getGroups(DeviceId deviceId);
+
+ /**
+ * Returns the stored group entry.
+ *
+ * @param deviceId the device ID
+ * @param appCookie the group key
+ * @return a group associated with the key
+ */
+ Group getGroup(DeviceId deviceId, GroupKey appCookie);
+
+ /**
+ * Returns the stored group entry for an id.
+ *
+ * @param deviceId the device ID
+ * @param groupId the group identifier
+ * @return a group associated with the key
+ */
+ Group getGroup(DeviceId deviceId, GroupId groupId);
+
+ /**
+ * Stores a new group entry using the information from group description.
+ *
+ * @param groupDesc group description to be used to store group entry
+ */
+ void storeGroupDescription(GroupDescription groupDesc);
+
+ /**
+ * Updates the existing group entry with the information
+ * from group description.
+ *
+ * @param deviceId the device ID
+ * @param oldAppCookie the current group key
+ * @param type update type
+ * @param newBuckets group buckets for updates
+ * @param newAppCookie optional new group key
+ */
+ void updateGroupDescription(DeviceId deviceId,
+ GroupKey oldAppCookie,
+ UpdateType type,
+ GroupBuckets newBuckets,
+ GroupKey newAppCookie);
+
+ /**
+ * Triggers deleting the existing group entry.
+ *
+ * @param deviceId the device ID
+ * @param appCookie the group key
+ */
+ void deleteGroupDescription(DeviceId deviceId,
+ GroupKey appCookie);
+
+ /**
+ * Stores a new group entry, or updates an existing entry.
+ *
+ * @param group group entry
+ */
+ void addOrUpdateGroupEntry(Group group);
+
+ /**
+ * Removes the group entry from store.
+ *
+ * @param group group entry
+ */
+ void removeGroupEntry(Group group);
+
+ /**
+ * A group entry that is present in switch but not in the store.
+ *
+ * @param group group entry
+ */
+ void addOrUpdateExtraneousGroupEntry(Group group);
+
+ /**
+ * Remove the group entry from extraneous database.
+ *
+ * @param group group entry
+ */
+ void removeExtraneousGroupEntry(Group group);
+
+ /**
+ * Returns the extraneous groups associated with a device.
+ *
+ * @param deviceId the device ID
+ *
+ * @return the extraneous group entries
+ */
+ Iterable<Group> getExtraneousGroups(DeviceId deviceId);
+
+ /**
+ * Indicates the first group audit is completed.
+ *
+ * @param deviceId the device ID
+ * @param completed initial audit status
+ */
+ void deviceInitialAuditCompleted(DeviceId deviceId, boolean completed);
+
+ /**
+ * Retrieves the initial group audit status for a device.
+ *
+ * @param deviceId the device ID
+ *
+ * @return initial group audit status
+ */
+ boolean deviceInitialAuditStatus(DeviceId deviceId);
+
+ /**
+ * Indicates the group operations failed.
+ *
+ * @param deviceId the device ID
+ * @param operation the group operation failed
+ */
+ void groupOperationFailed(DeviceId deviceId, GroupOperation operation);
+
+ /**
+ * Submits the group metrics to store for a given device ID.
+ *
+ * @param deviceId the device ID
+ * @param groupEntries the group entries as received from southbound
+ */
+ void pushGroupMetrics(DeviceId deviceId, Collection<Group> groupEntries);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupStoreDelegate.java
new file mode 100644
index 00000000..308ebb1c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/GroupStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Group store delegate abstraction.
+ */
+public interface GroupStoreDelegate extends StoreDelegate<GroupEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/StoredGroupBucketEntry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/StoredGroupBucketEntry.java
new file mode 100644
index 00000000..131875b3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/StoredGroupBucketEntry.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+/**
+ * Generic group bucket entry representation that is stored in a
+ * group object. A group bucket entry provides additional info of
+ * group bucket like statistics...etc
+ */
+public interface StoredGroupBucketEntry extends GroupBucket {
+ /**
+ * Sets number of packets processed by this group bucket entry.
+ *
+ * @param packets a long value
+ */
+ void setPackets(long packets);
+
+ /**
+ * Sets number of bytes processed by this group bucket entry.
+ *
+ * @param bytes a long value
+ */
+ void setBytes(long bytes);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/StoredGroupEntry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/StoredGroupEntry.java
new file mode 100644
index 00000000..47d36122
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/StoredGroupEntry.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+/**
+ * Interface that defines set methods for a group entry
+ * that is stored in the system.
+ */
+public interface StoredGroupEntry extends Group {
+
+ /**
+ * Sets the new state for this entry.
+ *
+ * @param newState new group entry state.
+ */
+ void setState(Group.GroupState newState);
+
+ /**
+ * Sets if group has transitioned to ADDED state for the first time.
+ * This is to differentiate state transitions "from PENDING_ADD to ADDED"
+ * and "from PENDING_UPDATE to ADDED". For internal use only.
+ *
+ * @param isGroupAddedFirstTime true if group moves to ADDED state
+ * for the first time.
+ */
+ void setIsGroupStateAddedFirstTime(boolean isGroupAddedFirstTime);
+
+ /**
+ * Returns the isGroupStateAddedFirstTime value. For internal use only.
+ *
+ * @return isGroupStateAddedFirstTime value
+ */
+ boolean isGroupStateAddedFirstTime();
+
+ /**
+ * Sets how long this entry has been entered in the system.
+ *
+ * @param life epoch time
+ */
+ void setLife(long life);
+
+ /**
+ * Sets number of packets processed by this group entry.
+ *
+ * @param packets a long value
+ */
+ void setPackets(long packets);
+
+ /**
+ * Sets number of bytes processed by this group entry.
+ *
+ * @param bytes a long value
+ */
+ void setBytes(long bytes);
+
+ /**
+ * Sets number of flow rules or groups referencing this group entry.
+ *
+ * @param referenceCount reference count
+ */
+ void setReferenceCount(long referenceCount);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/package-info.java
new file mode 100644
index 00000000..26528c48
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Abstractions for interacting with device port groups.
+ */
+package org.onosproject.net.group; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java
new file mode 100644
index 00000000..1f05197a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.onosproject.net.AbstractDescription;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.SparseAnnotations;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+
+import com.google.common.collect.ImmutableSet;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of an immutable host description.
+ */
+public class DefaultHostDescription extends AbstractDescription
+ implements HostDescription {
+
+ private final MacAddress mac;
+ private final VlanId vlan;
+ private final HostLocation location;
+ private final Set<IpAddress> ip;
+
+ /**
+ * Creates a host description using the supplied information.
+ *
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @param location host location
+ * @param annotations optional key/value annotations map
+ */
+ public DefaultHostDescription(MacAddress mac, VlanId vlan,
+ HostLocation location,
+ SparseAnnotations... annotations) {
+ this(mac, vlan, location, Collections.<IpAddress>emptySet(),
+ annotations);
+ }
+
+ /**
+ * Creates a host description using the supplied information.
+ *
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @param location host location
+ * @param ip host IP address
+ * @param annotations optional key/value annotations map
+ */
+ public DefaultHostDescription(MacAddress mac, VlanId vlan,
+ HostLocation location, IpAddress ip,
+ SparseAnnotations... annotations) {
+ this(mac, vlan, location, ImmutableSet.of(ip), annotations);
+ }
+
+ /**
+ * Creates a host description using the supplied information.
+ *
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @param location host location
+ * @param ip host IP addresses
+ * @param annotations optional key/value annotations map
+ */
+ public DefaultHostDescription(MacAddress mac, VlanId vlan,
+ HostLocation location, Set<IpAddress> ip,
+ SparseAnnotations... annotations) {
+ super(annotations);
+ this.mac = mac;
+ this.vlan = vlan;
+ this.location = location;
+ this.ip = ImmutableSet.copyOf(ip);
+ }
+
+ @Override
+ public MacAddress hwAddress() {
+ return mac;
+ }
+
+ @Override
+ public VlanId vlan() {
+ return vlan;
+ }
+
+ @Override
+ public HostLocation location() {
+ return location;
+ }
+
+ @Override
+ public Set<IpAddress> ipAddress() {
+ return ip;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("mac", mac)
+ .add("vlan", vlan)
+ .add("location", location)
+ .add("ipAddress", ip)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostAdminService.java
new file mode 100644
index 00000000..d620fedb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostAdminService.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.HostId;
+
+/**
+ * Service for administering the inventory of end-station hosts.
+ */
+public interface HostAdminService extends HostService {
+
+ /**
+ * Removes the end-station host with the specified identifier.
+ *
+ * @param hostId host identifier
+ */
+ void removeHost(HostId hostId);
+
+ /**
+ * Binds IP and MAC addresses to the given connection point.
+ * <p>
+ * The addresses are added to the set of addresses already bound to the
+ * connection point.
+ *
+ * @param addresses address object containing addresses to add and the port
+ * to add them to
+ * @deprecated in Drake release: address info now stored in InterfaceService
+ */
+ @Deprecated
+ void bindAddressesToPort(PortAddresses addresses);
+
+ /**
+ * Removes the addresses contained in the given PortAddresses object from
+ * the set of addresses bound to the port.
+ *
+ * @param portAddresses set of addresses to remove and port to remove them
+ * from
+ * @deprecated in Drake release: address info now stored in InterfaceService
+ */
+ @Deprecated
+ void unbindAddressesFromPort(PortAddresses portAddresses);
+
+ /**
+ * Removes all address information for the given connection point.
+ *
+ * @param connectPoint the connection point to remove address information
+ * @deprecated in Drake release: address info now stored in InterfaceService
+ */
+ @Deprecated
+ void clearAddresses(ConnectPoint connectPoint);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostDescription.java
new file mode 100644
index 00000000..14c6f7ad
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostDescription.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import java.util.Set;
+
+import org.onosproject.net.Description;
+import org.onosproject.net.HostLocation;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+
+/**
+ * Information describing host and its location.
+ */
+public interface HostDescription extends Description {
+
+ /**
+ * Returns the MAC address associated with this host (NIC).
+ *
+ * @return the MAC address of this host
+ */
+ MacAddress hwAddress();
+
+ /**
+ * Returns the VLAN associated with this host.
+ *
+ * @return the VLAN ID value
+ */
+ VlanId vlan();
+
+ /**
+ * Returns the location of the host on the network edge.
+ *
+ * @return the network location
+ */
+ HostLocation location();
+
+ /**
+ * Returns the IP address associated with this host's MAC.
+ *
+ * @return host IP address
+ */
+ Set<IpAddress> ipAddress();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostEvent.java
new file mode 100644
index 00000000..98329df0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostEvent.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.Host;
+
+/**
+ * Describes end-station host event.
+ */
+public class HostEvent extends AbstractEvent<HostEvent.Type, Host> {
+
+ /**
+ * Type of host events.
+ */
+ public enum Type {
+ /**
+ * Signifies that a new host has been detected.
+ */
+ HOST_ADDED,
+
+ /**
+ * Signifies that a host has been removed.
+ */
+ HOST_REMOVED,
+
+ /**
+ * Signifies that host data changed, e.g. IP address
+ */
+ HOST_UPDATED,
+
+ /**
+ * Signifies that a host location has changed.
+ */
+ HOST_MOVED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified host and the
+ * current time.
+ *
+ * @param type host event type
+ * @param host event host subject
+ */
+ public HostEvent(Type type, Host host) {
+ super(type, host);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified host and time.
+ *
+ * @param type host event type
+ * @param host event host subject
+ * @param time occurrence time
+ */
+ public HostEvent(Type type, Host host, long time) {
+ super(type, host, time);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostListener.java
new file mode 100644
index 00000000..2eef7592
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving end-station host related events.
+ */
+public interface HostListener extends EventListener<HostEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProvider.java
new file mode 100644
index 00000000..0270996b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProvider.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onosproject.net.Host;
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Provider of information about hosts and their location on the network.
+ */
+public interface HostProvider extends Provider {
+
+ /**
+ * Triggers an asynchronous probe of the specified host, intended to
+ * determine whether the host is present or not. An indirect result of this
+ * should be invocation of {@link org.onosproject.net.host.HostProviderService#hostDetected}
+ * or {@link org.onosproject.net.host.HostProviderService#hostVanished}
+ * at some later point in time.
+ *
+ * @param host host to probe
+ */
+ void triggerProbe(Host host);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProviderRegistry.java
new file mode 100644
index 00000000..8ab600c2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction of a host provider registry.
+ */
+public interface HostProviderRegistry
+ extends ProviderRegistry<HostProvider, HostProviderService> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProviderService.java
new file mode 100644
index 00000000..8678a297
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostProviderService.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onosproject.net.HostId;
+import org.onosproject.net.provider.ProviderService;
+
+/**
+ * Means of conveying host information to the core.
+ */
+public interface HostProviderService extends ProviderService<HostProvider> {
+
+ /**
+ * Notifies the core when a host has been detected on a network along with
+ * information that identifies the host location.
+ *
+ * @param hostId id of the host that been detected
+ * @param hostDescription description of host and its location
+ */
+ void hostDetected(HostId hostId, HostDescription hostDescription);
+
+ /**
+ * Notifies the core when a host is no longer detected on a network.
+ *
+ * @param hostId id of the host that vanished
+ */
+ void hostVanished(HostId hostId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostService.java
new file mode 100644
index 00000000..be114f05
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostService.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+
+import java.util.Set;
+
+/**
+ * Service for interacting with the inventory of end-station hosts.
+ */
+public interface HostService
+ extends ListenerService<HostEvent, HostListener> {
+
+ /**
+ * Returns the number of end-station hosts known to the system.
+ *
+ * @return number of end-station hosts
+ */
+ int getHostCount();
+
+ /**
+ * Returns a collection of all end-station hosts.
+ *
+ * @return collection of hosts
+ */
+ Iterable<Host> getHosts();
+
+ /**
+ * Returns the host with the specified identifier.
+ *
+ * @param hostId host identifier
+ * @return host or null if one with the given identifier is not known
+ */
+ Host getHost(HostId hostId);
+
+ /**
+ * Returns the set of hosts that belong to the specified VLAN.
+ *
+ * @param vlanId vlan identifier
+ * @return set of hosts in the given vlan id
+ */
+ Set<Host> getHostsByVlan(VlanId vlanId);
+
+ /**
+ * Returns the set of hosts that have the specified MAC address.
+ *
+ * @param mac mac address
+ * @return set of hosts with the given mac
+ */
+ Set<Host> getHostsByMac(MacAddress mac);
+
+ /**
+ * Returns the set of hosts that have the specified IP address.
+ *
+ * @param ip ip address
+ * @return set of hosts with the given IP
+ */
+ Set<Host> getHostsByIp(IpAddress ip);
+
+ // TODO: consider adding Host getHostByIp(IpAddress ip, VlanId vlan);
+
+ /**
+ * Returns the set of hosts whose most recent location is the specified
+ * connection point.
+ *
+ * @param connectPoint connection point
+ * @return set of hosts connected to the connection point
+ */
+ Set<Host> getConnectedHosts(ConnectPoint connectPoint);
+
+ /**
+ * Returns the set of hosts whose most recent location is the specified
+ * infrastructure device.
+ *
+ * @param deviceId device identifier
+ * @return set of hosts connected to the device
+ */
+ Set<Host> getConnectedHosts(DeviceId deviceId);
+
+ /**
+ * Requests the host service to monitor hosts with the given IP address and
+ * notify listeners of changes.
+ *
+ * @param ip IP address of the host to monitor
+ */
+ void startMonitoringIp(IpAddress ip);
+
+ /**
+ * Stops the host service from monitoring an IP address.
+ *
+ * @param ip IP address to stop monitoring
+ */
+ // TODO clients can cancel other client's requests
+ void stopMonitoringIp(IpAddress ip);
+
+ /**
+ * Requests the host service to resolve the MAC address for the given IP
+ * address. This will trigger a notification to the host listeners if the MAC
+ * address is found.
+ *
+ * @param ip IP address to find the MAC address for
+ */
+ void requestMac(IpAddress ip);
+
+ /**
+ * Returns the addresses information for all connection points.
+ *
+ * @return the set of address bindings for all connection points
+ * @deprecated in Drake release: use InterfaceService instead
+ */
+ @Deprecated
+ Set<PortAddresses> getAddressBindings();
+
+ /**
+ * Retrieves the addresses that have been bound to the given connection
+ * point.
+ *
+ * @param connectPoint the connection point to retrieve address bindings for
+ * @return addresses bound to the port
+ * @deprecated in Drake release: use InterfaceService instead
+ */
+ @Deprecated
+ Set<PortAddresses> getAddressBindingsForPort(ConnectPoint connectPoint);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostStore.java
new file mode 100644
index 00000000..ca11a942
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostStore.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.store.Store;
+
+import java.util.Set;
+
+/**
+ * Manages inventory of end-station hosts; not intended for direct use.
+ */
+public interface HostStore extends Store<HostEvent, HostStoreDelegate> {
+
+ /**
+ * Creates a new host or updates the existing one based on the specified
+ * description.
+ *
+ * @param providerId provider identification
+ * @param hostId host identification
+ * @param hostDescription host description data
+ * @return appropriate event or null if no change resulted
+ */
+ HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
+ HostDescription hostDescription);
+
+ // FIXME: API to remove only IpAddress is missing
+ /**
+ * Removes the specified host from the inventory.
+ *
+ * @param hostId host identification
+ * @return remove event or null if host was not found
+ */
+ HostEvent removeHost(HostId hostId);
+
+ /**
+ * Returns the number of hosts in the store.
+ *
+ * @return host count
+ */
+ int getHostCount();
+
+ /**
+ * Returns a collection of all hosts in the store.
+ *
+ * @return iterable collection of all hosts
+ */
+ Iterable<Host> getHosts();
+
+ /**
+ * Returns the host with the specified identifer.
+ *
+ * @param hostId host identification
+ * @return host or null if not found
+ */
+ Host getHost(HostId hostId);
+
+ /**
+ * Returns the set of all hosts within the specified VLAN.
+ *
+ * @param vlanId vlan id
+ * @return set of hosts in the vlan
+ */
+ Set<Host> getHosts(VlanId vlanId);
+
+ /**
+ * Returns the set of hosts with the specified MAC address.
+ *
+ * @param mac mac address
+ * @return set of hosts with the given mac
+ */
+ Set<Host> getHosts(MacAddress mac);
+
+ /**
+ * Returns the set of hosts with the specified IP address.
+ *
+ * @param ip ip address
+ * @return set of hosts with the given IP
+ */
+ Set<Host> getHosts(IpAddress ip);
+
+ /**
+ * Returns the set of hosts whose location falls on the given connection point.
+ *
+ * @param connectPoint connection point
+ * @return set of hosts
+ */
+ Set<Host> getConnectedHosts(ConnectPoint connectPoint);
+
+ /**
+ * Returns the set of hosts whose location falls on the given device.
+ *
+ * @param deviceId infrastructure device identifier
+ * @return set of hosts
+ */
+ Set<Host> getConnectedHosts(DeviceId deviceId);
+
+ /**
+ * Updates the address information for a given port. The given address
+ * information is added to any previously held information for the port.
+ *
+ * @param addresses the port and address information
+ * @deprecated in Drake release: address info now stored in InterfaceService
+ */
+ @Deprecated
+ void updateAddressBindings(PortAddresses addresses);
+
+ /**
+ * Removes the given addresses from the set of address information held for
+ * a port.
+ *
+ * @param addresses the port and address information
+ * @deprecated in Drake release: address info now stored in InterfaceService
+ */
+ @Deprecated
+ void removeAddressBindings(PortAddresses addresses);
+
+ /**
+ * Removes any previously stored address information for a given connection
+ * point.
+ *
+ * @param connectPoint the connection point
+ * @deprecated in Drake release: address info now stored in InterfaceService
+ */
+ @Deprecated
+ void clearAddressBindings(ConnectPoint connectPoint);
+
+ /**
+ * Returns the address bindings stored for all connection points.
+ *
+ * @return the set of address bindings
+ * @deprecated in Drake release: address info now stored in InterfaceService
+ */
+ @Deprecated
+ Set<PortAddresses> getAddressBindings();
+
+ /**
+ * Returns the address bindings for a particular connection point.
+ *
+ * @param connectPoint the connection point to return address information
+ * for
+ * @return address information for the connection point
+ * @deprecated in Drake release: address info now stored in InterfaceService
+ */
+ @Deprecated
+ Set<PortAddresses> getAddressBindingsForPort(ConnectPoint connectPoint);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostStoreDelegate.java
new file mode 100644
index 00000000..efc84232
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Infrastructure link store delegate abstraction.
+ */
+public interface HostStoreDelegate extends StoreDelegate<HostEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/InterfaceIpAddress.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/InterfaceIpAddress.java
new file mode 100644
index 00000000..2f53df50
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/InterfaceIpAddress.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Represents a single IP address information on an interface.
+ *
+ * TODO:
+ * - Add computation for the default broadcast address if it is not
+ * specified
+ * - Add explicit checks that each IP address or prefix belong to the
+ * same IP version: IPv4/IPv6.
+ * - Inside the copy constructor we should use copy constructors for each
+ * field
+ */
+public class InterfaceIpAddress {
+ private final IpAddress ipAddress;
+ private final IpPrefix subnetAddress;
+ private final IpAddress broadcastAddress;
+ private final IpAddress peerAddress;
+
+ /**
+ * Copy constructor.
+ *
+ * @param other the object to copy from
+ */
+ public InterfaceIpAddress(InterfaceIpAddress other) {
+ // TODO: we should use copy constructors for each field
+ this.ipAddress = other.ipAddress;
+ this.subnetAddress = other.subnetAddress;
+ this.broadcastAddress = other.broadcastAddress;
+ this.peerAddress = other.peerAddress;
+ }
+
+ /**
+ * Constructor for a given IP address and a subnet address.
+ *
+ * @param ipAddress the IP address
+ * @param subnetAddress the IP subnet address
+ */
+ public InterfaceIpAddress(IpAddress ipAddress, IpPrefix subnetAddress) {
+ this.ipAddress = checkNotNull(ipAddress);
+ this.subnetAddress = checkNotNull(subnetAddress);
+ // TODO: Recompute the default broadcast address from the subnet
+ // address
+ this.broadcastAddress = null;
+ this.peerAddress = null;
+ }
+
+ /**
+ * Constructor for a given IP address and a subnet address.
+ *
+ * @param ipAddress the IP address
+ * @param subnetAddress the IP subnet address
+ * @param broadcastAddress the IP broadcast address. It can be used
+ * to specify non-default broadcast address
+ */
+ public InterfaceIpAddress(IpAddress ipAddress, IpPrefix subnetAddress,
+ IpAddress broadcastAddress) {
+ this.ipAddress = checkNotNull(ipAddress);
+ this.subnetAddress = checkNotNull(subnetAddress);
+ this.broadcastAddress = broadcastAddress;
+ this.peerAddress = null;
+ }
+
+ /**
+ * Constructor for a given IP address and a subnet address.
+ *
+ * @param ipAddress the IP address
+ * @param subnetAddress the IP subnet address
+ * @param broadcastAddress the IP broadcast address. It can be used
+ * to specify non-default broadcast address. It should be null for
+ * point-to-point interfaces with a peer address
+ * @param peerAddress the peer IP address for point-to-point interfaces
+ */
+ public InterfaceIpAddress(IpAddress ipAddress, IpPrefix subnetAddress,
+ IpAddress broadcastAddress,
+ IpAddress peerAddress) {
+ this.ipAddress = checkNotNull(ipAddress);
+ this.subnetAddress = checkNotNull(subnetAddress);
+ this.broadcastAddress = broadcastAddress;
+ this.peerAddress = peerAddress;
+ }
+
+ /**
+ * Gets the IP address.
+ *
+ * @return the IP address
+ */
+ public IpAddress ipAddress() {
+ return ipAddress;
+ }
+
+ /**
+ * Gets the IP subnet address.
+ *
+ * @return the IP subnet address
+ */
+ public IpPrefix subnetAddress() {
+ return subnetAddress;
+ }
+
+ /**
+ * Gets the subnet IP broadcast address.
+ *
+ * @return the subnet IP broadcast address
+ */
+ public IpAddress broadcastAddress() {
+ return broadcastAddress;
+ }
+
+ /**
+ * Gets the IP point-to-point interface peer address.
+ *
+ * @return the IP point-to-point interface peer address
+ */
+ public IpAddress peerAddress() {
+ return peerAddress;
+ }
+
+ /**
+ * Converts a CIDR string literal to an interface IP address.
+ * E.g. 10.0.0.1/24
+ *
+ * @param value an IP address value in string form
+ * @return an interface IP address
+ * @throws IllegalArgumentException if the argument is invalid
+ */
+ public static InterfaceIpAddress valueOf(String value) {
+ String[] splits = value.split("/");
+ checkArgument(splits.length == 2, "Invalid IP address and prefix length format");
+
+ // NOTE: IpPrefix will mask-out the bits after the prefix length.
+ IpPrefix subnet = IpPrefix.valueOf(value);
+ IpAddress addr = IpAddress.valueOf(splits[0]);
+ return new InterfaceIpAddress(addr, subnet);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof InterfaceIpAddress)) {
+ return false;
+ }
+ InterfaceIpAddress otherAddr = (InterfaceIpAddress) other;
+
+ return Objects.equals(this.ipAddress, otherAddr.ipAddress)
+ && Objects.equals(this.subnetAddress, otherAddr.subnetAddress)
+ && Objects.equals(this.broadcastAddress,
+ otherAddr.broadcastAddress)
+ && Objects.equals(this.peerAddress, otherAddr.peerAddress);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ipAddress, subnetAddress, broadcastAddress,
+ peerAddress);
+ }
+
+ @Override
+ public String toString() {
+ /*return toStringHelper(this).add("ipAddress", ipAddress)
+ .add("subnetAddress", subnetAddress)
+ .add("broadcastAddress", broadcastAddress)
+ .add("peerAddress", peerAddress)
+ .omitNullValues().toString();*/
+ return ipAddress.toString() + "/" + subnetAddress.prefixLength();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/PortAddresses.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/PortAddresses.java
new file mode 100644
index 00000000..74f22ae9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/PortAddresses.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.host;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Represents address information bound to a port.
+ */
+public final class PortAddresses {
+
+ private final ConnectPoint connectPoint;
+ private final Set<InterfaceIpAddress> ipAddresses;
+ private final MacAddress macAddress;
+ private final VlanId vlan;
+
+ /**
+ * Constructs a PortAddresses object for the given connection point, with a
+ * set of IP addresses and a MAC address. Both address parameters are
+ * optional and can be set to null.
+ *
+ * @param connectPoint the connection point these addresses are for
+ * @param ipAddresses a set of interface IP addresses
+ * @param mac a MAC address
+ * @param vlan a VLAN ID
+ */
+ public PortAddresses(ConnectPoint connectPoint,
+ Set<InterfaceIpAddress> ipAddresses, MacAddress mac, VlanId vlan) {
+ this.connectPoint = connectPoint;
+ this.ipAddresses = (ipAddresses == null) ?
+ Collections.<InterfaceIpAddress>emptySet()
+ : new HashSet<>(ipAddresses);
+ this.macAddress = mac;
+ this.vlan = vlan;
+ }
+
+ /**
+ * Returns the connection point this address information is bound to.
+ *
+ * @return the connection point
+ */
+ public ConnectPoint connectPoint() {
+ return connectPoint;
+ }
+
+ /**
+ * Returns the set of interface IP addresses.
+ *
+ * @return the interface IP addresses
+ */
+ public Set<InterfaceIpAddress> ipAddresses() {
+ return ipAddresses;
+ }
+
+ /**
+ * Returns the MAC address.
+ *
+ * @return the MAC address
+ */
+ public MacAddress mac() {
+ return macAddress;
+ }
+
+ /**
+ * Returns the VLAN ID.
+ *
+ * @return the VLAN ID
+ */
+ public VlanId vlan() {
+ return vlan;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof PortAddresses)) {
+ return false;
+ }
+
+ PortAddresses otherPa = (PortAddresses) other;
+
+ return Objects.equals(this.connectPoint, otherPa.connectPoint)
+ && Objects.equals(this.ipAddresses, otherPa.ipAddresses)
+ && Objects.equals(this.macAddress, otherPa.macAddress)
+ && Objects.equals(this.vlan, otherPa.vlan);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(connectPoint, ipAddresses, macAddress, vlan);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("connect-point", connectPoint)
+ .add("ip-addresses", ipAddresses)
+ .add("mac-address", macAddress)
+ .add("vlan", vlan)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/package-info.java
new file mode 100644
index 00000000..4f2bc7c4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * End-station host model &amp; related services API definitions.
+ */
+package org.onosproject.net.host;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/ConnectivityIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/ConnectivityIntent.java
new file mode 100644
index 00000000..7caee3e8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/ConnectivityIntent.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.Link;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of connectivity intent for traffic matching some criteria.
+ */
+@Beta
+public abstract class ConnectivityIntent extends Intent {
+
+ // TODO: other forms of intents should be considered for this family:
+ // point-to-point with constraints (waypoints/obstacles)
+ // multi-to-single point with constraints (waypoints/obstacles)
+ // single-to-multi point with constraints (waypoints/obstacles)
+ // concrete path (with alternate)
+ // ...
+
+ private final TrafficSelector selector;
+ private final TrafficTreatment treatment;
+ private final List<Constraint> constraints;
+
+ /**
+ * Creates a connectivity intent that matches on the specified selector
+ * and applies the specified treatment.
+ * <p>
+ * Path will be optimized based on the first constraint if one is given.
+ * </p>
+ *
+ * @param appId application identifier
+ * @param key explicit key to use for intent
+ * @param resources required network resources (optional)
+ * @param selector traffic selector
+ * @param treatment treatment
+ * @param constraints optional prioritized list of constraints
+ * @param priority priority to use for flows generated by this intent
+ * @throws NullPointerException if the selector or treatment is null
+ */
+ protected ConnectivityIntent(ApplicationId appId,
+ Key key,
+ Collection<NetworkResource> resources,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ List<Constraint> constraints,
+ int priority) {
+ super(appId, key, resources, priority);
+ this.selector = checkNotNull(selector);
+ this.treatment = checkNotNull(treatment);
+ this.constraints = checkNotNull(constraints);
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected ConnectivityIntent() {
+ super();
+ this.selector = null;
+ this.treatment = null;
+ this.constraints = Collections.emptyList();
+ }
+
+ /**
+ * Abstract builder for connectivity intents.
+ */
+ public abstract static class Builder extends Intent.Builder {
+ protected TrafficSelector selector = DefaultTrafficSelector.emptySelector();
+ protected TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
+ protected List<Constraint> constraints = ImmutableList.of();
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+
+ /**
+ * Sets the traffic selector for the intent that will be built.
+ *
+ * @param selector selector to use for built intent
+ * @return this builder
+ */
+ public Builder selector(TrafficSelector selector) {
+ this.selector = selector;
+ return this;
+ }
+
+ /**
+ * Sets the traffic treatment for the intent that will be built.
+ *
+ * @param treatment treatment to use for built intent
+ * @return this builder
+ */
+ public Builder treatment(TrafficTreatment treatment) {
+ this.treatment = treatment;
+ return this;
+ }
+
+ /**
+ * Sets the constraints for the intent that will be built.
+ *
+ * @param constraints constraints to use for built intent
+ * @return this builder
+ */
+ public Builder constraints(List<Constraint> constraints) {
+ this.constraints = ImmutableList.copyOf(constraints);
+ return this;
+ }
+ }
+
+
+ /**
+ * Returns the match specifying the type of traffic.
+ *
+ * @return traffic match
+ */
+ public TrafficSelector selector() {
+ return selector;
+ }
+
+ /**
+ * Returns the action applied to the traffic.
+ *
+ * @return applied action
+ */
+ public TrafficTreatment treatment() {
+ return treatment;
+ }
+
+ /**
+ * Returns the set of connectivity constraints.
+ *
+ * @return list of intent constraints
+ */
+ public List<Constraint> constraints() {
+ return constraints;
+ }
+
+ /**
+ * 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.copyOf(links);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Constraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Constraint.java
new file mode 100644
index 00000000..03acf17c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Constraint.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+/**
+ * Representation of a connectivity constraint capable of evaluating a link
+ * and determining the cost of traversing that link in the context of this
+ * constraint.
+ */
+@Beta
+public interface Constraint {
+
+ // TODO: Consider separating cost vs viability.
+
+ /**
+ * Evaluates the specified link and provides the cost for its traversal.
+ *
+ * @param link link to be evaluated
+ * @param resourceService resource service for validating availability of
+ * link resources
+ * @return cost of link traversal
+ */
+ double cost(Link link, LinkResourceService resourceService);
+
+ /**
+ * Validates that the specified path satisfies the constraint.
+ *
+ * @param path path to be validated
+ * @param resourceService resource service for validating availability of
+ * link resources
+ * @return cost of link traversal
+ */
+ boolean validate(Path path, LinkResourceService resourceService);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/FlowRuleIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/FlowRuleIntent.java
new file mode 100644
index 00000000..0646a003
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/FlowRuleIntent.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.flow.FlowRule;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * An intent that enables to tell flow level operation.
+ * This instance holds a collection of flow rules that may be executed in parallel.
+ */
+@Beta
+public class FlowRuleIntent extends Intent {
+
+ private final Collection<FlowRule> flowRules;
+
+ /**
+ * Creates an flow rule intent with the specified flow rules to be set.
+ *
+ * @param appId application id
+ * @param flowRules flow rules to be set.
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ public FlowRuleIntent(ApplicationId appId, List<FlowRule> flowRules) {
+ this(appId, null, flowRules, Collections.emptyList());
+ }
+
+ /**
+ * Creates a flow rule intent with the specified flow rules and resources.
+ *
+ * @param appId application id
+ * @param flowRules flow rules to be set
+ * @param resources network resource to be set
+ */
+ public FlowRuleIntent(ApplicationId appId, List<FlowRule> flowRules, Collection<NetworkResource> resources) {
+ this(appId, null, flowRules, resources);
+ }
+
+ /**
+ * Creates an flow rule intent with the specified key, flow rules to be set, and
+ * required network resources.
+ *
+ * @param appId application id
+ * @param key key
+ * @param flowRules flow rules
+ * @param resources network resources
+ */
+ public FlowRuleIntent(ApplicationId appId, Key key, Collection<FlowRule> flowRules,
+ Collection<NetworkResource> resources) {
+ super(appId, key, resources, DEFAULT_INTENT_PRIORITY);
+ this.flowRules = ImmutableList.copyOf(checkNotNull(flowRules));
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected FlowRuleIntent() {
+ super();
+ this.flowRules = null;
+ }
+
+ /**
+ * Returns a collection of flow rules to be set.
+ *
+ * @return a collection of flow rules
+ */
+ public Collection<FlowRule> flowRules() {
+ return flowRules;
+ }
+
+ @Override
+ public boolean isInstallable() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("resources", resources())
+ .add("flowRule", flowRules)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java
new file mode 100644
index 00000000..bd4219ad
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of end-station to end-station bidirectional connectivity.
+ */
+@Beta
+public final class HostToHostIntent extends ConnectivityIntent {
+
+ private final HostId one;
+ private final HostId two;
+
+ /**
+ * Returns a new host to host intent builder.
+ *
+ * @return host to host intent builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of a host to host intent.
+ */
+ public static final class Builder extends ConnectivityIntent.Builder {
+ HostId one;
+ HostId two;
+
+ private Builder() {
+ // Hide constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the first host of the intent that will be built.
+ *
+ * @param one first host
+ * @return this builder
+ */
+ public Builder one(HostId one) {
+ this.one = one;
+ return this;
+ }
+
+ /**
+ * Sets the second host of the intent that will be built.
+ *
+ * @param two second host
+ * @return this builder
+ */
+ public Builder two(HostId two) {
+ this.two = two;
+ return this;
+ }
+
+ /**
+ * Builds a host to host intent from the accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public HostToHostIntent build() {
+
+ return new HostToHostIntent(
+ appId,
+ key,
+ one,
+ two,
+ selector,
+ treatment,
+ constraints,
+ priority
+ );
+ }
+ }
+
+
+ /**
+ * Creates a new host-to-host intent with the supplied host pair.
+ *
+ * @param appId application identifier
+ * @param key intent key
+ * @param one first host
+ * @param two second host
+ * @param selector action
+ * @param treatment ingress port
+ * @param constraints optional prioritized list of path selection constraints
+ * @param priority priority to use for flows generated by this intent
+ * @throws NullPointerException if {@code one} or {@code two} is null.
+ */
+ private HostToHostIntent(ApplicationId appId, Key key,
+ HostId one, HostId two,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ List<Constraint> constraints,
+ int priority) {
+ super(appId, key, ImmutableSet.of(one, two), selector, treatment,
+ constraints, priority);
+
+ // TODO: consider whether the case one and two are same is allowed
+ this.one = checkNotNull(one);
+ this.two = checkNotNull(two);
+
+ }
+
+ /**
+ * Returns identifier of the first host.
+ *
+ * @return first host identifier
+ */
+ public HostId one() {
+ return one;
+ }
+
+ /**
+ * Returns identifier of the second host.
+ *
+ * @return second host identifier
+ */
+ public HostId two() {
+ return two;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("constraints", constraints())
+ .add("one", one)
+ .add("two", two)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Intent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Intent.java
new file mode 100644
index 00000000..077fd895
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Intent.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import java.util.Collection;
+import java.util.Objects;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.net.NetworkResource;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Abstraction of an application level intent.
+ * <p>
+ * Make sure that an Intent should be immutable when a new type is defined.
+ * </p>
+ */
+@Beta
+public abstract class Intent {
+
+ private final IntentId id;
+
+ private final ApplicationId appId;
+ private final Key key;
+
+ private final int priority;
+ public static final int DEFAULT_INTENT_PRIORITY = 100;
+ public static final int MAX_PRIORITY = (1 << 16) - 1;
+ public static final int MIN_PRIORITY = 1;
+
+ private final Collection<NetworkResource> resources;
+
+ private static IdGenerator idGenerator;
+
+ /**
+ * Constructor for serializer.
+ */
+ protected Intent() {
+ this.id = null;
+ this.appId = null;
+ this.key = null;
+ this.resources = null;
+ this.priority = DEFAULT_INTENT_PRIORITY;
+ }
+
+ /**
+ * Creates a new intent.
+ *
+ * @param appId application identifier
+ * @param key optional key
+ * @param resources required network resources (optional)
+ * @param priority flow rule priority
+ */
+ protected Intent(ApplicationId appId,
+ Key key,
+ Collection<NetworkResource> resources,
+ int priority) {
+ checkState(idGenerator != null, "Id generator is not bound.");
+ checkArgument(priority <= MAX_PRIORITY && priority >= MIN_PRIORITY);
+ this.id = IntentId.valueOf(idGenerator.getNewId());
+ this.appId = checkNotNull(appId, "Application ID cannot be null");
+ this.key = (key != null) ? key : Key.of(id.fingerprint(), appId);
+ this.priority = priority;
+ this.resources = checkNotNull(resources);
+ }
+
+ /**
+ * Abstract builder for intents.
+ */
+ public abstract static class Builder {
+ protected ApplicationId appId;
+ protected Key key;
+ protected int priority = Intent.DEFAULT_INTENT_PRIORITY;
+
+ /**
+ * Sets the application id for the intent that will be built.
+ *
+ * @param appId application id to use for built intent
+ * @return this builder
+ */
+ public Builder appId(ApplicationId appId) {
+ this.appId = appId;
+ return this;
+ }
+
+ /**
+ * Sets the key for the intent that will be built.
+ *
+ * @param key key to use for built intent
+ * @return this builder
+ */
+ public Builder key(Key key) {
+ this.key = key;
+ return this;
+ }
+
+ /**
+ * Sets the priority for the intent that will be built.
+ *
+ * @param priority priority to use for built intent
+ * @return this builder
+ */
+ public Builder priority(int priority) {
+ this.priority = priority;
+ return this;
+ }
+
+ }
+
+ /**
+ * 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 priority of the intent.
+ *
+ * @return intent priority
+ */
+ public int priority() {
+ return priority;
+ }
+
+ /**
+ * Returns the collection of resources required for this intent.
+ *
+ * @return collection of resources; may be null
+ */
+ public Collection<NetworkResource> resources() {
+ return resources;
+ }
+
+ /**
+ * Indicates whether or not the intent is installable.
+ *
+ * @return true if installable
+ */
+ public boolean isInstallable() {
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ return id.hashCode();
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final Intent other = (Intent) obj;
+ return this.id().equals(other.id());
+ }
+
+ /**
+ * Binds an id generator for unique intent id generation.
+ *
+ * Note: A generator cannot be bound if there is already a generator bound.
+ *
+ * @param newIdGenerator id generator
+ */
+ public static void bindIdGenerator(IdGenerator newIdGenerator) {
+ checkState(idGenerator == null, "Id generator is already bound.");
+ idGenerator = checkNotNull(newIdGenerator);
+ }
+
+ /**
+ * Unbinds an id generator.
+ *
+ * Note: The caller must provide the old id generator to succeed.
+ *
+ * @param oldIdGenerator the current id generator
+ */
+ public static void unbindIdGenerator(IdGenerator oldIdGenerator) {
+ if (Objects.equals(idGenerator, oldIdGenerator)) {
+ idGenerator = null;
+ }
+ }
+
+ public Key key() {
+ return key;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentBatchDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentBatchDelegate.java
new file mode 100644
index 00000000..e4babfb1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentBatchDelegate.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Collection;
+
+/**
+ * Facade for receiving notifications from the intent batch service.
+ */
+@Beta
+public interface IntentBatchDelegate {
+
+ /**
+ * Submits the specified batch of intent operations for processing.
+ *
+ * @param operations batch of operations
+ */
+ void execute(Collection<IntentData> operations);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentClockService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentClockService.java
new file mode 100644
index 00000000..d0dbacf8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentClockService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.store.Timestamp;
+
+/**
+ * Logical clock service that issues per-intent timestamps.
+ */
+@Beta
+public interface IntentClockService {
+
+ /**
+ * Returns a new timestamp for the specified intent.
+ *
+ * @param intentId identifier for the intent.
+ * @return timestamp
+ */
+ Timestamp getTimestamp(IntentId intentId);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentCompiler.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentCompiler.java
new file mode 100644
index 00000000..9a059be8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentCompiler.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.resource.link.LinkResourceAllocations;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Abstraction of a compiler which is capable of taking an intent
+ * and translating it to other, potentially installable, intents.
+ *
+ * @param <T> the type of intent
+ */
+@Beta
+public interface IntentCompiler<T extends Intent> {
+ /**
+ * Compiles the specified intent into other intents.
+ *
+ * @param intent intent to be compiled
+ * @param installable previously compilation result; optional
+ * @param resources previously allocated resources; optional
+ * @return list of resulting intents
+ * @throws IntentException if issues are encountered while compiling the intent
+ */
+ List<Intent> compile(T intent, List<Intent> installable,
+ Set<LinkResourceAllocations> resources);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentData.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentData.java
new file mode 100644
index 00000000..e24e14e0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentData.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.store.Timestamp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.intent.IntentState.*;
+
+/**
+ * A wrapper class that contains an intents, its state, and other metadata for
+ * internal use.
+ */
+@Beta
+public class IntentData { //FIXME need to make this "immutable"
+ // manager should be able to mutate a local copy while processing
+
+ private static final Logger log = LoggerFactory.getLogger(IntentData.class);
+
+ private final Intent intent;
+
+ private final IntentState request; //TODO perhaps we want a full fledged object for requests
+ private IntentState state;
+ private Timestamp version;
+ private NodeId origin;
+ private int errorCount;
+
+ private List<Intent> installables;
+
+ /**
+ * Creates a new intent data object.
+ *
+ * @param intent intent this metadata references
+ * @param state intent state
+ * @param version version of the intent for this key
+ */
+ public IntentData(Intent intent, IntentState state, Timestamp version) {
+ this.intent = intent;
+ this.state = state;
+ this.request = state;
+ this.version = version;
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param intentData intent data to copy
+ */
+ public IntentData(IntentData intentData) {
+ checkNotNull(intentData);
+
+ intent = intentData.intent;
+ state = intentData.state;
+ request = intentData.request;
+ version = intentData.version;
+ origin = intentData.origin;
+ installables = intentData.installables;
+ errorCount = intentData.errorCount;
+ }
+
+ // kryo constructor
+ protected IntentData() {
+ intent = null;
+ request = null;
+ }
+
+ /**
+ * Returns the intent this metadata references.
+ *
+ * @return intent
+ */
+ public Intent intent() {
+ return intent;
+ }
+
+ /**
+ * Returns the state of the intent.
+ *
+ * @return intent state
+ */
+ public IntentState state() {
+ return state;
+ }
+
+ public IntentState request() {
+ return request;
+ }
+
+ /**
+ * Returns the intent key.
+ *
+ * @return intent key
+ */
+ public Key key() {
+ return intent.key();
+ }
+
+ /**
+ * Returns the version of the intent for this key.
+ *
+ * @return intent version
+ */
+ public Timestamp version() {
+ return version;
+ }
+
+ /**
+ * Sets the origin, which is the node that created the intent.
+ *
+ * @param origin origin instance
+ */
+ public void setOrigin(NodeId origin) {
+ this.origin = origin;
+ }
+
+ /**
+ * Returns the origin node that created this intent.
+ *
+ * @return origin node ID
+ */
+ public NodeId origin() {
+ return origin;
+ }
+
+ /**
+ * Updates the state of the intent to the given new state.
+ *
+ * @param newState new state of the intent
+ */
+ public void setState(IntentState newState) {
+ this.state = newState;
+ }
+
+ /**
+ * Sets the version for this intent data.
+ * <p>
+ * The store should call this method only once when the IntentData is
+ * first passed into the pending map. Ideally, an IntentData is timestamped
+ * on the same thread that the called used to submit the intents.
+ * </p>
+ *
+ * @param version the version/timestamp for this intent data
+ */
+ public void setVersion(Timestamp version) {
+ this.version = version;
+ }
+
+ /**
+ * Increments the error count for this intent.
+ */
+ public void incrementErrorCount() {
+ errorCount++;
+ }
+
+ /**
+ * Sets the error count for this intent.
+ *
+ * @param newCount new count
+ */
+ public void setErrorCount(int newCount) {
+ errorCount = newCount;
+ }
+
+ /**
+ * Returns the number of times that this intent has encountered an error
+ * during installation or withdrawal.
+ *
+ * @return error count
+ */
+ public int errorCount() {
+ return errorCount;
+ }
+
+ /**
+ * Sets the intent installables to the given list of intents.
+ *
+ * @param installables list of installables for this intent
+ */
+ public void setInstallables(List<Intent> installables) {
+ this.installables = ImmutableList.copyOf(installables);
+ }
+
+ /**
+ * Returns the installables associated with this intent.
+ *
+ * @return list of installable intents
+ */
+ public List<Intent> installables() {
+ return installables != null ? installables : Collections.emptyList();
+ }
+
+ /**
+ * Determines whether an intent data update is allowed. The update must
+ * either have a higher version than the current data, or the state
+ * transition between two updates of the same version must be sane.
+ *
+ * @param currentData existing intent data in the store
+ * @param newData new intent data update proposal
+ * @return true if we can apply the update, otherwise false
+ */
+ public static boolean isUpdateAcceptable(IntentData currentData, IntentData newData) {
+
+ if (currentData == null) {
+ return true;
+ } else if (currentData.version().isOlderThan(newData.version())) {
+ return true;
+ } else if (currentData.version().isNewerThan(newData.version())) {
+ return false;
+ }
+
+ // current and new data versions are the same
+ IntentState currentState = currentData.state();
+ IntentState newState = newData.state();
+
+ switch (newState) {
+ case INSTALLING:
+ if (currentState == INSTALLING) {
+ return false;
+ }
+ // FALLTHROUGH
+ case INSTALLED:
+ if (currentState == INSTALLED) {
+ return false;
+ } else if (currentState == WITHDRAWING || currentState == WITHDRAWN
+ || currentState == PURGE_REQ) {
+ log.warn("Invalid state transition from {} to {} for intent {}",
+ currentState, newState, newData.key());
+ return false;
+ }
+ return true;
+
+ case WITHDRAWING:
+ if (currentState == WITHDRAWING) {
+ return false;
+ }
+ // FALLTHROUGH
+ case WITHDRAWN:
+ if (currentState == WITHDRAWN) {
+ return false;
+ } else if (currentState == INSTALLING || currentState == INSTALLED
+ || currentState == PURGE_REQ) {
+ log.warn("Invalid state transition from {} to {} for intent {}",
+ currentState, newState, newData.key());
+ return false;
+ }
+ return true;
+
+ case FAILED:
+ if (currentState == FAILED) {
+ return false;
+ }
+ return true;
+
+ case CORRUPT:
+ if (currentState == CORRUPT) {
+ return false;
+ }
+ return true;
+
+ case PURGE_REQ:
+ // TODO we should enforce that only WITHDRAWN intents can be purged
+ return true;
+
+ case COMPILING:
+ case RECOMPILING:
+ case INSTALL_REQ:
+ case WITHDRAW_REQ:
+ default:
+ log.warn("Invalid state {} for intent {}", newState, newData.key());
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(intent, version);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final IntentData other = (IntentData) obj;
+ return Objects.equals(this.intent, other.intent)
+ && Objects.equals(this.version, other.version);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("key", key())
+ .add("state", state())
+ .add("version", version())
+ .add("intent", intent())
+ .add("origin", origin())
+ .add("installables", installables())
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentEvent.java
new file mode 100644
index 00000000..b27a5074
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentEvent.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * A class to represent an intent related event.
+ */
+@Beta
+public class IntentEvent extends AbstractEvent<IntentEvent.Type, Intent> {
+
+ public enum Type {
+ /**
+ * Signifies that an intent is to be installed or reinstalled.
+ */
+ INSTALL_REQ,
+
+ /**
+ * Signifies that an intent has been successfully installed.
+ */
+ INSTALLED,
+
+ /**
+ * Signifies that an intent has failed compilation and that it cannot
+ * be satisfied by the network at this time.
+ */
+ FAILED,
+
+ /**
+ * Signifies that an intent will be withdrawn.
+ */
+ WITHDRAW_REQ,
+
+ /**
+ * Signifies that an intent has been withdrawn from the system.
+ */
+ WITHDRAWN,
+
+ /**
+ * Signifies that an intent has failed installation or withdrawal, but
+ * still hold some or all of its resources.
+ * (e.g. link reservations, flow rules on the data plane, etc.)
+ */
+ CORRUPT,
+
+ /**
+ * Signifies that an intent has been purged from the system.
+ */
+ PURGED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified intent and the
+ * current time.
+ *
+ * @param type event type
+ * @param intent subject intent
+ * @param time time the event created in milliseconds since start of epoch
+ */
+ public IntentEvent(Type type, Intent intent, long time) {
+ super(type, intent, time);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified intent and the
+ * current time.
+ *
+ * @param type event type
+ * @param intent subject intent
+ */
+ public IntentEvent(Type type, Intent intent) {
+ super(type, intent);
+ }
+
+ /**
+ * Creates an IntentEvent based on the state contained in the given intent
+ * data. Some states are not sent as external events, and these states will
+ * return null events.
+ *
+ * @param data the intent data to create an event for
+ * @return new intent event if the state is valid, otherwise null.
+ */
+ public static IntentEvent getEvent(IntentData data) {
+ return getEvent(data.state(), data.intent());
+ }
+
+ /**
+ * Creates an IntentEvent based on the given state and intent. Some states
+ * are not sent as external events, and these states will return null events.
+ *
+ * @param state new state of the intent
+ * @param intent intent to put in event
+ * @return new intent event if the state is valid, otherwise null.
+ */
+ public static IntentEvent getEvent(IntentState state, Intent intent) {
+ Type type;
+ switch (state) {
+ case INSTALL_REQ:
+ type = Type.INSTALL_REQ;
+ break;
+ case INSTALLED:
+ type = Type.INSTALLED;
+ break;
+ case WITHDRAW_REQ:
+ type = Type.WITHDRAW_REQ;
+ break;
+ case WITHDRAWN:
+ type = Type.WITHDRAWN;
+ break;
+ case FAILED:
+ type = Type.FAILED;
+ break;
+ case CORRUPT:
+ type = Type.CORRUPT;
+ break;
+ case PURGE_REQ:
+ type = Type.PURGED;
+ break;
+
+ // fallthrough to default from here
+ case COMPILING:
+ case INSTALLING:
+ case RECOMPILING:
+ case WITHDRAWING:
+ default:
+ return null;
+ }
+ return new IntentEvent(type, intent);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentException.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentException.java
new file mode 100644
index 00000000..3ac1df50
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentException.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents an intent related error.
+ */
+@Beta
+public class IntentException extends RuntimeException {
+
+ private static final long serialVersionUID = 1907263634145241319L;
+
+ /**
+ * Constructs an exception with no message and no underlying cause.
+ */
+ public IntentException() {
+ }
+
+ /**
+ * Constructs an exception with the specified message.
+ *
+ * @param message the message describing the specific nature of the error
+ */
+ public IntentException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception with the specified message and the underlying cause.
+ *
+ * @param message the message describing the specific nature of the error
+ * @param cause the underlying cause of this error
+ */
+ public IntentException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentExtensionService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentExtensionService.java
new file mode 100644
index 00000000..d7c7c641
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentExtensionService.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Map;
+
+/**
+ * Service for extending the capability of intent framework by
+ * adding additional compilers or/and installers.
+ */
+@Beta
+public interface IntentExtensionService {
+ /**
+ * Registers the specified compiler for the given intent class.
+ *
+ * @param cls intent class
+ * @param compiler intent compiler
+ * @param <T> the type of intent
+ */
+ <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler);
+
+ /**
+ * Unregisters the compiler for the specified intent class.
+ *
+ * @param cls intent class
+ * @param <T> the type of intent
+ */
+ <T extends Intent> void unregisterCompiler(Class<T> cls);
+
+ /**
+ * Returns immutable set of bindings of currently registered intent compilers.
+ *
+ * @return the set of compiler bindings
+ */
+ Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentId.java
new file mode 100644
index 00000000..b9a30d2d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentId.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.newresource.ResourceConsumer;
+
+/**
+ * Intent identifier suitable as an external key.
+ * <p>This class is immutable.</p>
+ */
+@Beta
+public final class IntentId implements ResourceConsumer {
+
+ private final long value;
+
+ /**
+ * Creates an intent identifier from the specified long representation.
+ *
+ * @param value long value
+ * @return intent identifier
+ */
+ public static IntentId valueOf(long value) {
+ return new IntentId(value);
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ IntentId() {
+ this.value = 0;
+ }
+
+ /**
+ * Constructs the ID corresponding to a given long value.
+ *
+ * @param value the underlying value of this ID
+ */
+ IntentId(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns the backing value.
+ *
+ * @return the value
+ */
+ public long fingerprint() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Long.hashCode(value);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof IntentId)) {
+ return false;
+ }
+ IntentId that = (IntentId) obj;
+ return this.value == that.value;
+ }
+
+ @Override
+ public String toString() {
+ return "0x" + Long.toHexString(value);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentListener.java
new file mode 100644
index 00000000..4858c7ed
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.event.EventListener;
+
+/**
+ * Listener for {@link IntentEvent intent events}.
+ */
+@Beta
+public interface IntentListener extends EventListener<IntentEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentOperation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentOperation.java
new file mode 100644
index 00000000..1b51b4f3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentOperation.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+
+import com.google.common.annotations.Beta;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of an intent-related operation, e.g. add, remove, replace.
+ */
+@Beta
+public final class IntentOperation {
+
+ private final Type type;
+ private final Intent intent;
+
+ /**
+ * Operation type.
+ */
+ public enum Type {
+ /**
+ * Indicates that an intent should be added.
+ */
+ SUBMIT,
+
+ /**
+ * Indicates that an intent should be removed.
+ */
+ WITHDRAW,
+ }
+
+ /**
+ * Creates an intent operation.
+ *
+ * @param type operation type
+ * @param intent intent subject
+ */
+ public IntentOperation(Type type, Intent intent) {
+ this.type = checkNotNull(type);
+ this.intent = intent;
+ }
+
+ /**
+ * Returns the type of the operation.
+ *
+ * @return operation type
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the identifier of the intent to which this operation applies.
+ *
+ * @return intent identifier
+ */
+ public IntentId intentId() {
+ return intent.id();
+ }
+
+ /**
+ * Returns the key for this intent.
+ *
+ * @return key value
+ */
+ public Key key() {
+ return intent.key();
+ }
+
+ /**
+ * Returns the intent to which this operation applied. For remove,
+ * this can be null.
+ *
+ * @return intent that is the subject of the operation; null for remove
+ */
+ public Intent intent() {
+ return intent;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, intent);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final IntentOperation other = (IntentOperation) obj;
+ return Objects.equals(this.type, other.type) &&
+ Objects.equals(this.intent, other.intent);
+ }
+
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("type", type)
+ .add("intent", intent)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentService.java
new file mode 100644
index 00000000..8533cebc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentService.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+
+import com.google.common.annotations.Beta;
+import org.onosproject.event.ListenerService;
+
+import java.util.List;
+
+/**
+ * Service for application submitting or withdrawing their intents.
+ */
+@Beta
+public interface IntentService
+ extends ListenerService<IntentEvent, IntentListener> {
+
+ /**
+ * Submits an intent into the system.
+ * <p>
+ * This is an asynchronous request meaning that any compiling or
+ * installation activities may be done at later time.
+ * </p>
+ * @param intent intent to be submitted
+ */
+ void submit(Intent intent);
+
+ /**
+ * Withdraws an intent from the system.
+ * <p>
+ * This is an asynchronous request meaning that the environment may be
+ * affected at later time.
+ * </p>
+ * @param intent intent to be withdrawn
+ */
+ void withdraw(Intent intent);
+
+ /**
+ * Purges a specific intent from the system if it is <b>FAILED</b> or
+ * <b>WITHDRAWN</b>. Otherwise, the intent remains in its current state.
+ *
+ * @param intent intent to purge
+ */
+ void purge(Intent intent);
+
+ /**
+ * Fetches an intent based on its key.
+ *
+ * @param key key of the intent
+ * @return intent object if the key is found, null otherwise
+ */
+ Intent getIntent(Key key);
+
+ /**
+ * Returns an iterable of intents currently in the system.
+ *
+ * @return set of intents
+ */
+ Iterable<Intent> getIntents();
+
+ /**
+ * Returns an iterable of intent data objects currently in the system.
+ *
+ * @return set of intent data objects
+ */
+ Iterable<IntentData> getIntentData();
+
+ /**
+ * Returns the number of intents currently in the system.
+ *
+ * @return number of intents
+ */
+ long getIntentCount();
+
+ /**
+ * Retrieves the state of an intent by its identifier.
+ *
+ * @param intentKey intent identifier
+ * @return the intent state or null if one with the given identifier is not
+ * found
+ */
+ IntentState getIntentState(Key intentKey);
+
+ /**
+ * Returns the list of the installable events associated with the specified
+ * top-level intent.
+ *
+ * @param intentKey top-level intent identifier
+ * @return compiled installable intents
+ */
+ List<Intent> getInstallableIntents(Key intentKey);
+
+ /**
+ * Signifies whether the local node is responsible for processing the given
+ * intent key.
+ *
+ * @param intentKey intent key to check
+ * @return true if the local node is responsible for the intent key,
+ * otherwise false
+ */
+ boolean isLocal(Key intentKey);
+
+ /**
+ * Returns the list of intent requests pending processing.
+ *
+ * @return intents pending processing
+ */
+ Iterable<Intent> getPending();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentState.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentState.java
new file mode 100644
index 00000000..1e5fd054
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentState.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Representation of the phases an intent may attain during its lifecycle.
+ */
+@Beta
+public enum IntentState {
+
+ /**
+ * Signifies that the intent has been submitted and will start compiling
+ * shortly. However, this compilation may not necessarily occur on the
+ * local controller instance.
+ * <p>
+ * All intent in the runtime take this state first.
+ * </p><p>
+ * Intents will also pass through this state when they are updated.
+ * </p>
+ */
+ INSTALL_REQ, // TODO submit_REQ?
+
+ /**
+ * Signifies that the intent is being compiled into installable intents.
+ * This is a transitional state after which the intent will enter either
+ * {@link #FAILED} state or {@link #INSTALLING} state.
+ */
+ COMPILING, //TODO do we really need this?
+
+ /**
+ * Signifies that the resulting installable intents are being installed
+ * into the network environment. This is a transitional state after which
+ * the intent will enter either {@link #INSTALLED} state or
+ * {@link #RECOMPILING} state.
+ */
+ INSTALLING,
+
+ /**
+ * The intent has been successfully installed. This is a state where the
+ * intent may remain parked until it is withdrawn by the application or
+ * until the network environment changes in some way to make the original
+ * set of installable intents untenable.
+ */
+ INSTALLED,
+
+ /**
+ * Signifies that the intent is being recompiled into installable intents
+ * as an attempt to adapt to an anomaly in the network environment.
+ * This is a transitional state after which the intent will enter either
+ * {@link #FAILED} state or {@link #INSTALLING} state.
+ * <p>
+ * Exit to the {@link #FAILED} state may be caused by failure to compile
+ * or by compiling into the same set of installable intents which have
+ * previously failed to be installed.
+ * </p>
+ */
+ RECOMPILING, // TODO perhaps repurpose as BROKEN.
+
+ /**
+ * Indicates that an application has requested that an intent be withdrawn.
+ * It will start withdrawing shortly, but not necessarily on this instance.
+ * Intents can also be parked here if it is impossible to withdraw them.
+ */
+ WITHDRAW_REQ,
+
+ /**
+ * Indicates that the intent is being withdrawn. This is a transitional
+ * state, triggered by invocation of the
+ * {@link IntentService#withdraw(Intent)} but one with only one outcome,
+ * which is the the intent being placed in the {@link #WITHDRAWN} state.
+ */
+ WITHDRAWING,
+
+ /**
+ * Indicates that the intent has been successfully withdrawn.
+ */
+ WITHDRAWN,
+
+ /**
+ * Signifies that the intent has failed to be installed and cannot be
+ * satisfied given current network conditions. But, the framework will
+ * reattempt to install it when network conditions change until it is
+ * withdrawn by an application.
+ */
+ FAILED, //TODO consider renaming to UNSATISFIABLE
+
+ /**
+ * Signifies that an intent has failed either installation or withdrawal,
+ * and still hold some or all of its resources.
+ * (e.g. link reservations, flow rules on the data plane, etc.)
+ */
+ CORRUPT, //TODO consider renaming to ERROR
+
+ /**
+ * Indicates that the intent should be purged from the database.
+ * <p>
+ * Note: This operation will only be performed if the intent is already
+ * in WITHDRAWN or FAILED.
+ * </p>
+ */
+ PURGE_REQ
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java
new file mode 100644
index 00000000..167ba152
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.store.Store;
+
+import java.util.List;
+
+/**
+ * Manages inventory of end-station intents; not intended for direct use.
+ */
+@Beta
+public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> {
+
+ /**
+ * Returns the number of intents in the store.
+ *
+ * @return the number of intents in the store
+ */
+ long getIntentCount();
+
+ /**
+ * Returns an iterable of all intents in the store.
+ *
+ * @return iterable of all intents
+ */
+ Iterable<Intent> getIntents();
+
+
+ /**
+ * Returns an iterable of all intent data objects in the store.
+ *
+ * @param localOnly should only intents for which this instance is master
+ * be returned
+ * @param olderThan specified duration in milliseconds (0 for "now")
+ * @return iterable of all intent data objects
+ */
+ Iterable<IntentData> getIntentData(boolean localOnly, long olderThan);
+
+ /**
+ * Returns the state of the specified intent.
+ *
+ * @param intentKey intent identification
+ * @return current intent state
+ */
+ IntentState getIntentState(Key intentKey);
+
+ /**
+ * Returns the list of the installable events associated with the specified
+ * original intent.
+ *
+ * @param intentKey original intent identifier
+ * @return compiled installable intents, or null if no installables exist
+ */
+ List<Intent> getInstallableIntents(Key intentKey);
+
+ /**
+ * Writes an IntentData object to the store.
+ *
+ * @param newData new intent data to write
+ */
+ void write(IntentData newData);
+
+ /**
+ * Writes a batch of IntentData objects to the store. A batch has no
+ * semantics, this is simply a convenience API.
+ *
+ * @param updates collection of intent data objects to write
+ */
+ void batchWrite(Iterable<IntentData> updates);
+
+ /**
+ * Returns the intent with the specified identifier.
+ *
+ * @param key key
+ * @return intent or null if not found
+ */
+ Intent getIntent(Key key);
+
+ /**
+ * Returns the intent data object associated with the specified key.
+ *
+ * @param key key to look up
+ * @return intent data object
+ */
+ IntentData getIntentData(Key key);
+
+ /**
+ * Adds a new operation, which should be persisted and delegated.
+ *
+ * @param intent operation
+ */
+ void addPending(IntentData intent);
+
+ /**
+ * Checks to see whether the calling instance is the master for processing
+ * this intent, or more specifically, the key contained in this intent.
+ *
+ * @param intentKey intentKey to check
+ * @return true if master; false, otherwise
+ */
+ //TODO better name
+ boolean isMaster(Key intentKey);
+
+ /**
+ * Returns the intent requests pending processing.
+ *
+ * @return pending intents
+ */
+ Iterable<Intent> getPending();
+
+ /**
+ * Returns the intent data objects that are pending processing.
+ *
+ * @return pending intent data objects
+ */
+ Iterable<IntentData> getPendingData();
+
+ /**
+ * Returns the intent data objects that are pending processing for longer
+ * than the specified duration.
+ *
+ * @param localOnly should only intents for which this instance is master
+ * be returned
+ * @param olderThan specified duration in milliseconds (0 for "now")
+ * @return pending intent data objects
+ */
+ Iterable<IntentData> getPendingData(boolean localOnly, long olderThan);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentStoreDelegate.java
new file mode 100644
index 00000000..fd99881c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/IntentStoreDelegate.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Intent store delegate abstraction.
+ */
+@Beta
+public interface IntentStoreDelegate extends StoreDelegate<IntentEvent> {
+
+ /**
+ * Provides an intent data object that should be processed (compiled and
+ * installed) by this manager.
+ *
+ * @param intentData intent data object
+ */
+ void process(IntentData intentData);
+
+ /**
+ * Called when a new intent has been updated for which this node is the master.
+ *
+ * @param intentData intent data object
+ */
+ default void onUpdate(IntentData intentData) {
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java
new file mode 100644
index 00000000..18baafc8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hashing;
+import org.onosproject.core.ApplicationId;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+
+/**
+ * Key class for Intents.
+ */
+// TODO maybe pull this up to utils
+@Beta
+public abstract class Key {
+
+ //TODO consider making this a HashCode object (worry about performance)
+ private final long hash;
+ private static final HashFunction HASH_FN = Hashing.md5();
+
+ protected Key(long hash) {
+ this.hash = hash;
+ }
+
+ public long hash() {
+ return hash;
+ }
+
+ @Override
+ public int hashCode() {
+ return Long.hashCode(hash);
+ }
+
+ @Override
+ public abstract boolean equals(Object obj);
+
+ /**
+ * Creates a key based on the provided string.
+ * <p>
+ * Note: Two keys with equal value, but different appId, are not equal.
+ * </p>
+ *
+ * @param key the provided string
+ * @param appId application id to associate with this key
+ * @return the key for the string
+ */
+ public static Key of(String key, ApplicationId appId) {
+ return new StringKey(key, appId);
+ }
+
+ /**
+ * Creates a key based on the provided long.
+ * <p>
+ * Note: Two keys with equal value, but different appId, are not equal.
+ * Also, "10" and 10L are different.
+ * </p>
+ *
+ * @param key the provided long
+ * @param appId application id to associate with this key
+ * @return the key for the long
+ */
+ public static Key of(long key, ApplicationId appId) {
+ return new LongKey(key, appId);
+ }
+
+ private static final class StringKey extends Key {
+
+ private final ApplicationId appId;
+ private final String key;
+
+ private StringKey(String key, ApplicationId appId) {
+ super(HASH_FN.newHasher()
+ .putShort(appId.id())
+ .putString(key, StandardCharsets.UTF_8)
+ .hash().asLong());
+ this.key = key;
+ this.appId = appId;
+ }
+
+ @Override
+ public String toString() {
+ return key;
+ }
+
+ // checkstyle requires this
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final StringKey other = (StringKey) obj;
+ return this.hash() == other.hash() &&
+ Objects.equals(this.appId, other.appId) &&
+ Objects.equals(this.key, other.key);
+ }
+ }
+
+ private static final class LongKey extends Key {
+
+ private final ApplicationId appId;
+ private final long key;
+
+ private LongKey(long key, ApplicationId appId) {
+ super(HASH_FN.newHasher()
+ .putShort(appId.id())
+ .putLong(key)
+ .hash().asLong());
+ this.key = key;
+ this.appId = appId;
+ }
+
+ @Override
+ public String toString() {
+ return "0x" + Long.toHexString(key);
+ }
+
+ // checkstyle requires this
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final LongKey other = (LongKey) obj;
+ return this.hash() == other.hash() &&
+ this.key == other.key &&
+ Objects.equals(this.appId, other.appId);
+ }
+ }
+}
+
+
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/LinkCollectionIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/LinkCollectionIntent.java
new file mode 100644
index 00000000..d7953fd8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/LinkCollectionIntent.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Abstraction of a connectivity intent that is implemented by a set of path
+ * segments.
+ */
+@Beta
+public final class LinkCollectionIntent extends ConnectivityIntent {
+
+ private final Set<Link> links;
+
+ private final Set<ConnectPoint> ingressPoints;
+ private final Set<ConnectPoint> egressPoints;
+
+ /**
+ * Creates a new actionable intent capable of funneling the selected
+ * traffic along the specified convergent tree and out the given egress
+ * point satisfying the specified constraints.
+ *
+ * @param appId application identifier
+ * @param key key to use for the intent
+ * @param selector traffic match
+ * @param treatment action
+ * @param links traversed links
+ * @param ingressPoints ingress points
+ * @param egressPoints egress points
+ * @param constraints optional list of constraints
+ * @param priority priority to use for the flows generated by this intent
+ * @throws NullPointerException {@code path} is null
+ */
+ private LinkCollectionIntent(ApplicationId appId,
+ Key key,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ Set<Link> links,
+ Set<ConnectPoint> ingressPoints,
+ Set<ConnectPoint> egressPoints,
+ List<Constraint> constraints,
+ int priority) {
+ super(appId, key, resources(links), selector, treatment, constraints, priority);
+ this.links = links;
+ this.ingressPoints = ingressPoints;
+ this.egressPoints = egressPoints;
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected LinkCollectionIntent() {
+ super();
+ this.links = null;
+ this.ingressPoints = null;
+ this.egressPoints = null;
+ }
+
+ /**
+ * Returns a new link collection intent builder. The application id,
+ * ingress point and egress points are required fields. If they are
+ * not set by calls to the appropriate methods, an exception will
+ * be thrown.
+ *
+ * @return single point to multi point builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of a single point to multi point intent.
+ */
+ public static final class Builder extends ConnectivityIntent.Builder {
+ Set<Link> links;
+ Set<ConnectPoint> ingressPoints;
+ Set<ConnectPoint> egressPoints;
+
+ private Builder() {
+ // Hide constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the ingress point of the single point to multi point intent
+ * that will be built.
+ *
+ * @param ingressPoints ingress connect points
+ * @return this builder
+ */
+ public Builder ingressPoints(Set<ConnectPoint> ingressPoints) {
+ this.ingressPoints = ImmutableSet.copyOf(ingressPoints);
+ return this;
+ }
+
+ /**
+ * Sets the egress points of the single point to multi point intent
+ * that will be built.
+ *
+ * @param egressPoints egress connect points
+ * @return this builder
+ */
+ public Builder egressPoints(Set<ConnectPoint> egressPoints) {
+ this.egressPoints = ImmutableSet.copyOf(egressPoints);
+ return this;
+ }
+
+ /**
+ * Sets the links of the link collection intent
+ * that will be built.
+ *
+ * @param links links for the intent
+ * @return this builder
+ */
+ public Builder links(Set<Link> links) {
+ this.links = ImmutableSet.copyOf(links);
+ return this;
+ }
+
+
+ /**
+ * Builds a single point to multi point intent from the
+ * accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public LinkCollectionIntent build() {
+
+ return new LinkCollectionIntent(
+ appId,
+ key,
+ selector,
+ treatment,
+ links,
+ ingressPoints,
+ egressPoints,
+ constraints,
+ priority
+ );
+ }
+ }
+
+
+ /**
+ * Returns the set of links that represent the network connections needed
+ * by this intent.
+ *
+ * @return Set of links for the network hops needed by this intent
+ */
+ public Set<Link> links() {
+ return links;
+ }
+
+ /**
+ * Returns the ingress points of the intent.
+ *
+ * @return the ingress points
+ */
+ public Set<ConnectPoint> ingressPoints() {
+ return ingressPoints;
+ }
+
+ /**
+ * Returns the egress points of the intent.
+ *
+ * @return the egress points
+ */
+ public Set<ConnectPoint> egressPoints() {
+ return egressPoints;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("links", links())
+ .add("ingress", ingressPoints())
+ .add("egress", egressPoints())
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsIntent.java
new file mode 100644
index 00000000..bf469dbe
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsIntent.java
@@ -0,0 +1,261 @@
+package org.onosproject.net.intent;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import com.google.common.annotations.Beta;
+import org.onlab.packet.MplsLabel;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import com.google.common.base.MoreObjects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+
+/**
+ * Abstraction of MPLS label-switched connectivity.
+ */
+@Beta
+public final class MplsIntent extends ConnectivityIntent {
+
+ private final ConnectPoint ingressPoint;
+ private final Optional<MplsLabel> ingressLabel;
+ private final ConnectPoint egressPoint;
+ private final Optional<MplsLabel> egressLabel;
+
+ /**
+ * Creates a new point-to-point intent with the supplied ingress/egress
+ * ports, labels and constraints.
+ *
+ * @param appId application identifier
+ * @param selector traffic selector
+ * @param treatment treatment
+ * @param ingressPoint ingress port
+ * @param ingressLabel ingress MPLS label
+ * @param egressPoint egress port
+ * @param egressLabel egress MPLS label
+ * @param constraints optional list of constraints
+ * @param priority priority to use for flows generated by this intent
+ * @throws NullPointerException if {@code ingressPoint} or {@code egressPoints} is null.
+ */
+ private MplsIntent(ApplicationId appId,
+ Key key,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ ConnectPoint ingressPoint,
+ Optional<MplsLabel> ingressLabel,
+ ConnectPoint egressPoint,
+ Optional<MplsLabel> egressLabel,
+ List<Constraint> constraints,
+ int priority) {
+
+ super(appId, key, Collections.emptyList(), selector, treatment, constraints,
+ priority);
+
+ this.ingressPoint = checkNotNull(ingressPoint);
+ this.ingressLabel = checkNotNull(ingressLabel);
+ this.egressPoint = checkNotNull(egressPoint);
+ this.egressLabel = checkNotNull(egressLabel);
+
+ checkArgument(!ingressPoint.equals(egressPoint),
+ "ingress and egress should be different (ingress: %s, egress: %s)",
+ ingressPoint, egressPoint);
+ }
+
+ /**
+ * Returns a new MPLS intent builder. The application id,
+ * ingress point, egress point, ingress label and egress label are
+ * required fields. If they are not set by calls to the appropriate
+ * methods, an exception will be thrown.
+ *
+ * @return point to point builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of an MPLS intent.
+ */
+ public static final class Builder extends ConnectivityIntent.Builder {
+ ConnectPoint ingressPoint;
+ ConnectPoint egressPoint;
+ Optional<MplsLabel> ingressLabel;
+ Optional<MplsLabel> egressLabel;
+
+ private Builder() {
+ // Hide constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the ingress point of the point to point intent that will be built.
+ *
+ * @param ingressPoint ingress connect point
+ * @return this builder
+ */
+ public Builder ingressPoint(ConnectPoint ingressPoint) {
+ this.ingressPoint = ingressPoint;
+ return this;
+ }
+
+ /**
+ * Sets the egress point of the point to point intent that will be built.
+ *
+ * @param egressPoint egress connect point
+ * @return this builder
+ */
+ public Builder egressPoint(ConnectPoint egressPoint) {
+ this.egressPoint = egressPoint;
+ return this;
+ }
+
+ /**
+ * Sets the ingress label of the intent that will be built.
+ *
+ * @param ingressLabel ingress label
+ * @return this builder
+ */
+ public Builder ingressLabel(Optional<MplsLabel> ingressLabel) {
+ this.ingressLabel = ingressLabel;
+ return this;
+ }
+
+ /**
+ * Sets the ingress label of the intent that will be built.
+ *
+ * @param egressLabel ingress label
+ * @return this builder
+ */
+ public Builder egressLabel(Optional<MplsLabel> egressLabel) {
+ this.egressLabel = egressLabel;
+ return this;
+ }
+
+ /**
+ * Builds a point to point intent from the accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public MplsIntent build() {
+
+ return new MplsIntent(
+ appId,
+ key,
+ selector,
+ treatment,
+ ingressPoint,
+ ingressLabel,
+ egressPoint,
+ egressLabel,
+ constraints,
+ priority
+ );
+ }
+ }
+
+
+
+ /**
+ * Constructor for serializer.
+ */
+ protected MplsIntent() {
+ super();
+ this.ingressPoint = null;
+ this.ingressLabel = null;
+ this.egressPoint = null;
+ this.egressLabel = null;
+ }
+
+ /**
+ * Returns the port on which the ingress traffic should be connected to
+ * the egress.
+ *
+ * @return ingress switch port
+ */
+ public ConnectPoint ingressPoint() {
+ return ingressPoint;
+ }
+
+ /**
+ * Returns the port on which the traffic should egress.
+ *
+ * @return egress switch port
+ */
+ public ConnectPoint egressPoint() {
+ return egressPoint;
+ }
+
+
+ /**
+ * Returns the MPLS label which the ingress traffic should tagged.
+ *
+ * @return ingress MPLS label
+ */
+ public Optional<MplsLabel> ingressLabel() {
+ return ingressLabel;
+ }
+
+ /**
+ * Returns the MPLS label which the egress traffic should tagged.
+ *
+ * @return egress MPLS label
+ */
+ public Optional<MplsLabel> egressLabel() {
+ return egressLabel;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("appId", appId())
+ .add("key", key())
+ .add("priority", priority())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("ingressPoint", ingressPoint)
+ .add("ingressLabel", ingressLabel)
+ .add("egressPoint", egressPoint)
+ .add("egressLabel", egressLabel)
+ .add("constraints", constraints())
+ .toString();
+ }
+
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsPathIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsPathIntent.java
new file mode 100644
index 00000000..3c3c45ce
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsPathIntent.java
@@ -0,0 +1,167 @@
+package org.onosproject.net.intent;
+
+import java.util.List;
+import java.util.Optional;
+
+import com.google.common.annotations.Beta;
+import org.onlab.packet.MplsLabel;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.Path;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+
+/**
+ * Abstraction of explicit MPLS label-switched path.
+ */
+@Beta
+public final class MplsPathIntent extends PathIntent {
+
+ private final Optional<MplsLabel> ingressLabel;
+ private final Optional<MplsLabel> egressLabel;
+
+ /**
+ * Creates a new point-to-point intent with the supplied ingress/egress
+ * ports and using the specified explicit path.
+ *
+ * @param appId application identifier
+ * @param selector traffic selector
+ * @param treatment treatment
+ * @param path traversed links
+ * @param ingressLabel MPLS egress label
+ * @param egressLabel MPLS ingress label
+ * @param constraints optional list of constraints
+ * @param priority priority to use for flows generated by this intent
+ * @throws NullPointerException {@code path} is null
+ */
+ private MplsPathIntent(ApplicationId appId, TrafficSelector selector,
+ TrafficTreatment treatment, Path path, Optional<MplsLabel> ingressLabel,
+ Optional<MplsLabel> egressLabel, List<Constraint> constraints,
+ int priority) {
+ super(appId, selector, treatment, path, constraints,
+ priority);
+
+ this.ingressLabel = checkNotNull(ingressLabel);
+ this.egressLabel = checkNotNull(egressLabel);
+ }
+
+ /**
+ * Returns a new host to host intent builder.
+ *
+ * @return host to host intent builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of a host to host intent.
+ */
+ public static final class Builder extends PathIntent.Builder {
+ private Optional<MplsLabel> ingressLabel = Optional.empty();
+ private Optional<MplsLabel> egressLabel = Optional.empty();
+
+ private Builder() {
+ // Hide constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ @Override
+ public Builder path(Path path) {
+ return (Builder) super.path(path);
+ }
+
+ /**
+ * Sets the ingress label of the intent that will be built.
+ *
+ * @param ingressLabel ingress label
+ * @return this builder
+ */
+ public Builder ingressLabel(Optional<MplsLabel> ingressLabel) {
+ this.ingressLabel = ingressLabel;
+ return this;
+ }
+
+ /**
+ * Sets the ingress label of the intent that will be built.
+ *
+ * @param egressLabel ingress label
+ * @return this builder
+ */
+ public Builder egressLabel(Optional<MplsLabel> egressLabel) {
+ this.egressLabel = egressLabel;
+ return this;
+ }
+
+
+ /**
+ * Builds a host to host intent from the accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public MplsPathIntent build() {
+
+ return new MplsPathIntent(
+ appId,
+ selector,
+ treatment,
+ path,
+ ingressLabel,
+ egressLabel,
+ constraints,
+ priority
+ );
+ }
+ }
+
+
+ /**
+ * Returns the MPLS label which the ingress traffic should tagged.
+ *
+ * @return ingress MPLS label
+ */
+ public Optional<MplsLabel> ingressLabel() {
+ return ingressLabel;
+ }
+
+ /**
+ * Returns the MPLS label which the egress traffic should tagged.
+ *
+ * @return egress MPLS label
+ */
+ public Optional<MplsLabel> egressLabel() {
+ return egressLabel;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MultiPointToSinglePointIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MultiPointToSinglePointIntent.java
new file mode 100644
index 00000000..ac6061c7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MultiPointToSinglePointIntent.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of multiple source to single destination connectivity intent.
+ */
+@Beta
+public final class MultiPointToSinglePointIntent extends ConnectivityIntent {
+
+ private final Set<ConnectPoint> ingressPoints;
+ private final ConnectPoint egressPoint;
+
+ /**
+ * Creates a new multi-to-single point connectivity intent for the specified
+ * traffic selector and treatment.
+ *
+ * @param appId application identifier
+ * @param key intent key
+ * @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
+ * @param constraints constraints to apply to the intent
+ * @param priority priority to use for flows generated by this intent
+ * @throws NullPointerException if {@code ingressPoints} or
+ * {@code egressPoint} is null.
+ * @throws IllegalArgumentException if the size of {@code ingressPoints} is
+ * not more than 1
+ */
+ private MultiPointToSinglePointIntent(ApplicationId appId,
+ Key key,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ Set<ConnectPoint> ingressPoints,
+ ConnectPoint egressPoint,
+ List<Constraint> constraints,
+ int priority) {
+ super(appId, key, Collections.emptyList(), selector, treatment, constraints,
+ priority);
+
+ checkNotNull(ingressPoints);
+ checkArgument(!ingressPoints.isEmpty(), "Ingress point set cannot be empty");
+ checkNotNull(egressPoint);
+ checkArgument(!ingressPoints.contains(egressPoint),
+ "Set of ingresses should not contain egress (egress: %s)", egressPoint);
+
+ this.ingressPoints = Sets.newHashSet(ingressPoints);
+ this.egressPoint = egressPoint;
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected MultiPointToSinglePointIntent() {
+ super();
+ this.ingressPoints = null;
+ this.egressPoint = null;
+ }
+
+ /**
+ * Returns a new multi point to single point intent builder. The application id,
+ * ingress points and egress point are required fields. If they are
+ * not set by calls to the appropriate methods, an exception will
+ * be thrown.
+ *
+ * @return single point to multi point builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of a multi point to single point intent.
+ */
+ public static final class Builder extends ConnectivityIntent.Builder {
+ Set<ConnectPoint> ingressPoints;
+ ConnectPoint egressPoint;
+
+ private Builder() {
+ // Hide constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the ingress point of the single point to multi point intent
+ * that will be built.
+ *
+ * @param ingressPoints ingress connect points
+ * @return this builder
+ */
+ public Builder ingressPoints(Set<ConnectPoint> ingressPoints) {
+ this.ingressPoints = ImmutableSet.copyOf(ingressPoints);
+ return this;
+ }
+
+ /**
+ * Sets the egress point of the multi point to single point intent
+ * that will be built.
+ *
+ * @param egressPoint egress connect point
+ * @return this builder
+ */
+ public Builder egressPoint(ConnectPoint egressPoint) {
+ this.egressPoint = egressPoint;
+ return this;
+ }
+
+ /**
+ * Builds a multi point to single point intent from the
+ * accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public MultiPointToSinglePointIntent build() {
+
+ return new MultiPointToSinglePointIntent(
+ appId,
+ key,
+ selector,
+ treatment,
+ ingressPoints,
+ egressPoint,
+ constraints,
+ priority
+ );
+ }
+ }
+
+
+ /**
+ * Returns the set of ports on which ingress traffic should be connected to
+ * the egress port.
+ *
+ * @return set of ingress ports
+ */
+ public Set<ConnectPoint> ingressPoints() {
+ return ingressPoints;
+ }
+
+ /**
+ * Returns the port on which the traffic should egress.
+ *
+ * @return egress port
+ */
+ public ConnectPoint egressPoint() {
+ return egressPoint;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("ingress", ingressPoints())
+ .add("egress", egressPoint())
+ .add("constraints", constraints())
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalCircuitIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalCircuitIntent.java
new file mode 100644
index 00000000..1e515c8c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalCircuitIntent.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.OduCltPort;
+
+import java.util.Collections;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * An optical layer intent for circuits between two OduClt ports.
+ * No traffic selector or traffic treatment are needed.
+ */
+@Beta
+public class OpticalCircuitIntent extends Intent {
+ private final ConnectPoint src;
+ private final ConnectPoint dst;
+ private final OduCltPort.SignalType signalType;
+ private final boolean isBidirectional;
+
+ /**
+ * Creates an optical circuit intent between the specified
+ * connection points.
+ *
+ * @param appId application identification
+ * @param key intent key
+ * @param src the source transponder port
+ * @param dst the destination transponder port
+ * @param signalType ODU signal type
+ * @param isBidirectional indicate if intent is bidirectional
+ * @param priority priority to use for flows from this intent
+ */
+ protected OpticalCircuitIntent(ApplicationId appId, Key key, ConnectPoint src, ConnectPoint dst,
+ OduCltPort.SignalType signalType, boolean isBidirectional, int priority) {
+ super(appId, key, Collections.emptyList(), priority);
+ this.src = checkNotNull(src);
+ this.dst = checkNotNull(dst);
+ this.signalType = checkNotNull(signalType);
+ this.isBidirectional = isBidirectional;
+ }
+
+ /**
+ * Returns a new optical circuit intent builder.
+ *
+ * @return host to host intent builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+
+ /**
+ * Builder for optical circuit intents.
+ */
+ public static class Builder extends Intent.Builder {
+ private ConnectPoint src;
+ private ConnectPoint dst;
+ private OduCltPort.SignalType signalType;
+ private boolean isBidirectional;
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the source for the intent that will be built.
+ *
+ * @param src source to use for built intent
+ * @return this builder
+ */
+ public Builder src(ConnectPoint src) {
+ this.src = src;
+ return this;
+ }
+
+ /**
+ * Sets the destination for the intent that will be built.
+ *
+ * @param dst dest to use for built intent
+ * @return this builder
+ */
+ public Builder dst(ConnectPoint dst) {
+ this.dst = dst;
+ return this;
+ }
+
+ /**
+ * Sets the ODU signal type for the intent that will be built.
+ *
+ * @param signalType signal type to use for built intent
+ * @return this builder
+ */
+ public Builder signalType(OduCltPort.SignalType signalType) {
+ this.signalType = signalType;
+ return this;
+ }
+
+ /**
+ * Sets the directionality of the intent.
+ *
+ * @param isBidirectional true if bidirectional, false if unidirectional
+ * @return this builder
+ */
+ public Builder bidirectional(boolean isBidirectional) {
+ this.isBidirectional = isBidirectional;
+ return this;
+ }
+
+ /**
+ * Builds an optical circuit intent from the accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public OpticalCircuitIntent build() {
+
+ return new OpticalCircuitIntent(
+ appId,
+ key,
+ src,
+ dst,
+ signalType,
+ isBidirectional,
+ priority
+ );
+ }
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected OpticalCircuitIntent() {
+ super();
+ this.src = null;
+ this.dst = null;
+ this.signalType = null;
+ this.isBidirectional = false;
+ }
+
+ /**
+ * Returns the source transponder port.
+ *
+ * @return source transponder port
+ */
+ public ConnectPoint getSrc() {
+ return src;
+ }
+
+ /**
+ * Returns the destination transponder port.
+ *
+ * @return source transponder port
+ */
+ public ConnectPoint getDst() {
+ return dst;
+ }
+
+ /**
+ * Returns the ODU signal type.
+ *
+ * @return ODU signal type
+ */
+ public OduCltPort.SignalType getSignalType() {
+ return signalType;
+ }
+
+ /**
+ * Returns the directionality of the intent.
+ *
+ * @return true if bidirectional, false if unidirectional
+ */
+ public boolean isBidirectional() {
+ return isBidirectional;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("src", src)
+ .add("dst", dst)
+ .add("signalType", signalType)
+ .add("isBidirectional", isBidirectional)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalConnectivityIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalConnectivityIntent.java
new file mode 100644
index 00000000..aeb0255f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalConnectivityIntent.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.OduSignalType;
+
+import java.util.Collections;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * An optical layer intent for connectivity between two OCh ports.
+ * No traffic selector or traffic treatment are needed.
+ */
+@Beta
+public final class OpticalConnectivityIntent extends Intent {
+ private final ConnectPoint src;
+ private final ConnectPoint dst;
+ private final OduSignalType signalType;
+ private final boolean isBidirectional;
+
+ /**
+ * Creates an optical connectivity intent between the specified
+ * connection points.
+ *
+ * @param appId application identification
+ * @param key intent key
+ * @param src the source transponder port
+ * @param dst the destination transponder port
+ * @param signalType signal type
+ * @param isBidirectional indicates if intent is unidirectional
+ * @param priority priority to use for flows from this intent
+ */
+ protected OpticalConnectivityIntent(ApplicationId appId,
+ Key key,
+ ConnectPoint src,
+ ConnectPoint dst,
+ OduSignalType signalType,
+ boolean isBidirectional,
+ int priority) {
+ super(appId, key, Collections.emptyList(), priority);
+ this.src = checkNotNull(src);
+ this.dst = checkNotNull(dst);
+ this.signalType = checkNotNull(signalType);
+ this.isBidirectional = isBidirectional;
+ }
+
+ /**
+ * Returns a new optical connectivity intent builder.
+ *
+ * @return host to host intent builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+
+ /**
+ * Builder for optical connectivity intents.
+ */
+ public static class Builder extends Intent.Builder {
+ private ConnectPoint src;
+ private ConnectPoint dst;
+ private OduSignalType signalType;
+ private boolean isBidirectional;
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the source for the intent that will be built.
+ *
+ * @param src source to use for built intent
+ * @return this builder
+ */
+ public Builder src(ConnectPoint src) {
+ this.src = src;
+ return this;
+ }
+
+ /**
+ * Sets the destination for the intent that will be built.
+ *
+ * @param dst dest to use for built intent
+ * @return this builder
+ */
+ public Builder dst(ConnectPoint dst) {
+ this.dst = dst;
+ return this;
+ }
+
+ /**
+ * Sets the ODU signal type for the intent that will be built.
+ *
+ * @param signalType ODU signal type
+ * @return this builder
+ */
+ public Builder signalType(OduSignalType signalType) {
+ this.signalType = signalType;
+ return this;
+ }
+
+ /**
+ * Sets the directionality of the intent.
+ *
+ * @param isBidirectional true if bidirectional, false if unidirectional
+ * @return this builder
+ */
+ public Builder bidirectional(boolean isBidirectional) {
+ this.isBidirectional = isBidirectional;
+ return this;
+ }
+
+ /**
+ * Builds an optical connectivity intent from the accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public OpticalConnectivityIntent build() {
+
+ return new OpticalConnectivityIntent(
+ appId,
+ key,
+ src,
+ dst,
+ signalType,
+ isBidirectional,
+ priority
+ );
+ }
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected OpticalConnectivityIntent() {
+ super();
+ this.src = null;
+ this.dst = null;
+ this.signalType = null;
+ this.isBidirectional = false;
+ }
+
+ /**
+ * Returns the source transponder port.
+ *
+ * @return source transponder port
+ */
+ public ConnectPoint getSrc() {
+ return src;
+ }
+
+ /**
+ * Returns the destination transponder port.
+ *
+ * @return source transponder port
+ */
+ public ConnectPoint getDst() {
+ return dst;
+ }
+
+ /**
+ * Returns the ODU signal type.
+ *
+ * @return ODU signal type
+ */
+ public OduSignalType getSignalType() {
+ return signalType;
+ }
+
+ /**
+ * Returns the directionality of the intent.
+ *
+ * @return true if bidirectional, false if unidirectional
+ */
+ public boolean isBidirectional() {
+ return isBidirectional;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("src", src)
+ .add("dst", dst)
+ .add("signalType", signalType)
+ .add("isBidirectional", isBidirectional)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalPathIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalPathIntent.java
new file mode 100644
index 00000000..5a5461cb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/OpticalPathIntent.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.Path;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * An optical layer intent with explicitly selected path.
+ */
+@Beta
+public final class OpticalPathIntent extends Intent {
+
+ private final ConnectPoint src;
+ private final ConnectPoint dst;
+ private final Path path;
+ private final OchSignal lambda;
+ private final OchSignalType signalType;
+ private final boolean isBidirectional;
+
+ private OpticalPathIntent(ApplicationId appId,
+ Key key,
+ ConnectPoint src,
+ ConnectPoint dst,
+ Path path,
+ OchSignal lambda,
+ OchSignalType signalType,
+ boolean isBidirectional,
+ int priority) {
+ super(appId, key, ImmutableSet.copyOf(path.links()), priority);
+ this.src = checkNotNull(src);
+ this.dst = checkNotNull(dst);
+ this.path = checkNotNull(path);
+ this.lambda = checkNotNull(lambda);
+ this.signalType = checkNotNull(signalType);
+ this.isBidirectional = isBidirectional;
+ }
+
+ protected OpticalPathIntent() {
+ this.src = null;
+ this.dst = null;
+ this.path = null;
+ this.lambda = null;
+ this.signalType = null;
+ this.isBidirectional = true;
+ }
+
+ /**
+ * Returns a new optical connectivity intent builder.
+ *
+ * @return host to host intent builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+
+ /**
+ * Builder for optical path intents.
+ */
+ public static class Builder extends Intent.Builder {
+ private ConnectPoint src;
+ private ConnectPoint dst;
+ private Path path;
+ private OchSignal lambda;
+ private OchSignalType signalType;
+ private boolean isBidirectional;
+ Key key;
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the source for the intent that will be built.
+ *
+ * @param src source to use for built intent
+ * @return this builder
+ */
+ public Builder src(ConnectPoint src) {
+ this.src = src;
+ return this;
+ }
+
+ /**
+ * Sets the destination for the intent that will be built.
+ *
+ * @param dst dest to use for built intent
+ * @return this builder
+ */
+ public Builder dst(ConnectPoint dst) {
+ this.dst = dst;
+ return this;
+ }
+
+ /**
+ * Sets the path for the intent that will be built.
+ *
+ * @param path path to use for built intent
+ * @return this builder
+ */
+ public Builder path(Path path) {
+ this.path = path;
+ return this;
+ }
+
+ /**
+ * Sets the optical channel (lambda) for the intent that will be built.
+ *
+ * @param lambda the optical channel
+ * @return this builder
+ */
+ public Builder lambda(OchSignal lambda) {
+ this.lambda = lambda;
+ return this;
+ }
+
+ /**
+ * Sets the optical signal type for the intent that will be built.
+ *
+ * @param signalType the optical signal type
+ * @return this builder
+ */
+ public Builder signalType(OchSignalType signalType) {
+ this.signalType = signalType;
+ return this;
+ }
+
+ /**
+ * Sets the intent's direction.
+ *
+ * @param isBidirectional indicates if intent is bidirectional
+ * @return this builder
+ */
+ public Builder bidirectional(boolean isBidirectional) {
+ this.isBidirectional = isBidirectional;
+ return this;
+ }
+
+ /**
+ * Builds an optical path intent from the accumulated parameters.
+ *
+ * @return optical path intent
+ */
+ public OpticalPathIntent build() {
+
+ return new OpticalPathIntent(
+ appId,
+ key,
+ src,
+ dst,
+ path,
+ lambda,
+ signalType,
+ isBidirectional,
+ priority
+ );
+ }
+ }
+
+
+ public ConnectPoint src() {
+ return src;
+ }
+
+ public ConnectPoint dst() {
+ return dst;
+ }
+
+ public Path path() {
+ return path;
+ }
+
+ public OchSignal lambda() {
+ return lambda;
+ }
+
+ public OchSignalType signalType() {
+ return signalType;
+ }
+
+ public boolean isBidirectional() {
+ return isBidirectional;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("appId", appId())
+ .add("key", key())
+ .add("resources", resources())
+ .add("ingressPort", src)
+ .add("egressPort", dst)
+ .add("path", path)
+ .add("lambda", lambda)
+ .add("signalType", signalType)
+ .add("isBidirectional", isBidirectional)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionEvent.java
new file mode 100644
index 00000000..c79a3818
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionEvent.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Partition event.
+ */
+//TODO change String into a proper object type
+@Beta
+public class PartitionEvent extends AbstractEvent<PartitionEvent.Type, String> {
+
+ public enum Type {
+ LEADER_CHANGED
+ }
+
+ public PartitionEvent(Type type, String partition) {
+ super(type, partition);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionEventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionEventListener.java
new file mode 100644
index 00000000..5f1da334
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionEventListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving device partition-related events.
+ */
+@Beta
+public interface PartitionEventListener extends EventListener<PartitionEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionService.java
new file mode 100644
index 00000000..02ccccac
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PartitionService.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.event.ListenerService;
+
+/**
+ * Service for interacting with the partition-to-instance assignments.
+ */
+@Beta
+public interface PartitionService
+ extends ListenerService<PartitionEvent, PartitionEventListener> {
+
+ /**
+ * Returns whether the given intent key is in a partition owned by this
+ * instance or not.
+ *
+ * @param intentKey intent key to query
+ * @return true if the key is owned by this instance, otherwise false
+ */
+ boolean isMine(Key intentKey);
+
+ /**
+ * Returns the leader for a particular key.
+ *
+ * @param intentKey intent key to query
+ * @return the leader node
+ */
+ NodeId getLeader(Key intentKey);
+
+ // TODO add API for rebalancing partitions
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java
new file mode 100644
index 00000000..dffbabfe
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import java.util.List;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Abstraction of explicitly path specified connectivity intent.
+ */
+@Beta
+public class PathIntent extends ConnectivityIntent {
+
+ private final Path path;
+
+ /**
+ * Creates a new point-to-point intent with the supplied ingress/egress
+ * ports and using the specified explicit path.
+ *
+ * @param appId application identifier
+ * @param selector traffic selector
+ * @param treatment treatment
+ * @param path traversed links
+ * @param constraints optional list of constraints
+ * @param priority priority to use for the generated flows
+ * @throws NullPointerException {@code path} is null
+ */
+ protected PathIntent(ApplicationId appId,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ Path path,
+ List<Constraint> constraints,
+ int priority) {
+ super(appId, null, resources(path.links()), selector, treatment, constraints,
+ priority);
+ PathIntent.validate(path.links());
+ this.path = path;
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected PathIntent() {
+ super();
+ this.path = null;
+ }
+
+ /**
+ * Returns a new host to host intent builder.
+ *
+ * @return host to host intent builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of a host to host intent.
+ */
+ public static class Builder extends ConnectivityIntent.Builder {
+ Path path;
+
+ protected Builder() {
+ // Hide default constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the path of the intent that will be built.
+ *
+ * @param path path for the intent
+ * @return this builder
+ */
+ public Builder path(Path path) {
+ this.path = path;
+ return this;
+ }
+
+ /**
+ * Builds a path intent from the accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public PathIntent build() {
+
+ return new PathIntent(
+ appId,
+ selector,
+ treatment,
+ path,
+ constraints,
+ priority
+ );
+ }
+ }
+
+
+
+ // NOTE: This methods takes linear time with the number of links.
+ /**
+ * Validates that source element ID and destination element ID of a link are
+ * different for the specified all links and that destination element ID of a link and source
+ * element ID of the next adjacent source element ID are same for the specified all links.
+ *
+ * @param links links to be validated
+ */
+ public static void validate(List<Link> links) {
+ checkArgument(Iterables.all(links, new Predicate<Link>() {
+ @Override
+ public boolean apply(Link link) {
+ return !link.src().elementId().equals(link.dst().elementId());
+ }
+ }), "element of src and dst in a link must be different: {}", links);
+
+ boolean adjacentSame = true;
+ for (int i = 0; i < links.size() - 1; i++) {
+ if (!links.get(i).dst().elementId().equals(links.get(i + 1).src().elementId())) {
+ adjacentSame = false;
+ break;
+ }
+ }
+ checkArgument(adjacentSame, "adjacent links must share the same element: {}", links);
+ }
+
+ /**
+ * Returns the links which the traffic goes along.
+ *
+ * @return traversed links
+ */
+ public Path path() {
+ return path;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("constraints", constraints())
+ .add("path", path)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PointToPointIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PointToPointIntent.java
new file mode 100644
index 00000000..d3f7529d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PointToPointIntent.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import com.google.common.base.MoreObjects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of point-to-point connectivity.
+ */
+@Beta
+public final class PointToPointIntent extends ConnectivityIntent {
+
+ private final ConnectPoint ingressPoint;
+ private final ConnectPoint egressPoint;
+
+ /**
+ * Returns a new point to point intent builder. The application id,
+ * ingress point and egress point are required fields. If they are
+ * not set by calls to the appropriate methods, an exception will
+ * be thrown.
+ *
+ * @return point to point builder
+ */
+ public static PointToPointIntent.Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of a point to point intent.
+ */
+ public static final class Builder extends ConnectivityIntent.Builder {
+ ConnectPoint ingressPoint;
+ ConnectPoint egressPoint;
+
+ private Builder() {
+ // Hide constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the ingress point of the point to point intent that will be built.
+ *
+ * @param ingressPoint ingress connect point
+ * @return this builder
+ */
+ public Builder ingressPoint(ConnectPoint ingressPoint) {
+ this.ingressPoint = ingressPoint;
+ return this;
+ }
+
+ /**
+ * Sets the egress point of the point to point intent that will be built.
+ *
+ * @param egressPoint egress connect point
+ * @return this builder
+ */
+ public Builder egressPoint(ConnectPoint egressPoint) {
+ this.egressPoint = egressPoint;
+ return this;
+ }
+
+ /**
+ * Builds a point to point intent from the accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public PointToPointIntent build() {
+
+ return new PointToPointIntent(
+ appId,
+ key,
+ selector,
+ treatment,
+ ingressPoint,
+ egressPoint,
+ constraints,
+ priority
+ );
+ }
+ }
+
+
+
+ /**
+ * Creates a new point-to-point intent with the supplied ingress/egress
+ * ports and constraints.
+ *
+ * @param appId application identifier
+ * @param key key of the intent
+ * @param selector traffic selector
+ * @param treatment treatment
+ * @param ingressPoint ingress port
+ * @param egressPoint egress port
+ * @param constraints optional list of constraints
+ * @param priority priority to use for flows generated by this intent
+ * @throws NullPointerException if {@code ingressPoint} or
+ * {@code egressPoints} or {@code appId} is null.
+ */
+ private PointToPointIntent(ApplicationId appId,
+ Key key,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ ConnectPoint ingressPoint,
+ ConnectPoint egressPoint,
+ List<Constraint> constraints,
+ int priority) {
+ super(appId, key, Collections.emptyList(), selector, treatment, constraints,
+ priority);
+
+ checkArgument(!ingressPoint.equals(egressPoint),
+ "ingress and egress should be different (ingress: %s, egress: %s)", ingressPoint, egressPoint);
+
+ this.ingressPoint = checkNotNull(ingressPoint);
+ this.egressPoint = checkNotNull(egressPoint);
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected PointToPointIntent() {
+ super();
+ this.ingressPoint = null;
+ this.egressPoint = null;
+ }
+
+ /**
+ * Returns the port on which the ingress traffic should be connected to
+ * the egress.
+ *
+ * @return ingress port
+ */
+ public ConnectPoint ingressPoint() {
+ return ingressPoint;
+ }
+
+ /**
+ * Returns the port on which the traffic should egress.
+ *
+ * @return egress port
+ */
+ public ConnectPoint egressPoint() {
+ return egressPoint;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("ingress", ingressPoint)
+ .add("egress", egressPoint)
+ .add("constraints", constraints())
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/SinglePointToMultiPointIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/SinglePointToMultiPointIntent.java
new file mode 100644
index 00000000..de555cf0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/SinglePointToMultiPointIntent.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of single source, multiple destination connectivity intent.
+ */
+@Beta
+public final class SinglePointToMultiPointIntent extends ConnectivityIntent {
+
+ private final ConnectPoint ingressPoint;
+ private final Set<ConnectPoint> egressPoints;
+
+ /**
+ * Creates a new single-to-multi point connectivity intent.
+ *
+ * @param appId application identifier
+ * @param key intent key
+ * @param selector traffic selector
+ * @param treatment treatment
+ * @param ingressPoint port on which traffic will ingress
+ * @param egressPoints set of ports on which traffic will egress
+ * @param constraints constraints to apply to the intent
+ * @param priority priority to use for flows generated by this intent
+ * @throws NullPointerException if {@code ingressPoint} or
+ * {@code egressPoints} is null
+ * @throws IllegalArgumentException if the size of {@code egressPoints} is
+ * not more than 1
+ */
+ private SinglePointToMultiPointIntent(ApplicationId appId,
+ Key key,
+ TrafficSelector selector, TrafficTreatment treatment,
+ ConnectPoint ingressPoint, Set<ConnectPoint> egressPoints,
+ List<Constraint> constraints,
+ int priority) {
+ super(appId, key, Collections.emptyList(), selector, treatment, constraints,
+ priority);
+ checkNotNull(egressPoints);
+ checkNotNull(ingressPoint);
+ checkArgument(!egressPoints.isEmpty(), "Egress point set cannot be empty");
+ checkArgument(!egressPoints.contains(ingressPoint),
+ "Set of egresses should not contain ingress (ingress: %s)", ingressPoint);
+
+ this.ingressPoint = checkNotNull(ingressPoint);
+ this.egressPoints = egressPoints;
+ }
+
+ /**
+ * Returns a new single point to multi point intent builder. The application id,
+ * ingress point and egress points are required fields. If they are
+ * not set by calls to the appropriate methods, an exception will
+ * be thrown.
+ *
+ * @return single point to multi point builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of a single point to multi point intent.
+ */
+ public static final class Builder extends ConnectivityIntent.Builder {
+ ConnectPoint ingressPoint;
+ Set<ConnectPoint> egressPoints;
+
+ private Builder() {
+ // Hide constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the ingress point of the single point to multi point intent
+ * that will be built.
+ *
+ * @param ingressPoint ingress connect point
+ * @return this builder
+ */
+ public Builder ingressPoint(ConnectPoint ingressPoint) {
+ this.ingressPoint = ingressPoint;
+ return this;
+ }
+
+ /**
+ * Sets the egress points of the single point to multi point intent
+ * that will be built.
+ *
+ * @param egressPoints egress connect points
+ * @return this builder
+ */
+ public Builder egressPoints(Set<ConnectPoint> egressPoints) {
+ this.egressPoints = ImmutableSet.copyOf(egressPoints);
+ return this;
+ }
+
+ /**
+ * Builds a single point to multi point intent from the
+ * accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public SinglePointToMultiPointIntent build() {
+
+ return new SinglePointToMultiPointIntent(
+ appId,
+ key,
+ selector,
+ treatment,
+ ingressPoint,
+ egressPoints,
+ constraints,
+ priority
+ );
+ }
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected SinglePointToMultiPointIntent() {
+ super();
+ this.ingressPoint = null;
+ this.egressPoints = null;
+ }
+
+ /**
+ * Returns the port on which the ingress traffic should be connected to the
+ * egress.
+ *
+ * @return ingress port
+ */
+ public ConnectPoint ingressPoint() {
+ return ingressPoint;
+ }
+
+ /**
+ * Returns the set of ports on which the traffic should egress.
+ *
+ * @return set of egress ports
+ */
+ public Set<ConnectPoint> egressPoints() {
+ return egressPoints;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("ingress", ingressPoint)
+ .add("egress", egressPoints)
+ .add("constraints", constraints())
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/TwoWayP2PIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/TwoWayP2PIntent.java
new file mode 100644
index 00000000..b9f126f4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/TwoWayP2PIntent.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent;
+
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import com.google.common.base.MoreObjects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of bidirectional connectivity between two points in the network.
+ */
+@Beta
+public final class TwoWayP2PIntent extends ConnectivityIntent {
+
+ private final ConnectPoint one;
+ private final ConnectPoint two;
+
+
+ /**
+ * Creates a new host-to-host intent with the supplied host pair.
+ *
+ * @param appId application identifier
+ * @param key intent key
+ * @param one first host
+ * @param two second host
+ * @param selector action
+ * @param treatment ingress port
+ * @param constraints optional prioritized list of path selection constraints
+ * @param priority priority to use for flows generated by this intent
+ * @throws NullPointerException if {@code one} or {@code two} is null.
+ */
+ private TwoWayP2PIntent(ApplicationId appId, Key key,
+ ConnectPoint one, ConnectPoint two,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ List<Constraint> constraints,
+ int priority) {
+ super(appId, key, Collections.emptyList(), selector, treatment, constraints,
+ priority);
+
+ // TODO: consider whether the case one and two are same is allowed
+ this.one = checkNotNull(one);
+ this.two = checkNotNull(two);
+
+ }
+
+ /**
+ * Returns a new two way intent builder.
+ *
+ * @return two way intent builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder of a point to point intent.
+ */
+ public static final class Builder extends ConnectivityIntent.Builder {
+ ConnectPoint one;
+ ConnectPoint two;
+
+ private Builder() {
+ // Hide constructor
+ }
+
+ @Override
+ public Builder appId(ApplicationId appId) {
+ return (Builder) super.appId(appId);
+ }
+
+ @Override
+ public Builder key(Key key) {
+ return (Builder) super.key(key);
+ }
+
+ @Override
+ public Builder selector(TrafficSelector selector) {
+ return (Builder) super.selector(selector);
+ }
+
+ @Override
+ public Builder treatment(TrafficTreatment treatment) {
+ return (Builder) super.treatment(treatment);
+ }
+
+ @Override
+ public Builder constraints(List<Constraint> constraints) {
+ return (Builder) super.constraints(constraints);
+ }
+
+ @Override
+ public Builder priority(int priority) {
+ return (Builder) super.priority(priority);
+ }
+
+ /**
+ * Sets the first connection point of the two way intent that will be built.
+ *
+ * @param one first connect point
+ * @return this builder
+ */
+ public Builder one(ConnectPoint one) {
+ this.one = one;
+ return this;
+ }
+
+ /**
+ * Sets the second connection point of the two way intent that will be built.
+ *
+ * @param two second connect point
+ * @return this builder
+ */
+ public Builder two(ConnectPoint two) {
+ this.two = two;
+ return this;
+ }
+
+ /**
+ * Builds a point to point intent from the accumulated parameters.
+ *
+ * @return point to point intent
+ */
+ public TwoWayP2PIntent build() {
+
+ return new TwoWayP2PIntent(
+ appId,
+ key,
+ one,
+ two,
+ selector,
+ treatment,
+ constraints,
+ priority
+ );
+ }
+ }
+
+ /**
+ * Returns identifier of the first host.
+ *
+ * @return first host identifier
+ */
+ public ConnectPoint one() {
+ return one;
+ }
+
+ /**
+ * Returns identifier of the second host.
+ *
+ * @return second host identifier
+ */
+ public ConnectPoint two() {
+ return two;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("key", key())
+ .add("appId", appId())
+ .add("priority", priority())
+ .add("resources", resources())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("constraints", constraints())
+ .add("one", one)
+ .add("two", two)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/AnnotationConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/AnnotationConstraint.java
new file mode 100644
index 00000000..f5439efd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/AnnotationConstraint.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.Link;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+import java.util.Objects;
+
+import static org.onosproject.net.AnnotationKeys.getAnnotatedValue;
+
+/**
+ * Constraint that evaluates an arbitrary link annotated value is under the specified threshold.
+ */
+@Beta
+public class AnnotationConstraint extends BooleanConstraint {
+
+ private final String key;
+ private final double threshold;
+
+ /**
+ * Creates a new constraint to keep the value for the specified key
+ * of link annotation under the threshold.
+ *
+ * @param key key of link annotation
+ * @param threshold threshold value of the specified link annotation
+ */
+ public AnnotationConstraint(String key, double threshold) {
+ this.key = key;
+ this.threshold = threshold;
+ }
+
+ // Constructor for serialization
+ private AnnotationConstraint() {
+ this.key = "";
+ this.threshold = 0;
+ }
+
+ /**
+ * Returns the key of link annotation this constraint designates.
+ * @return key of link annotation
+ */
+ public String key() {
+ return key;
+ }
+
+ /**
+ * Returns the threshold this constraint ensures as link annotated value.
+ *
+ * @return threshold as link annotated value
+ */
+ public double threshold() {
+ return threshold;
+ }
+
+ @Override
+ public boolean isValid(Link link, LinkResourceService resourceService) {
+ double value = getAnnotatedValue(link, key);
+
+ return value <= threshold;
+ }
+
+ @Override
+ public double cost(Link link, LinkResourceService resourceService) {
+ if (isValid(link, resourceService)) {
+ return getAnnotatedValue(link, key);
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(key, threshold);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof AnnotationConstraint)) {
+ return false;
+ }
+
+ final AnnotationConstraint other = (AnnotationConstraint) obj;
+ return Objects.equals(this.key, other.key) && Objects.equals(this.threshold, other.threshold);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("key", key)
+ .add("threshold", threshold)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/AsymmetricPathConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/AsymmetricPathConstraint.java
new file mode 100644
index 00000000..e0f8614c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/AsymmetricPathConstraint.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Constraint that serves as a request for asymmetric bi-directional path.
+ */
+@Beta
+public class AsymmetricPathConstraint implements Constraint {
+
+ @Override
+ public double cost(Link link, LinkResourceService resourceService) {
+ return 1;
+ }
+
+ @Override
+ public boolean validate(Path path, LinkResourceService resourceService) {
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(true);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java
new file mode 100644
index 00000000..43b8e4b1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.Link;
+import org.onosproject.net.resource.link.BandwidthResource;
+import org.onosproject.net.resource.link.BandwidthResourceRequest;
+import org.onosproject.net.resource.link.LinkResourceService;
+import org.onosproject.net.resource.ResourceRequest;
+import org.onosproject.net.resource.ResourceType;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Constraint that evaluates links based on available bandwidths.
+ */
+@Beta
+public class BandwidthConstraint extends BooleanConstraint {
+
+ private final BandwidthResource bandwidth;
+
+ /**
+ * Creates a new bandwidth constraint.
+ *
+ * @param bandwidth required bandwidth
+ */
+ public BandwidthConstraint(BandwidthResource bandwidth) {
+ this.bandwidth = checkNotNull(bandwidth, "Bandwidth cannot be null");
+ }
+
+ // Constructor for serialization
+ private BandwidthConstraint() {
+ this.bandwidth = null;
+ }
+
+ @Override
+ public boolean isValid(Link link, LinkResourceService resourceService) {
+ for (ResourceRequest request : resourceService.getAvailableResources(link)) {
+ if (request.type() == ResourceType.BANDWIDTH) {
+ BandwidthResourceRequest brr = (BandwidthResourceRequest) request;
+ if (brr.bandwidth().toDouble() >= bandwidth.toDouble()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the bandwidth required by this constraint.
+ *
+ * @return required bandwidth
+ */
+ public BandwidthResource bandwidth() {
+ return bandwidth;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(bandwidth);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final BandwidthConstraint other = (BandwidthConstraint) obj;
+ return Objects.equals(this.bandwidth, other.bandwidth);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("bandwidth", bandwidth).toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BooleanConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BooleanConstraint.java
new file mode 100644
index 00000000..f1d4ad9f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BooleanConstraint.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+/**
+ * Abstract base class for various constraints that evaluate link viability
+ * in a yes/no fashion.
+ */
+@Beta
+public abstract class BooleanConstraint implements Constraint {
+
+ /**
+ * Returns true if the specified link satisfies the constraint.
+ *
+ * @param link link to be validated
+ * @param resourceService resource service for checking available link resources
+ * @return true if link is viable
+ */
+ public abstract boolean isValid(Link link, LinkResourceService resourceService);
+
+ /**
+ * {@inheritDoc}
+ *
+ * Negative return value means the specified link does not satisfy this constraint.
+ *
+ * @param link {@inheritDoc}
+ * @param resourceService {@inheritDoc}
+ * @return {@inheritDoc}
+ */
+ @Override
+ public double cost(Link link, LinkResourceService resourceService) {
+ return isValid(link, resourceService) ? +1 : -1;
+ }
+
+ @Override
+ public boolean validate(Path path, LinkResourceService resourceService) {
+ for (Link link : path.links()) {
+ if (!isValid(link, resourceService)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LambdaConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LambdaConstraint.java
new file mode 100644
index 00000000..9dd813b2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LambdaConstraint.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.Link;
+import org.onosproject.net.resource.link.LambdaResource;
+import org.onosproject.net.resource.link.LinkResourceService;
+import org.onosproject.net.resource.ResourceRequest;
+import org.onosproject.net.resource.ResourceType;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Constraint that evaluates links based on available lambda.
+ */
+@Beta
+public class LambdaConstraint extends BooleanConstraint {
+
+ private final LambdaResource lambda;
+
+ /**
+ * Creates a new optical lambda constraint.
+ *
+ * @param lambda optional lambda to indicate a specific lambda
+ */
+ public LambdaConstraint(LambdaResource lambda) {
+ this.lambda = lambda;
+ }
+
+ // Constructor for serialization
+ private LambdaConstraint() {
+ this.lambda = null;
+ }
+
+ @Override
+ public boolean isValid(Link link, LinkResourceService resourceService) {
+ for (ResourceRequest request : resourceService.getAvailableResources(link)) {
+ if (request.type() == ResourceType.LAMBDA) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the lambda required by this constraint.
+ *
+ * @return required lambda
+ */
+ public LambdaResource lambda() {
+ return lambda;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(lambda);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final LambdaConstraint other = (LambdaConstraint) obj;
+ return Objects.equals(this.lambda, other.lambda);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("lambda", lambda).toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LatencyConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LatencyConstraint.java
new file mode 100644
index 00000000..54eb4ea5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LatencyConstraint.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
+import java.util.Objects;
+
+import static org.onosproject.net.AnnotationKeys.LATENCY;
+import static org.onosproject.net.AnnotationKeys.getAnnotatedValue;
+
+/**
+ * Constraint that evaluates the latency through a path.
+ */
+@Beta
+public class LatencyConstraint implements Constraint {
+
+ private final Duration latency;
+
+ /**
+ * Creates a new constraint to keep under specified latency through a path.
+ * @param latency latency to be kept
+ */
+ public LatencyConstraint(Duration latency) {
+ this.latency = latency;
+ }
+
+ // Constructor for serialization
+ private LatencyConstraint() {
+ this.latency = Duration.ZERO;
+ }
+
+ public Duration latency() {
+ return latency;
+ }
+
+ @Override
+ public double cost(Link link, LinkResourceService resourceService) {
+ return getAnnotatedValue(link, LATENCY);
+ }
+
+ @Override
+ public boolean validate(Path path, LinkResourceService resourceService) {
+ double pathLatency = path.links().stream().mapToDouble(link -> cost(link, resourceService)).sum();
+ return Duration.of((long) pathLatency, ChronoUnit.MICROS).compareTo(latency) <= 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(latency);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof LatencyConstraint)) {
+ return false;
+ }
+
+ final LatencyConstraint that = (LatencyConstraint) obj;
+ return Objects.equals(this.latency, that.latency);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("latency", latency)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LinkTypeConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LinkTypeConstraint.java
new file mode 100644
index 00000000..ffa4405b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LinkTypeConstraint.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.Link;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+import java.util.Objects;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Constraint that evaluates links based on their type.
+ */
+@Beta
+public class LinkTypeConstraint extends BooleanConstraint {
+
+ private final Set<Link.Type> types;
+ private final boolean isInclusive;
+
+ /**
+ * Creates a new constraint for requesting connectivity using or avoiding
+ * the specified link types.
+ *
+ * @param inclusive indicates whether the given link types are to be
+ * permitted or avoided
+ * @param types link types
+ */
+ public LinkTypeConstraint(boolean inclusive, Link.Type... types) {
+ checkNotNull(types, "Link types cannot be null");
+ checkArgument(types.length > 0, "There must be more than one type");
+ this.types = ImmutableSet.copyOf(types);
+ this.isInclusive = inclusive;
+ }
+
+ // Constructor for serialization
+ private LinkTypeConstraint() {
+ this.types = null;
+ this.isInclusive = false;
+ }
+
+ @Override
+ public boolean isValid(Link link, LinkResourceService resourceService) {
+ boolean contains = types.contains(link.type());
+ return isInclusive ? contains : !contains;
+ }
+
+ /**
+ * Returns the set of link types.
+ *
+ * @return set of link types
+ */
+ public Set<Link.Type> types() {
+ return types;
+ }
+
+ /**
+ * Indicates if the constraint is inclusive or exclusive.
+ *
+ * @return true if inclusive
+ */
+ public boolean isInclusive() {
+ return isInclusive;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(types, isInclusive);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final LinkTypeConstraint other = (LinkTypeConstraint) obj;
+ return Objects.equals(this.types, other.types) && Objects.equals(this.isInclusive, other.isInclusive);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("inclusive", isInclusive)
+ .add("types", types)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/ObstacleConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/ObstacleConstraint.java
new file mode 100644
index 00000000..cb1e6b2b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/ObstacleConstraint.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Constraint that evaluates elements not passed through.
+ */
+@Beta
+public class ObstacleConstraint extends BooleanConstraint {
+
+ private final Set<DeviceId> obstacles;
+
+ /**
+ * Creates a new constraint that the specified device are not passed through.
+ * @param obstacles devices not to be passed
+ */
+ public ObstacleConstraint(DeviceId... obstacles) {
+ this.obstacles = ImmutableSet.copyOf(obstacles);
+ }
+
+ // Constructor for serialization
+ private ObstacleConstraint() {
+ this.obstacles = Collections.emptySet();
+ }
+
+ /**
+ * Returns the obstacle device ids.
+ *
+ * @return Set of obstacle device ids
+ */
+ public Set<DeviceId> obstacles() {
+ return obstacles;
+ }
+
+ @Override
+ public boolean isValid(Link link, LinkResourceService resourceService) {
+ DeviceId src = link.src().deviceId();
+ DeviceId dst = link.dst().deviceId();
+
+ return !(obstacles.contains(src) || obstacles.contains(dst));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(obstacles);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof ObstacleConstraint)) {
+ return false;
+ }
+
+ final ObstacleConstraint that = (ObstacleConstraint) obj;
+ return Objects.equals(this.obstacles, that.obstacles);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("obstacles", obstacles)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/PartialFailureConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/PartialFailureConstraint.java
new file mode 100644
index 00000000..827859b1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/PartialFailureConstraint.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.intent.ConnectivityIntent;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+/**
+ * A constraint that allows intents that can only be partially compiled
+ * (i.e. MultiPointToSinglePointIntent or SinglePointToMultiPointIntent)
+ * to be installed when some endpoints or paths are not found.
+ */
+public class PartialFailureConstraint implements Constraint {
+ @Override
+ public double cost(Link link, LinkResourceService resourceService) {
+ return 1;
+ }
+
+ @Override
+ public boolean validate(Path path, LinkResourceService resourceService) {
+ return true;
+ }
+
+ public static boolean intentAllowsPartialFailure(Intent intent) {
+ if (intent instanceof ConnectivityIntent) {
+ ConnectivityIntent connectivityIntent = (ConnectivityIntent) intent;
+ return connectivityIntent.constraints().stream()
+ .anyMatch(c -> c instanceof PartialFailureConstraint);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/WaypointConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/WaypointConstraint.java
new file mode 100644
index 00000000..1acf6dfe
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/WaypointConstraint.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.constraint;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Constraint that evaluates elements passed through in order.
+ */
+@Beta
+public class WaypointConstraint implements Constraint {
+
+ private final List<DeviceId> waypoints;
+
+ /**
+ * Creates a new waypoint constraint.
+ *
+ * @param waypoints waypoints
+ */
+ public WaypointConstraint(DeviceId... waypoints) {
+ checkNotNull(waypoints, "waypoints cannot be null");
+ checkArgument(waypoints.length > 0, "length of waypoints should be more than 0");
+ this.waypoints = ImmutableList.copyOf(waypoints);
+ }
+
+ // Constructor for serialization
+ private WaypointConstraint() {
+ this.waypoints = Collections.emptyList();
+ }
+
+ public List<DeviceId> waypoints() {
+ return waypoints;
+ }
+
+ @Override
+ public double cost(Link link, LinkResourceService resourceService) {
+ // Always consider the number of hops
+ return 1;
+ }
+
+ @Override
+ public boolean validate(Path path, LinkResourceService resourceService) {
+ LinkedList<DeviceId> waypoints = new LinkedList<>(this.waypoints);
+ DeviceId current = waypoints.poll();
+ // This is safe because Path class ensures the number of links are more than 0
+ Link firstLink = path.links().get(0);
+ if (firstLink.src().elementId().equals(current)) {
+ current = waypoints.poll();
+ }
+
+ for (Link link : path.links()) {
+ if (link.dst().elementId().equals(current)) {
+ current = waypoints.poll();
+ // Empty waypoints means passing through all waypoints in the specified order
+ if (current == null) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(waypoints);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof WaypointConstraint)) {
+ return false;
+ }
+
+ final WaypointConstraint that = (WaypointConstraint) obj;
+ return Objects.equals(this.waypoints, that.waypoints);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("waypoints", waypoints)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/package-info.java
new file mode 100644
index 00000000..60d8df16
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Definitions of constraints used to refine intent specifications.
+ */
+package org.onosproject.net.intent.constraint;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/package-info.java
new file mode 100644
index 00000000..a86b3118
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/package-info.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Set of abstractions for conveying high-level intents for treatment of
+ * selected network traffic by allowing applications to express the
+ * <em>what</em> rather than the <em>how</em>. This makes such instructions
+ * largely independent of topology and device specifics, thus allowing them to
+ * survive topology mutations.
+ * <p>
+ * The controller core provides a suite of built-in intents and their compilers
+ * and installers. However, the intent framework is extensible in that it allows
+ * additional intents and their compilers or installers to be added
+ * dynamically at run-time. This allows others to enhance the initial arsenal of
+ * connectivity and policy-based intents available in base controller software.
+ * </p>
+ * <p>
+ * The following diagram depicts the state transition diagram for each top-level intent:<br>
+ * <img src="doc-files/intent-states.png" alt="ONOS intent states">
+ * </p>
+ * <p>
+ * The controller core accepts the intent specifications and translates them, via a
+ * process referred to as intent compilation, to installable intents, which are
+ * essentially actionable operations on the network environment.
+ * These actions are carried out by intent installation process, which results
+ * in some changes to the environment, e.g. tunnel links being provisioned,
+ * flow rules being installed on the data-plane, optical lambdas being reserved.
+ * </p>
+ * <p>
+ * After an intent is submitted by an application, it will be sent immediately
+ * (but asynchronously) into a compiling phase, then to installing phase and if
+ * all goes according to plan into installed state. Once an application decides
+ * it no longer wishes the intent to hold, it can withdraw it. This describes
+ * the nominal flow. However, it may happen that some issue is encountered.
+ * For example, an application may ask for an objective that is not currently
+ * achievable, e.g. connectivity across to unconnected network segments.
+ * If this is the case, the compiling phase may fail to produce a set of
+ * installable intents and instead result in a failed compile. If this occurs,
+ * only a change in the environment can trigger a transition back to the
+ * compiling state.
+ * </p>
+ * <p>
+ * Similarly, an issue may be encountered during the installation phase in
+ * which case the framework will attempt to recompile the intent to see if an
+ * alternate approach is available. If so, the intent will be sent back to
+ * installing phase. Otherwise, it will be parked in the failed state. Another
+ * scenario that’s very likely to be encountered is where the intent is
+ * successfully compiled and installed, but due to some topology event, such
+ * as a downed or downgraded link, loss of throughput may occur or connectivity
+ * may be lost altogether, thus impacting the viability of a previously
+ * satisfied intent. If this occurs, the framework will attempt to recompile
+ * the intent, and if an alternate approach is available, its installation
+ * will be attempted. Otherwise, the original top-level intent will be parked
+ * in the failed state.
+ * </p>
+ * <p>
+ * Please note that all *ing states, depicted in orange, are transitional and
+ * are expected to last only a brief amount of time. The rest of the states
+ * are parking states where the intent may spent some time; except for the
+ * submitted state of course. There, the intent may pause, but only briefly,
+ * while the system determines where to perform the compilation or while it
+ * performs global recomputation/optimization across all prior intents.
+ * </p>
+ * <p>
+ * The figure below depicts the general interactions between different
+ * components of the intent subsystem.<br>
+ * <img src="doc-files/intent-design.png" alt="ONOS intent subsystem design">
+ * </p>
+ */
+package org.onosproject.net.intent;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/DefaultLinkDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/DefaultLinkDescription.java
new file mode 100644
index 00000000..891eb65d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/DefaultLinkDescription.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.AbstractDescription;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.SparseAnnotations;
+
+/**
+ * Default implementation of immutable link description entity.
+ */
+public class DefaultLinkDescription extends AbstractDescription
+ implements LinkDescription {
+
+ private final ConnectPoint src;
+ private final ConnectPoint dst;
+ private final Link.Type type;
+
+ /**
+ * Creates a link description using the supplied information.
+ *
+ * @param src link source
+ * @param dst link destination
+ * @param type link type
+ * @param annotations optional key/value annotations
+ */
+ public DefaultLinkDescription(ConnectPoint src, ConnectPoint dst,
+ Link.Type type, SparseAnnotations... annotations) {
+ super(annotations);
+ this.src = src;
+ this.dst = dst;
+ this.type = type;
+ }
+
+ @Override
+ public ConnectPoint src() {
+ return src;
+ }
+
+ @Override
+ public ConnectPoint dst() {
+ return dst;
+ }
+
+ @Override
+ public Link.Type type() {
+ return type;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("src", src())
+ .add("dst", dst())
+ .add("type", type()).toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkAdminService.java
new file mode 100644
index 00000000..a0b5e1e2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkAdminService.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Service for administering the inventory of infrastructure links.
+ */
+public interface LinkAdminService extends LinkService {
+
+ /**
+ * Removes all infrastructure links leading to and from the
+ * specified connection point.
+ *
+ * @param connectPoint connection point
+ */
+ void removeLinks(ConnectPoint connectPoint);
+
+ /**
+ * Removes all infrastructure links leading to and from the
+ * specified device.
+ *
+ * @param deviceId device identifier
+ */
+ void removeLinks(DeviceId deviceId);
+
+ /**
+ * Removes all links between between the specified src and
+ * dst connection points.
+ *
+ * @param src link source
+ * @param dst link destination
+ */
+ void removeLink(ConnectPoint src, ConnectPoint dst);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkDescription.java
new file mode 100644
index 00000000..f85718b7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkDescription.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Description;
+import org.onosproject.net.Link;
+
+/**
+ * Describes an infrastructure link.
+ */
+public interface LinkDescription extends Description {
+
+ /**
+ * Returns the link source.
+ *
+ * @return links source
+ */
+ ConnectPoint src();
+
+ /**
+ * Returns the link destination.
+ *
+ * @return links destination
+ */
+ ConnectPoint dst();
+
+ /**
+ * Returns the link type.
+ *
+ * @return link type
+ */
+ Link.Type type();
+
+ // Add further link attributes
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkEvent.java
new file mode 100644
index 00000000..d87bce06
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkEvent.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.Link;
+
+/**
+ * Describes infrastructure link event.
+ */
+public class LinkEvent extends AbstractEvent<LinkEvent.Type, Link> {
+
+ /**
+ * Type of link events.
+ */
+ public enum Type {
+ /**
+ * Signifies that a new link has been detected.
+ */
+ LINK_ADDED,
+
+ /**
+ * Signifies that a link has been updated or changed state.
+ */
+ LINK_UPDATED,
+
+ /**
+ * Signifies that a link has been removed.
+ */
+ LINK_REMOVED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified link and the
+ * current time.
+ *
+ * @param type link event type
+ * @param link event link subject
+ */
+ public LinkEvent(Type type, Link link) {
+ super(type, link);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified link and time.
+ *
+ * @param type link event type
+ * @param link event link subject
+ * @param time occurrence time
+ */
+ public LinkEvent(Type type, Link link, long time) {
+ super(type, link, time);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkListener.java
new file mode 100644
index 00000000..82f6bdb9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving infrastructure link related events.
+ */
+public interface LinkListener extends EventListener<LinkEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProvider.java
new file mode 100644
index 00000000..ed4348c7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProvider.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Abstraction of an entity providing information about infrastructure links
+ * to the core.
+ */
+public interface LinkProvider extends Provider {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProviderRegistry.java
new file mode 100644
index 00000000..57a05d93
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction of an infrastructure link provider registry.
+ */
+public interface LinkProviderRegistry
+ extends ProviderRegistry<LinkProvider, LinkProviderService> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProviderService.java
new file mode 100644
index 00000000..f5ef52a2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkProviderService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.ProviderService;
+
+/**
+ * Means for injecting link information into the core.
+ */
+public interface LinkProviderService extends ProviderService<LinkProvider> {
+
+ /**
+ * Signals that an infrastructure link has been detected.
+ *
+ * @param linkDescription link information
+ */
+ void linkDetected(LinkDescription linkDescription);
+
+ /**
+ * Signals that an infrastructure link has disappeared.
+ *
+ * @param linkDescription link information
+ */
+ void linkVanished(LinkDescription linkDescription);
+
+ /**
+ * Signals that infrastructure links associated with the specified
+ * connect point have vanished.
+ *
+ * @param connectPoint connect point
+ */
+ void linksVanished(ConnectPoint connectPoint);
+
+ /**
+ * Signals that infrastructure links associated with the specified
+ * device have vanished.
+ *
+ * @param deviceId device identifier
+ */
+ void linksVanished(DeviceId deviceId);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkService.java
new file mode 100644
index 00000000..c27e3110
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkService.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import java.util.Set;
+
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+
+/**
+ * Service for interacting with the inventory of infrastructure links.
+ */
+public interface LinkService
+ extends ListenerService<LinkEvent, LinkListener> {
+
+ /**
+ * Returns the count of all known infrastructure links.
+ *
+ * @return number of infrastructure links
+ */
+ int getLinkCount();
+
+ /**
+ * Returns a collection of all known infrastructure links.
+ *
+ * @return all infrastructure links
+ */
+ Iterable<Link> getLinks();
+
+ /**
+ * Returns a collection of all active infrastructure links.
+ *
+ * @return all infrastructure links
+ */
+ Iterable<Link> getActiveLinks();
+
+ /**
+ * Returns set of all infrastructure links leading to and from the
+ * specified device.
+ *
+ * @param deviceId device identifier
+ * @return set of device links
+ */
+ Set<Link> getDeviceLinks(DeviceId deviceId);
+
+ /**
+ * Returns set of all infrastructure links leading from the specified device.
+ *
+ * @param deviceId device identifier
+ * @return set of device egress links
+ */
+ Set<Link> getDeviceEgressLinks(DeviceId deviceId);
+
+ /**
+ * Returns set of all infrastructure links leading to the specified device.
+ *
+ * @param deviceId device identifier
+ * @return set of device ingress links
+ */
+ Set<Link> getDeviceIngressLinks(DeviceId deviceId);
+
+ /**
+ * Returns set of all infrastructure links leading to and from the
+ * specified connection point.
+ *
+ * @param connectPoint connection point
+ * @return set of links
+ */
+ Set<Link> getLinks(ConnectPoint connectPoint);
+
+ /**
+ * Returns set of all infrastructure links leading from the specified
+ * connection point.
+ *
+ * @param connectPoint connection point
+ * @return set of device egress links
+ */
+ Set<Link> getEgressLinks(ConnectPoint connectPoint);
+
+ /**
+ * Returns set of all infrastructure links leading to the specified
+ * connection point.
+ *
+ * @param connectPoint connection point
+ * @return set of device ingress links
+ */
+ Set<Link> getIngressLinks(ConnectPoint connectPoint);
+
+ // FIXME: I don't think this makes sense; discuss and remove or adjust return
+ // to be a Set<Link> or add Link.Type parameter
+ /**
+ * Returns the infrastructure links between the specified source
+ * and destination connection points.
+ *
+ * @param src source connection point
+ * @param dst destination connection point
+ * @return link from source to destination; null if none found
+ */
+ Link getLink(ConnectPoint src, ConnectPoint dst);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkStore.java
new file mode 100644
index 00000000..04c8773b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkStore.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.store.Store;
+
+import java.util.Set;
+
+/**
+ * Manages inventory of infrastructure links; not intended for direct use.
+ */
+public interface LinkStore extends Store<LinkEvent, LinkStoreDelegate> {
+
+ /**
+ * Returns the number of links in the store.
+ *
+ * @return number of links
+ */
+ int getLinkCount();
+
+ /**
+ * Returns an iterable collection of all links in the inventory.
+ *
+ * @return collection of all links
+ */
+ Iterable<Link> getLinks();
+
+ /**
+ * Returns all links egressing from the specified device.
+ *
+ * @param deviceId device identifier
+ * @return set of device links
+ */
+ Set<Link> getDeviceEgressLinks(DeviceId deviceId);
+
+ /**
+ * Returns all links ingressing from the specified device.
+ *
+ * @param deviceId device identifier
+ * @return set of device links
+ */
+ Set<Link> getDeviceIngressLinks(DeviceId deviceId);
+
+ /**
+ * Returns the link between the two end-points.
+ *
+ * @param src source connection point
+ * @param dst destination connection point
+ * @return link or null if one not found between the end-points
+ */
+ Link getLink(ConnectPoint src, ConnectPoint dst);
+
+ /**
+ * Returns all links egressing from the specified connection point.
+ *
+ * @param src source connection point
+ * @return set of connection point links
+ */
+ Set<Link> getEgressLinks(ConnectPoint src);
+
+ /**
+ * Returns all links ingressing to the specified connection point.
+ *
+ * @param dst destination connection point
+ * @return set of connection point links
+ */
+ Set<Link> getIngressLinks(ConnectPoint dst);
+
+ /**
+ * Creates a new link, or updates an existing one, based on the given
+ * information.
+ *
+ * @param providerId provider identity
+ * @param linkDescription link description
+ * @return create or update link event, or null if no change resulted
+ */
+ LinkEvent createOrUpdateLink(ProviderId providerId,
+ LinkDescription linkDescription);
+
+ /**
+ * Removes the link, or marks it as inactive if the link is durable,
+ * based on the specified information.
+ *
+ * @param src link source
+ * @param dst link destination
+ * @return remove or update link event, or null if no change resulted
+ */
+ LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst);
+
+ /**
+ * Removes the link based on the specified information.
+ *
+ * @param src link source
+ * @param dst link destination
+ * @return remove link event, or null if no change resulted
+ */
+ LinkEvent removeLink(ConnectPoint src, ConnectPoint dst);
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkStoreDelegate.java
new file mode 100644
index 00000000..1f66dd49
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/LinkStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.link;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Infrastructure link store delegate abstraction.
+ */
+public interface LinkStoreDelegate extends StoreDelegate<LinkEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/package-info.java
new file mode 100644
index 00000000..57aa5fa2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Infrastructure link model &amp; related services API definitions.
+ */
+package org.onosproject.net.link;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/Band.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/Band.java
new file mode 100644
index 00000000..2bfafad2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/Band.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+/**
+ * Represents a band used within a meter.
+ */
+public interface Band {
+
+ /**
+ * Specifies the type of band.
+ */
+ enum Type {
+ /**
+ * Simple rate limiter which drops packets
+ * when the rate is exceeded.
+ */
+ DROP,
+
+ /**
+ * defines a simple DiffServ policer that remark
+ * the drop precedence of the DSCP field in the
+ * IP header of the packets that exceed the band
+ * rate value.
+ */
+ REMARK
+ }
+
+ /**
+ * The rate at which this meter applies.
+ *
+ * @return the long value of the rate
+ */
+ long rate();
+
+ /**
+ * The burst size at which the meter applies.
+ *
+ * @return the long value of the size
+ */
+ long burst();
+
+ /**
+ * Only meaningful in the case of a REMARK band type.
+ * indicates by which amount the drop precedence of
+ * the packet should be increase if the band is exceeded.
+ *
+ * @return a short value
+ */
+ short dropPrecedence();
+
+ /**
+ * Signals the type of band to create.
+ *
+ * @return a band type
+ */
+ Type type();
+
+ /**
+ * Returns the packets seen by this band.
+ *
+ * @return a long value
+ */
+ long packets();
+
+ /**
+ * Return the bytes seen by this band.
+ *
+ * @return a byte counter
+ */
+ long bytes();
+
+ interface Builder {
+
+ /**
+ * Assigns a rate to this band. The units for this rate
+ * are defined in the encapsulating meter.
+ *
+ * @param rate a long value
+ * @return this
+ */
+ Builder withRate(long rate);
+
+ /**
+ * Assigns a burst size to this band. Only meaningful if
+ * the encapsulating meter is of burst type.
+ *
+ * @param burstSize a long value.
+ * @return this
+ */
+ Builder burstSize(long burstSize);
+
+ /**
+ * Assigns the drop precedence for this band. Only meaningful if
+ * the band is of REMARK type.
+ *
+ * @param prec a short value
+ * @return this
+ */
+ Builder dropPrecedence(short prec);
+
+ /**
+ * Assigns the @See Type of this band.
+ *
+ * @param type a band type
+ * @return this
+ */
+ Builder ofType(Type type);
+
+ /**
+ * Builds the band.
+ *
+ * @return a band
+ */
+ Band build();
+
+ }
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/BandEntry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/BandEntry.java
new file mode 100644
index 00000000..03145e91
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/BandEntry.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+/**
+ * Represents a stored band.
+ */
+public interface BandEntry extends Band {
+
+ /**
+ * Sets the number of packets seen by this band.
+ *
+ * @param packets a packet count
+ */
+ void setPackets(long packets);
+
+ /**
+ * Sets the number of bytes seen by this band.
+ *
+ * @param bytes a byte counter
+ */
+ void setBytes(long bytes);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultBand.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultBand.java
new file mode 100644
index 00000000..58a24766
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultBand.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * A default implementation for a Band.
+ */
+public final class DefaultBand implements Band, BandEntry {
+
+ private final Type type;
+ private final long rate;
+ //TODO: should be made optional
+ private final Long burstSize;
+ private final Short prec;
+ private long packets;
+ private long bytes;
+
+ public DefaultBand(Type type, long rate,
+ Long burstSize, Short prec) {
+ this.type = type;
+ this.rate = rate;
+ this.burstSize = burstSize;
+ this.prec = prec;
+ }
+
+ @Override
+ public long rate() {
+ return rate;
+ }
+
+ @Override
+ public long burst() {
+ return burstSize;
+ }
+
+ @Override
+ public short dropPrecedence() {
+ return prec;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public long packets() {
+ return packets;
+ }
+
+ @Override
+ public long bytes() {
+ return bytes;
+ }
+
+ @Override
+ public void setPackets(long packets) {
+ this.packets = packets;
+ }
+
+ @Override
+ public void setBytes(long bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("rate", rate)
+ .add("burst-size", burstSize)
+ .add("type", type)
+ .add("drop-precedence", prec).toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder implements Band.Builder {
+
+ private long rate;
+ private Long burstSize;
+ private Short prec;
+ private Type type;
+
+ @Override
+ public Band.Builder withRate(long rate) {
+ this.rate = rate;
+ return this;
+ }
+
+ @Override
+ public Band.Builder burstSize(long burstSize) {
+ this.burstSize = burstSize;
+ return this;
+ }
+
+ @Override
+ public Band.Builder dropPrecedence(short prec) {
+ this.prec = prec;
+ return this;
+ }
+
+ @Override
+ public Band.Builder ofType(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public DefaultBand build() {
+ checkArgument(type != Type.REMARK && prec == null,
+ "Only REMARK bands can have a precendence.");
+
+ return new DefaultBand(type, rate, burstSize, prec);
+ }
+
+
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java
new file mode 100644
index 00000000..f7d6210d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+
+import java.util.Collection;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A default implementation of a meter.
+ */
+public final class DefaultMeter implements Meter, MeterEntry {
+
+
+ private final MeterId id;
+ private final ApplicationId appId;
+ private final Unit unit;
+ private final boolean burst;
+ private final Collection<Band> bands;
+ private final DeviceId deviceId;
+
+ private MeterState state;
+ private long life;
+ private long refCount;
+ private long packets;
+ private long bytes;
+
+ private DefaultMeter(DeviceId deviceId, MeterId id, ApplicationId appId,
+ Unit unit, boolean burst,
+ Collection<Band> bands) {
+ this.deviceId = deviceId;
+ this.id = id;
+ this.appId = appId;
+ this.unit = unit;
+ this.burst = burst;
+ this.bands = bands;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public MeterId id() {
+ return id;
+ }
+
+ @Override
+ public ApplicationId appId() {
+ return appId;
+ }
+
+ @Override
+ public Unit unit() {
+ return unit;
+ }
+
+ @Override
+ public boolean isBurst() {
+ return burst;
+ }
+
+ @Override
+ public Collection<Band> bands() {
+ return bands;
+ }
+
+ @Override
+ public MeterState state() {
+ return state;
+ }
+
+ @Override
+ public long life() {
+ return life;
+ }
+
+ @Override
+ public long referenceCount() {
+ return refCount;
+ }
+
+ @Override
+ public long packetsSeen() {
+ return packets;
+ }
+
+ @Override
+ public long bytesSeen() {
+ return bytes;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public void setState(MeterState state) {
+ this.state = state;
+ }
+
+ @Override
+ public void setLife(long life) {
+ this.life = life;
+ }
+
+ @Override
+ public void setReferenceCount(long count) {
+ this.refCount = count;
+ }
+
+ @Override
+ public void setProcessedPackets(long packets) {
+ this.packets = packets;
+ }
+
+ @Override
+ public void setProcessedBytes(long bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("device", deviceId)
+ .add("id", id)
+ .add("appId", appId.name())
+ .add("unit", unit)
+ .add("isBurst", burst)
+ .add("state", state)
+ .add("bands", bands).toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DefaultMeter that = (DefaultMeter) o;
+ return Objects.equal(id, that.id) &&
+ Objects.equal(appId, that.appId) &&
+ Objects.equal(unit, that.unit) &&
+ Objects.equal(deviceId, that.deviceId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id, appId, unit, deviceId);
+ }
+
+ public static final class Builder implements Meter.Builder {
+
+ private MeterId id;
+ private ApplicationId appId;
+ private Unit unit = Unit.KB_PER_SEC;
+ private boolean burst = false;
+ private Collection<Band> bands;
+ private DeviceId deviceId;
+
+
+ @Override
+ public Meter.Builder forDevice(DeviceId deviceId) {
+ this.deviceId = deviceId;
+ return this;
+ }
+
+ @Override
+ public Meter.Builder withId(MeterId id) {
+ this.id = id;
+ return this;
+ }
+
+ @Override
+ public Meter.Builder fromApp(ApplicationId appId) {
+ this.appId = appId;
+ return this;
+ }
+
+ @Override
+ public Meter.Builder withUnit(Unit unit) {
+ this.unit = unit;
+ return this;
+ }
+
+ @Override
+ public Meter.Builder burst() {
+ this.burst = true;
+ return this;
+ }
+
+ @Override
+ public Meter.Builder withBands(Collection<Band> bands) {
+ this.bands = ImmutableSet.copyOf(bands);
+ return this;
+ }
+
+ @Override
+ public DefaultMeter build() {
+ checkNotNull(deviceId, "Must specify a device");
+ checkNotNull(bands, "Must have bands.");
+ checkArgument(bands.size() > 0, "Must have at least one band.");
+ checkNotNull(appId, "Must have an application id");
+ checkNotNull(id, "Must specify a meter id");
+ return new DefaultMeter(deviceId, id, appId, unit, burst, bands);
+ }
+
+
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java
new file mode 100644
index 00000000..94cada47
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+
+import java.util.Collection;
+import java.util.Optional;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A default implementation of a meter.
+ */
+public final class DefaultMeterRequest implements MeterRequest {
+
+
+
+ private final ApplicationId appId;
+ private final Meter.Unit unit;
+ private final boolean burst;
+ private final Collection<Band> bands;
+ private final DeviceId deviceId;
+ private final Optional<MeterContext> context;
+ private final Type op;
+
+ private DefaultMeterRequest(DeviceId deviceId, ApplicationId appId,
+ Meter.Unit unit, boolean burst,
+ Collection<Band> bands, MeterContext context, Type op) {
+ this.deviceId = deviceId;
+ this.appId = appId;
+ this.unit = unit;
+ this.burst = burst;
+ this.bands = bands;
+ this.context = Optional.ofNullable(context);
+ this.op = op;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public ApplicationId appId() {
+ return appId;
+ }
+
+ @Override
+ public Meter.Unit unit() {
+ return unit;
+ }
+
+ @Override
+ public boolean isBurst() {
+ return burst;
+ }
+
+ @Override
+ public Collection<Band> bands() {
+ return bands;
+ }
+
+ @Override
+ public Optional<MeterContext> context() {
+ return context;
+ }
+
+
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("device", deviceId)
+ .add("appId", appId.name())
+ .add("unit", unit)
+ .add("isBurst", burst)
+ .add("bands", bands).toString();
+ }
+
+ public static final class Builder implements MeterRequest.Builder {
+
+ private ApplicationId appId;
+ private Meter.Unit unit = Meter.Unit.KB_PER_SEC;
+ private boolean burst = false;
+ private Collection<Band> bands;
+ private DeviceId deviceId;
+ private MeterContext context;
+
+
+ @Override
+ public MeterRequest.Builder forDevice(DeviceId deviceId) {
+ this.deviceId = deviceId;
+ return this;
+ }
+
+ @Override
+ public MeterRequest.Builder fromApp(ApplicationId appId) {
+ this.appId = appId;
+ return this;
+ }
+
+ @Override
+ public MeterRequest.Builder withUnit(Meter.Unit unit) {
+ this.unit = unit;
+ return this;
+ }
+
+ @Override
+ public MeterRequest.Builder burst() {
+ this.burst = true;
+ return this;
+ }
+
+ @Override
+ public MeterRequest.Builder withBands(Collection<Band> bands) {
+ this.bands = ImmutableSet.copyOf(bands);
+ return this;
+ }
+
+ @Override
+ public MeterRequest.Builder withContext(MeterContext context) {
+ this.context = context;
+ return this;
+ }
+
+ @Override
+ public MeterRequest add() {
+ validate();
+ return new DefaultMeterRequest(deviceId, appId, unit, burst, bands,
+ context, Type.ADD);
+ }
+
+ @Override
+ public MeterRequest remove() {
+ validate();
+ return new DefaultMeterRequest(deviceId, appId, unit, burst, bands,
+ context, Type.REMOVE);
+ }
+
+ private void validate() {
+ checkNotNull(deviceId, "Must specify a device");
+ checkNotNull(bands, "Must have bands.");
+ checkArgument(bands.size() > 0, "Must have at least one band.");
+ checkNotNull(appId, "Must have an application id");
+ }
+
+
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/Meter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/Meter.java
new file mode 100644
index 00000000..98ebc350
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/Meter.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+
+import java.util.Collection;
+
+/**
+ * Represents a generalized meter to be deployed on a device.
+ */
+public interface Meter {
+
+ enum Unit {
+ /**
+ * Packets per second.
+ */
+ PKTS_PER_SEC,
+
+ /**
+ * Kilo bits per second.
+ */
+ KB_PER_SEC
+ }
+
+ /**
+ * The target device for this meter.
+ *
+ * @return a device id
+ */
+ DeviceId deviceId();
+
+ /**
+ * This meters id.
+ *
+ * @return a meter id
+ */
+ MeterId id();
+
+ /**
+ * The id of the application which created this meter.
+ *
+ * @return an application id
+ */
+ ApplicationId appId();
+
+ /**
+ * The unit used within this meter.
+ *
+ * @return the unit
+ */
+ Unit unit();
+
+ /**
+ * Signals whether this meter applies to bursts only.
+ *
+ * @return a boolean
+ */
+ boolean isBurst();
+
+ /**
+ * The collection of bands to apply on the dataplane.
+ *
+ * @return a collection of bands.
+ */
+ Collection<Band> bands();
+
+ /**
+ * Fetches the state of this meter.
+ *
+ * @return a meter state
+ */
+ MeterState state();
+
+ /**
+ * The lifetime in seconds of this meter.
+ *
+ * @return number of seconds
+ */
+ long life();
+
+ /**
+ * The number of flows pointing to this meter.
+ *
+ * @return a reference count
+ */
+ long referenceCount();
+
+ /**
+ * Number of packets processed by this meter.
+ *
+ * @return a packet count
+ */
+ long packetsSeen();
+
+ /**
+ * Number of bytes processed by this meter.
+ *
+ * @return a byte count
+ */
+ long bytesSeen();
+
+ /**
+ * A meter builder.
+ */
+ interface Builder {
+
+ /**
+ * Assigns the target device for this meter.
+ *
+ * @param deviceId a device id
+ * @return this
+ */
+ Builder forDevice(DeviceId deviceId);
+
+ /**
+ * Assigns the id to this meter.
+ *
+ * @param id a e
+ * @return this
+ */
+ Builder withId(MeterId id);
+
+ /**
+ * Assigns the application that built this meter.
+ *
+ * @param appId an application id
+ * @return this
+ */
+ Builder fromApp(ApplicationId appId);
+
+ /**
+ * Assigns the @See Unit to use for this meter.
+ * Defaults to kb/s
+ *
+ * @param unit a unit
+ * @return this
+ */
+ Builder withUnit(Unit unit);
+
+ /**
+ * Sets this meter as applicable to burst traffic only.
+ * Defaults to false.
+ *
+ * @return this
+ */
+ Builder burst();
+
+ /**
+ * Assigns bands to this meter. There must be at least one band.
+ *
+ * @param bands a collection of bands
+ * @return this
+ */
+ Builder withBands(Collection<Band> bands);
+
+ /**
+ * Builds the meter based on the specified parameters.
+ *
+ * @return a meter
+ */
+ Meter build();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterContext.java
new file mode 100644
index 00000000..574bdca9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterContext.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+/**
+ * A context permitting the application to be notified when the
+ * meter installation has been successful.
+ */
+public interface MeterContext {
+
+ /**
+ * Invoked on successful installation of the meter.
+ *
+ * @param op a meter
+ */
+ default void onSuccess(MeterRequest op) {}
+
+ /**
+ * Invoked when error is encountered while installing a meter.
+ *
+ * @param op a meter
+ * @param reason the reason why it failed
+ */
+ default void onError(MeterRequest op, MeterFailReason reason) {}
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterEntry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterEntry.java
new file mode 100644
index 00000000..178a564c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterEntry.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+/**
+ * Represents a stored meter.
+ */
+public interface MeterEntry extends Meter {
+
+ /**
+ * Updates the state of this meter.
+ *
+ * @param state a meter state
+ */
+ void setState(MeterState state);
+
+ /**
+ * Set the amount of time the meter has existed in seconds.
+ *
+ * @param life number of seconds
+ */
+ void setLife(long life);
+
+ /**
+ * Sets the number of flows which are using this meter.
+ *
+ * @param count a reference count.
+ */
+ void setReferenceCount(long count);
+
+ /**
+ * Updates the number of packets seen by this meter.
+ *
+ * @param packets a packet count.
+ */
+ void setProcessedPackets(long packets);
+
+ /**
+ * Updates the number of bytes seen by the meter.
+ *
+ * @param bytes a byte counter.
+ */
+ void setProcessedBytes(long bytes);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterEvent.java
new file mode 100644
index 00000000..72f0a53a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterEvent.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Entity that represents Meter events.
+ */
+public class MeterEvent extends AbstractEvent<MeterEvent.Type, Meter> {
+
+
+ public enum Type {
+ /**
+ * A meter addition was requested.
+ */
+ METER_ADD_REQ,
+
+ /**
+ * A meter removal was requested.
+ */
+ METER_REM_REQ
+ }
+
+
+ /**
+ * Creates an event of a given type and for the specified meter and the
+ * current time.
+ *
+ * @param type meter event type
+ * @param meter event subject
+ */
+ public MeterEvent(Type type, Meter meter) {
+ super(type, meter);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified meter and time.
+ *
+ * @param type meter event type
+ * @param meter event subject
+ * @param time occurrence time
+ */
+ public MeterEvent(Type type, Meter meter, long time) {
+ super(type, meter, time);
+ }
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterFailReason.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterFailReason.java
new file mode 100644
index 00000000..8683e2a2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterFailReason.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+/**
+ * Enum used to represent a meter failure condition.
+ */
+public enum MeterFailReason {
+ /**
+ * A meter with the same identifier already exists.
+ * Essentially a duplicate meter exists.
+ */
+ EXISTING_METER,
+
+ /**
+ * The device does not support any more meters.
+ */
+ OUT_OF_METERS,
+
+ /**
+ * The device does not support any more bands for this meter.
+ */
+ OUT_OF_BANDS,
+
+ /**
+ * The meter that was attempted to be modified is unknown.
+ */
+ UNKNOWN,
+
+ /**
+ * The operation for this meter installation timed out.
+ */
+ TIMEOUT,
+
+ /**
+ * Invalid meter definition.
+ */
+ INVALID_METER,
+
+ /**
+ * The target device is unknown.
+ */
+ UNKNOWN_DEVICE,
+
+ /**
+ * Unknown command.
+ */
+ UNKNOWN_COMMAND,
+
+ /**
+ * Unknown flags.
+ */
+ UNKNOWN_FLAGS,
+
+ /**
+ * Bad rate value.
+ */
+ BAD_RATE,
+
+ /**
+ * Bad burst size value.
+ */
+ BAD_BURST,
+
+ /**
+ * Bad band.
+ */
+ BAD_BAND,
+
+ /**
+ * Bad value value.
+ */
+ BAD_BAND_VALUE
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterId.java
new file mode 100644
index 00000000..872de2d8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterId.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * A representation of a meter id.
+ * Uniquely identifies a meter system wide.
+ */
+public final class MeterId {
+
+ static final long MAX = 0xFFFF0000;
+
+ private final long id;
+
+ public static final MeterId SLOWPATH = new MeterId(0xFFFFFFFD);
+ public static final MeterId CONTROLLER = new MeterId(0xFFFFFFFE);
+ public static final MeterId ALL = new MeterId(0xFFFFFFFF);
+
+ private MeterId(long id) {
+ checkArgument(id >= MAX, "id cannot be larger than 0xFFFF0000");
+ this.id = id;
+ }
+
+ /**
+ * The integer representation of the meter id.
+ *
+ * @return a long
+ */
+ public long id() {
+ return id;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ MeterId meterId = (MeterId) o;
+
+ return id == meterId.id;
+
+ }
+
+ @Override
+ public int hashCode() {
+ return Long.hashCode(id);
+ }
+
+ @Override
+ public String toString() {
+ return Long.toHexString(this.id);
+ }
+
+ public static MeterId meterId(long id) {
+ return new MeterId(id);
+
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterListener.java
new file mode 100644
index 00000000..0a5e203f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving Meter related events.
+ */
+public interface MeterListener extends EventListener<MeterEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterOperation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterOperation.java
new file mode 100644
index 00000000..437dd269
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterOperation.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+/**
+ * Representation of an operation on the meter table.
+ */
+public class MeterOperation {
+
+
+ /**
+ * Tyoe of meter operation.
+ */
+ public enum Type {
+ ADD,
+ REMOVE,
+ MODIFY
+ }
+
+ private final Meter meter;
+ private final Type type;
+
+
+ public MeterOperation(Meter meter, Type type) {
+ this.meter = meter;
+ this.type = type;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return type
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the meter.
+ *
+ * @return a meter
+ */
+ public Meter meter() {
+ return meter;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("meter", meter)
+ .add("type", type)
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ MeterOperation that = (MeterOperation) o;
+ return Objects.equal(meter, that.meter) &&
+ Objects.equal(type, that.type);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(meter, type);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterOperations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterOperations.java
new file mode 100644
index 00000000..92b0c3aa
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterOperations.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Immutable collection of meter operation to be used between
+ * core and provider layers of group subsystem.
+ *
+ */
+public final class MeterOperations {
+ private final List<MeterOperation> operations;
+
+ /**
+ * Creates a immutable list of meter operation.
+ *
+ * @param operations list of meter operation
+ */
+ public MeterOperations(List<MeterOperation> operations) {
+ this.operations = ImmutableList.copyOf(checkNotNull(operations));
+ }
+
+ /**
+ * Returns immutable list of Meter operation.
+ *
+ * @return list of Meter operation
+ */
+ public List<MeterOperation> operations() {
+ return operations;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProvider.java
new file mode 100644
index 00000000..4655e234
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Abstraction of a Meter provider.
+ */
+public interface MeterProvider extends Provider {
+
+ /**
+ * Performs a batch of meter operation on the specified device with the
+ * specified parameters.
+ *
+ * @param deviceId device identifier on which the batch of group
+ * operations to be executed
+ * @param meterOps immutable list of meter operation
+ */
+ void performMeterOperation(DeviceId deviceId,
+ MeterOperations meterOps);
+
+
+ /**
+ * Performs a meter operation on the specified device with the
+ * specified parameters.
+ *
+ * @param deviceId device identifier on which the batch of group
+ * operations to be executed
+ * @param meterOp a meter operation
+ */
+ void performMeterOperation(DeviceId deviceId,
+ MeterOperation meterOp);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProviderRegistry.java
new file mode 100644
index 00000000..019ca19a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProviderRegistry.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction for a meter provider registry.
+ */
+public interface MeterProviderRegistry
+ extends ProviderRegistry<MeterProvider, MeterProviderService> {
+}
+
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProviderService.java
new file mode 100644
index 00000000..85c0c43e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterProviderService.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.ProviderService;
+
+import java.util.Collection;
+
+/**
+ * Service through which meter providers can inject information
+ * into the core.
+ */
+public interface MeterProviderService extends ProviderService<MeterProvider> {
+
+ /**
+ * Notifies the core that a meter operaton failed for a
+ * specific reason.
+ * @param operation the failed operation
+ * @param reason the failure reason
+ */
+ void meterOperationFailed(MeterOperation operation,
+ MeterFailReason reason);
+
+ /**
+ * Pushes the collection of meters observed on the data plane as
+ * well as their associated statistics.
+ *
+ * @param deviceId a device id
+ * @param meterEntries a collection of meter entries
+ */
+ void pushMeterMetrics(DeviceId deviceId,
+ Collection<Meter> meterEntries);
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java
new file mode 100644
index 00000000..fd11ca41
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * Represents a generalized meter request to be deployed on a device.
+ */
+public interface MeterRequest {
+
+ enum Type {
+ ADD,
+ MODIFY,
+ REMOVE
+ }
+
+ /**
+ * The target device for this meter.
+ *
+ * @return a device id
+ */
+ DeviceId deviceId();
+
+ /**
+ * The id of the application which created this meter.
+ *
+ * @return an application id
+ */
+ ApplicationId appId();
+
+ /**
+ * The unit used within this meter.
+ *
+ * @return the unit
+ */
+ Meter.Unit unit();
+
+ /**
+ * Signals whether this meter applies to bursts only.
+ *
+ * @return a boolean
+ */
+ boolean isBurst();
+
+ /**
+ * The collection of bands to apply on the dataplane.
+ *
+ * @return a collection of bands.
+ */
+ Collection<Band> bands();
+
+ /**
+ * Returns the callback context for this meter.
+ *
+ * @return an optional meter context
+ */
+ Optional<MeterContext> context();
+
+ /**
+ * A meter builder.
+ */
+ interface Builder {
+
+ /**
+ * Assigns the target device for this meter.
+ *
+ * @param deviceId a device id
+ * @return this
+ */
+ Builder forDevice(DeviceId deviceId);
+
+ /**
+ * Assigns the application that built this meter.
+ *
+ * @param appId an application id
+ * @return this
+ */
+ Builder fromApp(ApplicationId appId);
+
+ /**
+ * Assigns the @See Unit to use for this meter.
+ * Defaults to kb/s
+ *
+ * @param unit a unit
+ * @return this
+ */
+ Builder withUnit(Meter.Unit unit);
+
+ /**
+ * Sets this meter as applicable to burst traffic only.
+ * Defaults to false.
+ *
+ * @return this
+ */
+ Builder burst();
+
+ /**
+ * Assigns bands to this meter. There must be at least one band.
+ *
+ * @param bands a collection of bands
+ * @return this
+ */
+ Builder withBands(Collection<Band> bands);
+
+ /**
+ * Assigns an execution context for this meter request.
+ *
+ * @param context a meter context
+ * @return this
+ */
+ Builder withContext(MeterContext context);
+
+ /**
+ * Requests the addition of a meter.
+ *
+ * @return a meter request
+ */
+ MeterRequest add();
+
+ /**
+ * Requests the removal of a meter.
+ *
+ * @return a meter request
+ */
+ MeterRequest remove();
+
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterService.java
new file mode 100644
index 00000000..bdc90eb7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterService.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import org.onosproject.event.ListenerService;
+
+import java.util.Collection;
+
+/**
+ * Service for add/updating and removing meters. Meters are
+ * are assigned to flow to rate limit them and provide a certain
+ * quality of service.
+ */
+public interface MeterService
+ extends ListenerService<MeterEvent, MeterListener> {
+
+ /**
+ * Adds a meter to the system and performs it installation.
+ *
+ * @param meter a meter
+ * @return a meter (with a meter id)
+ */
+ Meter submit(MeterRequest meter);
+
+ /**
+ * Remove a meter from the system and the dataplane.
+ *
+ * @param meter a meter to remove
+ * @param meterId the meter id of the meter to remove.
+ */
+ void withdraw(MeterRequest meter, MeterId meterId);
+
+ /**
+ * Fetch the meter by the meter id.
+ *
+ * @param id a meter id
+ * @return a meter
+ */
+ Meter getMeter(MeterId id);
+
+ /**
+ * Fetches all the meters.
+ *
+ * @return a collection of meters
+ */
+ Collection<Meter> getAllMeters();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterState.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterState.java
new file mode 100644
index 00000000..3b936099
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterState.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+/**
+ * Represents the state of the meter as seen by the store.
+ */
+public enum MeterState {
+
+ /**
+ * The meter is in the process of being added.
+ */
+ PENDING_ADD,
+
+ /**
+ * THe meter has been added.
+ */
+ ADDED,
+
+ /**
+ * The meter is in the process of being removed.
+ */
+ PENDING_REMOVE,
+
+ /**
+ * The meter has been removed.
+ */
+ REMOVED,
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStore.java
new file mode 100644
index 00000000..5112a4a3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStore.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import org.onosproject.store.Store;
+
+import java.util.Collection;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Entity that stores and distributed meter objects.
+ */
+public interface MeterStore extends Store<MeterEvent, MeterStoreDelegate> {
+
+ /**
+ * Adds a meter to the store.
+ *
+ * @param meter a meter
+ * @return a future indicating the result of the store operation
+ */
+ CompletableFuture<MeterStoreResult> storeMeter(Meter meter);
+
+ /**
+ * Deletes a meter from the store.
+ *
+ * @param meter a meter
+ * @return a future indicating the result of the store operation
+ */
+ CompletableFuture<MeterStoreResult> deleteMeter(Meter meter);
+
+ /**
+ * Updates a meter whose meter id is the same as the passed meter.
+ *
+ * @param meter a new meter
+ * @return a future indicating the result of the store operation
+ */
+ CompletableFuture<MeterStoreResult> updateMeter(Meter meter);
+
+ /**
+ * Updates a given meter's state with the provided state.
+ *
+ * @param meter a meter
+ */
+ void updateMeterState(Meter meter);
+
+ /**
+ * Obtains a meter matching the given meter id.
+ *
+ * @param meterId a meter id
+ * @return a meter
+ */
+ Meter getMeter(MeterId meterId);
+
+ /**
+ * Returns all meters stored in the store.
+ *
+ * @return a collection of meters
+ */
+ Collection<Meter> getAllMeters();
+
+ /**
+ * Update the store by deleting the failed meter.
+ * Notifies the delegate that the meter failed to allow it
+ * to nofity the app.
+ *
+ * @param op a failed meter operation
+ * @param reason a failure reason
+ */
+ void failedMeter(MeterOperation op, MeterFailReason reason);
+
+ /**
+ * Delete this meter immediately.
+ * @param m a meter
+ */
+ void deleteMeterNow(Meter m);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStoreDelegate.java
new file mode 100644
index 00000000..9bfeb42f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Meter store delegate abstraction.
+ */
+public interface MeterStoreDelegate extends StoreDelegate<MeterEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStoreResult.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStoreResult.java
new file mode 100644
index 00000000..7a26746f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/MeterStoreResult.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.meter;
+
+import java.util.Optional;
+
+/**
+ * An entity used to indicate whether the store operation passed.
+ */
+public final class MeterStoreResult {
+
+
+ private final Type type;
+ private final Optional<MeterFailReason> reason;
+
+ public enum Type {
+ SUCCESS,
+ FAIL
+ }
+
+ private MeterStoreResult(Type type, MeterFailReason reason) {
+ this.type = type;
+ this.reason = Optional.ofNullable(reason);
+ }
+
+ public Type type() {
+ return type;
+ }
+
+ public Optional<MeterFailReason> reason() {
+ return reason;
+ }
+
+ /**
+ * A successful store opertion.
+ *
+ * @return a meter store result
+ */
+ public static MeterStoreResult success() {
+ return new MeterStoreResult(Type.SUCCESS, null);
+ }
+
+ /**
+ * A failed store operation.
+ *
+ * @param reason a failure reason
+ * @return a meter store result
+ */
+ public static MeterStoreResult fail(MeterFailReason reason) {
+ return new MeterStoreResult(Type.FAIL, reason);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/package-info.java
new file mode 100644
index 00000000..258634da
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/meter/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Flow meter model and related services.
+ */
+package org.onosproject.net.meter; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAdminService.java
new file mode 100644
index 00000000..e94ee452
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAdminService.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.newresource;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Service for administering resource service behavior.
+ */
+@Beta
+public interface ResourceAdminService {
+ /**
+ * Register resources as the children of the parent resource path.
+ *
+ * @param parent parent resource path under which the resource are registered
+ * @param children resources to be registered as the children of the parent
+ * @param <T> type of resources
+ * @return true if registration is successfully done, false otherwise. Registration
+ * succeeds when each resource is not registered or unallocated.
+ */
+ default <T> boolean registerResources(ResourcePath parent, T... children) {
+ return registerResources(parent, Arrays.asList(children));
+ }
+
+ /**
+ * Register resources as the children of the parent resource path.
+ *
+ * @param parent parent resource path under which the resource are registered
+ * @param children resources to be registered as the children of the parent
+ * @param <T> type of resources
+ * @return true if registration is successfully done, false otherwise. Registration
+ * succeeds when each resource is not registered or unallocated.
+ */
+ <T> boolean registerResources(ResourcePath parent, List<T> children);
+
+ /**
+ * Unregister resources as the children of the parent resource path.
+ *
+ * @param parent parent resource path under which the resource are unregistered
+ * @param children resources to be unregistered as the children of the parent
+ * @param <T> type of resources
+ * @return true if unregistration is successfully done, false otherwise. Unregistration
+ * succeeds when each resource is not registered or unallocated.
+ */
+ default <T> boolean unregisterResources(ResourcePath parent, T... children) {
+ return unregisterResources(parent, Arrays.asList(children));
+ }
+
+ /**
+ * Unregister resources as the children of the parent resource path.
+ *
+ * @param parent parent resource path under which the resource are unregistered
+ * @param children resources to be unregistered as the children of the parent
+ * @param <T> type of resources
+ * @return true if unregistration is successfully done, false otherwise. Unregistration
+ * succeeds when each resource is not registered or unallocated.
+ */
+ <T> boolean unregisterResources(ResourcePath parent, List<T> children);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAllocation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAllocation.java
new file mode 100644
index 00000000..e6980267
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAllocation.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.newresource;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Represents allocation of resource which is identified by the specifier.
+ */
+@Beta
+public class ResourceAllocation {
+
+ private final ResourcePath resource;
+ private final ResourceConsumer consumer;
+
+ /**
+ * Creates an instance with the specified subject, resource and consumer.
+ *
+ * @param resource resource of the subject
+ * @param consumer consumer ot this resource
+ */
+ public ResourceAllocation(ResourcePath resource, ResourceConsumer consumer) {
+ this.resource = checkNotNull(resource);
+ this.consumer = consumer;
+ }
+
+ // for serialization
+ private ResourceAllocation() {
+ this.resource = null;
+ this.consumer = null;
+ }
+
+ /**
+ * Returns the specifier of the resource this allocation uses.
+ *
+ * @return the specifier of the resource this allocation uses
+ */
+ public ResourcePath resource() {
+ return resource;
+ }
+
+ /**
+ * Returns the consumer of this resource.
+ *
+ * @return the consumer of this resource
+ */
+ public ResourceConsumer consumer() {
+ return consumer;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(resource, consumer);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof ResourceAllocation)) {
+ return false;
+ }
+ final ResourceAllocation that = (ResourceAllocation) obj;
+ return Objects.equals(this.resource, that.resource)
+ && Objects.equals(this.consumer, that.consumer);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("resource", resource)
+ .add("consumer", consumer)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceConsumer.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceConsumer.java
new file mode 100644
index 00000000..1f67e204
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceConsumer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.newresource;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Marker interface representing an entity using resource.
+ */
+@Beta
+public interface ResourceConsumer {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java
new file mode 100644
index 00000000..3aa29f6b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.newresource;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * An object that is used to locate a resource in a network.
+ * A ResourcePath represents a path that is hierarchical and composed of a sequence
+ * of elementary resources that are not globally identifiable. A ResourcePath can be a globally
+ * unique resource identifier.
+ *
+ * Users of this class must keep the semantics of resources regarding the hierarchical structure.
+ * For example, resource path, Link:1/VLAN ID:100, is valid, but resource path, VLAN ID:100/Link:1
+ * is not valid because a link is not a sub-component of a VLAN ID.
+ */
+@Beta
+public final class ResourcePath {
+
+ private final List<Object> resources;
+
+ public static final ResourcePath ROOT = new ResourcePath(ImmutableList.of());
+
+ public static ResourcePath child(ResourcePath parent, Object child) {
+ ImmutableList<Object> components = ImmutableList.builder()
+ .addAll(parent.components())
+ .add(child)
+ .build();
+ return new ResourcePath(components);
+ }
+
+ /**
+ * Creates an resource path from the specified components.
+ *
+ * @param components components of the path. The order represents hierarchical structure of the resource.
+ */
+ public ResourcePath(Object... components) {
+ this(Arrays.asList(components));
+ }
+
+ /**
+ * Creates an resource path from the specified components.
+ *
+ * @param components components of the path. The order represents hierarchical structure of the resource.
+ */
+ public ResourcePath(List<Object> components) {
+ checkNotNull(components);
+
+ this.resources = ImmutableList.copyOf(components);
+ }
+
+ // for serialization
+ private ResourcePath() {
+ this.resources = null;
+ }
+
+ /**
+ * Returns the components of this resource path.
+ *
+ * @return the components of this resource path
+ */
+ public List<Object> components() {
+ return resources;
+ }
+
+ /**
+ * Returns the parent resource path of this instance.
+ * E.g. if this path is Link:1/VLAN ID:100, the return value is the resource path for Link:1.
+ *
+ * @return the parent resource path of this instance.
+ * If there is no parent, empty instance will be returned.
+ */
+ public Optional<ResourcePath> parent() {
+ if (!isRoot()) {
+ return Optional.of(new ResourcePath(resources.subList(0, resources.size() - 1)));
+ }
+
+ return Optional.empty();
+ }
+
+ /**
+ * Returns true if the path represents root.
+ *
+ * @return true if the path represents root, false otherwise.
+ */
+ public boolean isRoot() {
+ return resources.size() == 0;
+ }
+
+ /**
+ * Returns the last component of this instance.
+ *
+ * @return the last component of this instance.
+ * The return value is equal to the last object of {@code components()}.
+ */
+ public Object lastComponent() {
+ int last = resources.size() - 1;
+ return resources.get(last);
+ }
+
+ @Override
+ public int hashCode() {
+ return resources.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof ResourcePath)) {
+ return false;
+ }
+ final ResourcePath that = (ResourcePath) obj;
+ return Objects.equals(this.resources, that.resources);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("resources", resources)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
new file mode 100644
index 00000000..618042a3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.newresource;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Service for allocating/releasing resource(s) and retrieving allocation(s) and availability.
+ */
+@Beta
+public interface ResourceService {
+ /**
+ * Allocates the specified resource to the specified user.
+ *
+ * @param consumer resource user which the resource is allocated to
+ * @param resource resource to be allocated
+ * @return allocation information enclosed by Optional. If the allocation fails, the return value is empty
+ */
+ default Optional<ResourceAllocation> allocate(ResourceConsumer consumer, ResourcePath resource) {
+ checkNotNull(consumer);
+ checkNotNull(resource);
+
+ List<ResourceAllocation> allocations = allocate(consumer, ImmutableList.of(resource));
+ if (allocations.isEmpty()) {
+ return Optional.empty();
+ }
+
+ assert allocations.size() == 1;
+
+ ResourceAllocation allocation = allocations.get(0);
+
+ assert allocation.resource().equals(resource);
+
+ // cast is ensured by the assertions above
+ return Optional.of(allocation);
+ }
+
+ /**
+ * Transactionally allocates the specified resources to the specified user.
+ * All allocations are made when this method succeeds, or no allocation is made when this method fails.
+ *
+ * @param consumer resource user which the resources are allocated to
+ * @param resources resources to be allocated
+ * @return non-empty list of allocation information if succeeded, otherwise empty list
+ */
+ List<ResourceAllocation> allocate(ResourceConsumer consumer, List<ResourcePath> resources);
+
+ /**
+ * Transactionally allocates the specified resources to the specified user.
+ * All allocations are made when this method succeeds, or no allocation is made when this method fails.
+ *
+ * @param consumer resource user which the resources are allocated to
+ * @param resources resources to be allocated
+ * @return non-empty list of allocation information if succeeded, otherwise empty list
+ */
+ default List<ResourceAllocation> allocate(ResourceConsumer consumer, ResourcePath... resources) {
+ checkNotNull(consumer);
+ checkNotNull(resources);
+
+ return allocate(consumer, Arrays.asList(resources));
+ }
+
+ /**
+ * Releases the specified resource allocation.
+ *
+ * @param allocation resource allocation to be released
+ * @return true if succeeded, otherwise false
+ */
+ default boolean release(ResourceAllocation allocation) {
+ checkNotNull(allocation);
+
+ return release(ImmutableList.of(allocation));
+ }
+
+ /**
+ * Transactionally releases the specified resource allocations.
+ * All allocations are released when this method succeeded, or no allocation is released when this method fails.
+ *
+ * @param allocations resource allocations to be released
+ * @return true if succeeded, otherwise false
+ */
+ boolean release(List<ResourceAllocation> allocations);
+
+ /**
+ * Transactionally releases the specified resource allocations.
+ * All allocations are released when this method succeeded, or no allocation is released when this method fails.
+ *
+ * @param allocations resource allocations to be released
+ * @return true if succeeded, otherwise false
+ */
+ default boolean release(ResourceAllocation... allocations) {
+ checkNotNull(allocations);
+
+ return release(ImmutableList.copyOf(allocations));
+ }
+
+ /**
+ * Transactionally releases the resources allocated to the specified consumer.
+ * All allocations are released when this method succeeded, or no allocation is released when this method fails.
+ *
+ * @param consumer consumer whose allocated resources are to be released
+ * @return true if succeeded, otherwise false
+ */
+ boolean release(ResourceConsumer consumer);
+
+ /**
+ * Returns allocated resources being as children of the specified parent and being the specified resource type.
+ *
+ * @param parent parent resource path
+ * @param cls class to specify a type of resource
+ * @param <T> type of the resource
+ * @return non-empty collection of resource allocations if resources are allocated with the subject and type,
+ * empty collection if no resource is allocated with the subject and type
+ */
+ <T> Collection<ResourceAllocation> getResourceAllocations(ResourcePath parent, Class<T> cls);
+
+ /**
+ * Returns resources allocated to the specified consumer.
+ *
+ * @param consumer consumer whose allocated resources are to be returned
+ * @return resources allocated to the consumer
+ */
+ Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer);
+
+ /**
+ * Returns the availability of the specified resource.
+ *
+ * @param resource resource to check the availability
+ * @return true if available, otherwise false
+ */
+ boolean isAvailable(ResourcePath resource);
+
+ // TODO: listener and event mechanism need to be considered
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
new file mode 100644
index 00000000..fc2eba70
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
@@ -0,0 +1,90 @@
+package org.onosproject.net.newresource;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Service for storing resource and consumer information.
+ */
+@Beta
+public interface ResourceStore {
+
+ /**
+ * Registers the resources in transactional way.
+ * Resource registration must be done before resource allocation. The state after completion
+ * of this method is all the resources are registered, or none of the given resources is registered.
+ * The whole registration fails when any one of the resource can't be registered.
+ *
+ * @param resources resources to be registered
+ * @return true if the registration succeeds, false otherwise
+ */
+ boolean register(List<ResourcePath> resources);
+
+ /**
+ * Unregisters the resources in transactional way.
+ * The state after completion of this method is all the resources are unregistered,
+ * or none of the given resources is unregistered. The whole unregistration fails when any one of the
+ * resource can't be unregistered.
+ *
+ * @param resources resources to be unregistered
+ * @return true if the registration succeeds, false otherwise
+ */
+ boolean unregister(List<ResourcePath> resources);
+
+ /**
+ * Allocates the specified resources to the specified consumer in transactional way.
+ * The state after completion of this method is all the resources are allocated to the consumer,
+ * or no resource is allocated to the consumer. The whole allocation fails when any one of
+ * the resource can't be allocated.
+ *
+ * @param resources resources to be allocated
+ * @param consumer resource consumer which the resources are allocated to
+ * @return true if the allocation succeeds, false otherwise.
+ */
+ boolean allocate(List<ResourcePath> resources, ResourceConsumer consumer);
+
+ /**
+ * Releases the specified resources allocated to the specified corresponding consumers
+ * in transactional way. The state after completion of this method is all the resources
+ * are released from the consumer, or no resource is released. The whole release fails
+ * when any one of the resource can't be released. The size of the list of resources and
+ * that of consumers must be equal. The resource and consumer with the same position from
+ * the head of each list correspond to each other.
+ *
+ * @param resources resources to be released
+ * @param consumers resource consumers to whom the resource allocated to
+ * @return true if succeeds, otherwise false
+ */
+ boolean release(List<ResourcePath> resources, List<ResourceConsumer> consumers);
+
+ /**
+ * Returns the resource consumer to whom the specified resource is allocated.
+ *
+ * @param resource resource whose allocated consumer to be returned
+ * @return resource consumer who are allocated the resource
+ */
+ Optional<ResourceConsumer> getConsumer(ResourcePath resource);
+
+ /**
+ * Returns a collection of the resources allocated to the specified consumer.
+ *
+ * @param consumer resource consumer whose allocated resource are searched for
+ * @return a collection of the resources allocated to the specified consumer
+ */
+ Collection<ResourcePath> getResources(ResourceConsumer consumer);
+
+ /**
+ * Returns a collection of the resources which are children of the specified parent and
+ * whose type is the specified class.
+ *
+ * @param parent parent of the resources to be returned
+ * @param cls class instance of the children
+ * @param <T> type of the resource
+ * @return a collection of the resources which belongs to the specified subject and
+ * whose type is the specified class.
+ */
+ <T> Collection<ResourcePath> getAllocatedResources(ResourcePath parent, Class<T> cls);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/package-info.java
new file mode 100644
index 00000000..52bb8588
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Generic network resource model and services for resource allocation and
+ * resource tracking.
+ */
+package org.onosproject.net.newresource; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/package-info.java
new file mode 100644
index 00000000..34b4de21
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Network model entities &amp; service API definitions.
+ */
+package org.onosproject.net;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultInboundPacket.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultInboundPacket.java
new file mode 100644
index 00000000..96f872f5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultInboundPacket.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.net.ConnectPoint;
+import org.onlab.packet.Ethernet;
+
+import java.nio.ByteBuffer;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of an immutable inbound packet.
+ */
+public final class DefaultInboundPacket implements InboundPacket {
+
+ private final ConnectPoint receivedFrom;
+ private final Ethernet parsed;
+ private final ByteBuffer unparsed;
+
+ /**
+ * Creates an immutable inbound packet.
+ *
+ * @param receivedFrom connection point where received
+ * @param parsed parsed ethernet frame
+ * @param unparsed unparsed raw bytes
+ */
+ public DefaultInboundPacket(ConnectPoint receivedFrom, Ethernet parsed,
+ ByteBuffer unparsed) {
+ this.receivedFrom = receivedFrom;
+ this.parsed = parsed;
+ this.unparsed = unparsed;
+ }
+
+ @Override
+ public ConnectPoint receivedFrom() {
+ return receivedFrom;
+ }
+
+ @Override
+ public Ethernet parsed() {
+ return parsed;
+ }
+
+ @Override
+ public ByteBuffer unparsed() {
+ // FIXME: figure out immutability here
+ return unparsed;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(receivedFrom, parsed, unparsed);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof InboundPacket) {
+ final DefaultInboundPacket other = (DefaultInboundPacket) obj;
+ return Objects.equals(this.receivedFrom, other.receivedFrom) &&
+ Objects.equals(this.parsed, other.parsed) &&
+ Objects.equals(this.unparsed, other.unparsed);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("receivedFrom", receivedFrom)
+ .add("parsed", parsed)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultOutboundPacket.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultOutboundPacket.java
new file mode 100644
index 00000000..5bd4c986
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultOutboundPacket.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import java.nio.ByteBuffer;
+import java.util.Objects;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Default implementation of an immutable outbound packet.
+ */
+public final class DefaultOutboundPacket implements OutboundPacket {
+ private final DeviceId sendThrough;
+ private final TrafficTreatment treatment;
+ private final ByteBuffer data;
+
+ /**
+ * Creates an immutable outbound packet.
+ *
+ * @param sendThrough identifier through which to send the packet
+ * @param treatment list of packet treatments
+ * @param data raw packet data
+ */
+ public DefaultOutboundPacket(DeviceId sendThrough,
+ TrafficTreatment treatment, ByteBuffer data) {
+ this.sendThrough = sendThrough;
+ this.treatment = treatment;
+ this.data = data;
+ }
+
+ @Override
+ public DeviceId sendThrough() {
+ return sendThrough;
+ }
+
+ @Override
+ public TrafficTreatment treatment() {
+ return treatment;
+ }
+
+ @Override
+ public ByteBuffer data() {
+ // FIXME: figure out immutability here
+ return data;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(sendThrough, treatment, data);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof OutboundPacket) {
+ final DefaultOutboundPacket other = (DefaultOutboundPacket) obj;
+ return Objects.equals(this.sendThrough, other.sendThrough) &&
+ Objects.equals(this.treatment, other.treatment) &&
+ Objects.equals(this.data, other.data);
+ }
+ return false;
+ }
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("sendThrough", sendThrough)
+ .add("treatment", treatment)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultPacketContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultPacketContext.java
new file mode 100644
index 00000000..166269f9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultPacketContext.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment.Builder;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.onosproject.security.AppGuard.checkPermission;
+import static org.onosproject.security.AppPermission.Type.*;
+
+/**
+ * Default implementation of a packet context.
+ */
+public abstract class DefaultPacketContext implements PacketContext {
+
+ private final long time;
+ private final InboundPacket inPkt;
+ private final OutboundPacket outPkt;
+ private final TrafficTreatment.Builder builder;
+
+ private final AtomicBoolean block;
+
+ /**
+ * Creates a new packet context.
+ *
+ * @param time creation time
+ * @param inPkt inbound packet
+ * @param outPkt outbound packet
+ * @param block whether the context is blocked or not
+ */
+ protected DefaultPacketContext(long time, InboundPacket inPkt,
+ OutboundPacket outPkt, boolean block) {
+ super();
+ this.time = time;
+ this.inPkt = inPkt;
+ this.outPkt = outPkt;
+ this.block = new AtomicBoolean(block);
+ this.builder = DefaultTrafficTreatment.builder();
+ }
+
+ @Override
+ public long time() {
+ checkPermission(PACKET_READ);
+ return time;
+ }
+
+ @Override
+ public InboundPacket inPacket() {
+ checkPermission(PACKET_READ);
+ return inPkt;
+ }
+
+ @Override
+ public OutboundPacket outPacket() {
+ checkPermission(PACKET_READ);
+ return outPkt;
+ }
+
+ @Override
+ public Builder treatmentBuilder() {
+ checkPermission(PACKET_READ);
+ return builder;
+ }
+
+ @Override
+ public abstract void send();
+
+ @Override
+ public boolean block() {
+ checkPermission(PACKET_WRITE);
+ return this.block.getAndSet(true);
+ }
+
+ @Override
+ public boolean isHandled() {
+ checkPermission(PACKET_READ);
+ return this.block.get();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultPacketRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultPacketRequest.java
new file mode 100644
index 00000000..ce2eb118
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/DefaultPacketRequest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficSelector;
+
+import java.util.Objects;
+
+/**
+ * Default implementation of a packet request.
+ */
+public final class DefaultPacketRequest implements PacketRequest {
+ private final TrafficSelector selector;
+ private final PacketPriority priority;
+ private final ApplicationId appId;
+
+ /**
+ * Creates a new packet request.
+ *
+ * @param selector traffic selector
+ * @param priority intercept priority
+ * @param appId application id
+ */
+ public DefaultPacketRequest(TrafficSelector selector, PacketPriority priority,
+ ApplicationId appId) {
+ this.selector = selector;
+ this.priority = priority;
+ this.appId = appId;
+ }
+
+ public TrafficSelector selector() {
+ return selector;
+ }
+
+ public PacketPriority priority() {
+ return priority;
+ }
+
+ public ApplicationId appId() {
+ return appId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(selector, priority, appId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final DefaultPacketRequest other = (DefaultPacketRequest) obj;
+ return Objects.equals(this.selector, other.selector)
+ && Objects.equals(this.priority, other.priority)
+ && Objects.equals(this.appId, other.appId);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this.getClass())
+ .add("selector", selector)
+ .add("priority", priority)
+ .add("appId", appId).toString();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/InboundPacket.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/InboundPacket.java
new file mode 100644
index 00000000..3fd58149
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/InboundPacket.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.net.ConnectPoint;
+import org.onlab.packet.Ethernet;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Represents a data packet intercepted from an infrastructure device.
+ */
+public interface InboundPacket {
+
+ /**
+ * Returns the device and port from where the packet was received.
+ *
+ * @return connection point where received
+ */
+ ConnectPoint receivedFrom();
+
+ /**
+ * Returns the parsed form of the packet.
+ *
+ * @return parsed Ethernet frame; null if the packet is not an Ethernet
+ * frame or one for which there is no parser
+ */
+ Ethernet parsed();
+
+ /**
+ * Unparsed packet data.
+ *
+ * @return raw packet bytes
+ */
+ ByteBuffer unparsed();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/OutboundPacket.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/OutboundPacket.java
new file mode 100644
index 00000000..9e9329fa
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/OutboundPacket.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Represents an outbound data packet that is to be emitted to network via
+ * an infrastructure device.
+ */
+public interface OutboundPacket {
+
+ /**
+ * Returns the identity of a device through which this packet should be
+ * sent.
+ *
+ * @return device identity
+ */
+ DeviceId sendThrough();
+
+ /**
+ * Returns how the outbound packet should be treated.
+ *
+ * @return output treatment
+ */
+ TrafficTreatment treatment();
+
+ /**
+ * Returns immutable view of the raw data to be sent.
+ *
+ * @return data to emit
+ */
+ ByteBuffer data();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketContext.java
new file mode 100644
index 00000000..004adc87
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketContext.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.net.flow.TrafficTreatment;
+
+/**
+ * Represents context for processing an inbound packet, and (optionally)
+ * emitting a corresponding outbound packet.
+ */
+public interface PacketContext {
+
+ /**
+ * Returns the time when the packet was received.
+ *
+ * @return the time in millis since start of epoch
+ */
+ long time();
+
+ /**
+ * Returns the inbound packet being processed.
+ *
+ * @return inbound packet
+ */
+ InboundPacket inPacket();
+
+ /**
+ * Returns the view of the outbound packet.
+ *
+ * @return outbound packet
+ */
+ OutboundPacket outPacket();
+
+ /**
+ * Returns a builder for constructing traffic treatment.
+ *
+ * @return traffic treatment builder
+ */
+ TrafficTreatment.Builder treatmentBuilder();
+
+ /**
+ * Triggers the outbound packet to be sent.
+ */
+ void send();
+
+ /**
+ * Blocks the outbound packet from being sent from this point onward.
+ *
+ * @return whether the outbound packet is blocked.
+ */
+ boolean block();
+
+ /**
+ * Indicates whether the outbound packet is handled, i.e. sent or blocked.
+ *
+ * @return true uf the packed is handled
+ */
+ boolean isHandled();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketEvent.java
new file mode 100644
index 00000000..7b0a5ed7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketEvent.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes a packet event.
+ */
+public class PacketEvent extends AbstractEvent<PacketEvent.Type, OutboundPacket> {
+
+ /**
+ * Type of packet events.
+ */
+ public enum Type {
+ /**
+ * Signifies that the packet should be emitted out a local port.
+ */
+ EMIT
+ }
+
+ /**
+ * Creates an event of the given type for the specified packet.
+ *
+ * @param type the type of the event
+ * @param packet the packet the event is about
+ */
+ public PacketEvent(Type type, OutboundPacket packet) {
+ super(type, packet);
+ }
+
+ /**
+ * Creates an event of the given type for the specified packet at the given
+ * time.
+ *
+ * @param type the type of the event
+ * @param packet the packet the event is about
+ * @param time the time of the event
+ */
+ public PacketEvent(Type type, OutboundPacket packet, long time) {
+ super(type, packet, time);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketPriority.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketPriority.java
new file mode 100644
index 00000000..68c0a838
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketPriority.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+/**
+ * Priorities available to applications for requests for packets from the data
+ * plane.
+ */
+public enum PacketPriority {
+ /**
+ * High priority for control traffic. This will result in all traffic
+ * matching the selector being sent to the controller.
+ */
+ CONTROL(40000),
+
+ /**
+ * Low priority for reactive applications. Packets are only sent to the
+ * controller if they fail to match any of the rules installed in the switch.
+ */
+ REACTIVE(5);
+
+ private final int priorityValue;
+
+ private PacketPriority(int priorityValue) {
+ this.priorityValue = priorityValue;
+ }
+
+ /**
+ * Returns the integer value of the priority level.
+ *
+ * @return priority value
+ */
+ public int priorityValue() {
+ return priorityValue;
+ }
+
+ public String toString() {
+ return String.valueOf(priorityValue);
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProcessor.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProcessor.java
new file mode 100644
index 00000000..98886775
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProcessor.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Abstraction of an inbound packet processor.
+ */
+public interface PacketProcessor {
+
+ static final int ADVISOR_MAX = Integer.MAX_VALUE / 3;
+ static final int DIRECTOR_MAX = (Integer.MAX_VALUE / 3) * 2;
+ static final int OBSERVER_MAX = Integer.MAX_VALUE;
+
+ /**
+ * Returns a priority in the ADVISOR range, where processors can take early action and
+ * influence the packet context. However, they cannot handle the packet (i.e. call send() or block()).
+ * The valid range is from 1 to ADVISOR_MAX.
+ * Processors in this range get to see the packet first.
+ *
+ * @param priority priority within ADVISOR range
+ * @return overall priority
+ */
+ static int advisor(int priority) {
+ int overallPriority = priority + 1;
+ checkArgument(overallPriority > 0 && overallPriority <= ADVISOR_MAX,
+ "Priority not within ADVISOR range");
+ return overallPriority;
+ }
+
+ /**
+ * Returns a priority in the DIRECTOR range, where processors can handle the packet.
+ * The valid range is from ADVISOR_MAX+1 to DIRECTOR_MAX.
+ * Processors in this range get to see the packet second, after ADVISORS.
+ *
+ * @param priority priority within the DIRECTOR range
+ * @return overall priority
+ */
+ static int director(int priority) {
+ int overallPriority = ADVISOR_MAX + priority + 1;
+ checkArgument(overallPriority > ADVISOR_MAX && overallPriority <= DIRECTOR_MAX,
+ "Priority not within DIRECTOR range");
+ return overallPriority;
+ }
+
+ /**
+ * Returns a priority in the OBSERVER range, where processors cannot take any action,
+ * but can observe what action has been taken until then.
+ * The valid range is from DIRECTOR_MAX+1 to OBSERVER_MAX.
+ * Processors in this range get to see the packet last, after ADVISORS and DIRECTORS.
+ *
+ * @param priority priority within the OBSERVER range
+ * @return overall priority
+ */
+ static int observer(int priority) {
+ int overallPriority = DIRECTOR_MAX + priority + 1;
+ checkArgument(overallPriority > DIRECTOR_MAX && overallPriority <= OBSERVER_MAX,
+ "Priority not within OBSERVER range");
+ return overallPriority;
+ }
+
+ /**
+ * Processes the inbound packet as specified in the given context.
+ *
+ * @param context packet processing context
+ */
+ void process(PacketContext context);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProvider.java
new file mode 100644
index 00000000..8d55f0d1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProvider.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Abstraction of a packet provider capable of emitting packets.
+ */
+public interface PacketProvider extends Provider {
+
+ /**
+ * Emits the specified outbound packet onto the network.
+ *
+ * @param packet outbound packet
+ */
+ void emit(OutboundPacket packet);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProviderRegistry.java
new file mode 100644
index 00000000..6e73253e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction of an infrastructure packet provider registry.
+ */
+public interface PacketProviderRegistry
+extends ProviderRegistry<PacketProvider, PacketProviderService> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProviderService.java
new file mode 100644
index 00000000..1aaee65f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketProviderService.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.net.provider.ProviderService;
+
+/**
+ * Entity capable of processing inbound packets.
+ */
+public interface PacketProviderService extends ProviderService<PacketProvider> {
+
+ /**
+ * Submits inbound packet context for processing. This processing will be
+ * done synchronously, i.e. run-to-completion.
+ *
+ * @param context inbound packet context
+ */
+ void processPacket(PacketContext context);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketRequest.java
new file mode 100644
index 00000000..dc09219a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketRequest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficSelector;
+
+/**
+ * Represents a packet request made to devices.
+ */
+public interface PacketRequest {
+
+ /**
+ * Obtain the traffic selector.
+ *
+ * @return a traffic selector
+ */
+ TrafficSelector selector();
+
+ /**
+ * Obtain the priority.
+ *
+ * @return a PacketPriority
+ */
+ PacketPriority priority();
+
+ /**
+ * Obtain the application id.
+ *
+ * @return an application id
+ */
+ ApplicationId appId();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketService.java
new file mode 100644
index 00000000..06c416ec
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketService.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficSelector;
+
+/**
+ * Service for intercepting data plane packets and for emitting synthetic
+ * outbound packets.
+ */
+public interface PacketService {
+
+ // TODO: ponder better ordering scheme that does not require absolute numbers
+
+ /**
+ * Adds the specified processor to the list of packet processors.
+ * It will be added into the list in the order of priority. The higher
+ * numbers will be processing the packets after the lower numbers.
+ *
+ * @param processor processor to be added
+ * @param priority priority in the reverse natural order
+ * @throws java.lang.IllegalArgumentException if a processor with the
+ * given priority already exists
+ */
+ void addProcessor(PacketProcessor processor, int priority);
+
+ // TODO allow processors to register for particular types of packets
+
+ /**
+ * Removes the specified processor from the processing pipeline.
+ *
+ * @param processor packet processor
+ */
+ void removeProcessor(PacketProcessor processor);
+
+ /**
+ * Requests that packets matching the given selector are punted from the
+ * dataplane to the controller.
+ *
+ * @param selector the traffic selector used to match packets
+ * @param priority the priority of the rule
+ * @param appId the application ID of the requester
+ */
+ void requestPackets(TrafficSelector selector, PacketPriority priority,
+ ApplicationId appId);
+
+ /**
+ * Cancels previous packet requests for packets matching the given
+ * selector to be punted from the dataplane to the controller.
+ *
+ * @param selector the traffic selector used to match packets
+ * @param priority the priority of the rule
+ * @param appId the application ID of the requester
+ */
+ void cancelPackets(TrafficSelector selector, PacketPriority priority,
+ ApplicationId appId);
+
+ /**
+ * Emits the specified outbound packet onto the network.
+ *
+ * @param packet outbound packet
+ */
+ void emit(OutboundPacket packet);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketStore.java
new file mode 100644
index 00000000..ff45cc0c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketStore.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.store.Store;
+
+import java.util.Set;
+
+/**
+ * Manages routing of outbound packets.
+ */
+public interface PacketStore extends Store<PacketEvent, PacketStoreDelegate> {
+
+ /**
+ * Decides which instance should emit the packet and forwards the packet to
+ * that instance. The relevant PacketManager is notified via the
+ * PacketStoreDelegate that it should emit the packet.
+ *
+ * @param packet the packet to emit
+ */
+ void emit(OutboundPacket packet);
+
+ /**
+ * Requests intercept of packets that match the given selector.
+ *
+ * @param request a packet request
+ * @return true if the first time the given selector was requested
+ */
+ boolean requestPackets(PacketRequest request);
+
+ /**
+ * Cancels intercept of packets that match the given selector.
+ *
+ * @param request a packet request
+ * @return true if there is no other application requesting the given selector
+ */
+ boolean cancelPackets(PacketRequest request);
+
+ /**
+ * Obtains all existing requests in the system.
+ *
+ * @return a set of packet requests
+ */
+ Set<PacketRequest> existingRequests();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketStoreDelegate.java
new file mode 100644
index 00000000..bf5c3cc0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/PacketStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Packet store delegate abstraction.
+ */
+public interface PacketStoreDelegate extends StoreDelegate<PacketEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/package-info.java
new file mode 100644
index 00000000..0b9ea377
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/packet/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Mechanism for processing inbound packets intercepted from the data plane and
+ * for emitting outbound packets onto the data plane.
+ */
+package org.onosproject.net.packet;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractListenerProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractListenerProviderRegistry.java
new file mode 100644
index 00000000..ff67c6da
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractListenerProviderRegistry.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.provider;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.event.Event;
+import org.onosproject.event.EventDeliveryService;
+import org.onosproject.event.EventListener;
+import org.onosproject.event.ListenerRegistry;
+import org.onosproject.event.ListenerService;
+
+/**
+ * Basis for components which need to export listener mechanism.
+ */
+@Component(componentAbstract = true)
+public abstract class AbstractListenerProviderRegistry<E extends Event, L extends EventListener<E>,
+ P extends Provider, S extends ProviderService<P>>
+ extends AbstractProviderRegistry<P, S> implements ListenerService<E, L> {
+
+ // If only Java supported mixins...
+
+ protected final ListenerRegistry<E, L> listenerRegistry = new ListenerRegistry<>();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected EventDeliveryService eventDispatcher;
+
+ @Override
+ public void addListener(L listener) {
+ listenerRegistry.addListener(listener);
+ }
+
+ @Override
+ public void removeListener(L listener) {
+ listenerRegistry.removeListener(listener);
+ }
+
+
+ /**
+ * Safely posts the specified event to the local event dispatcher.
+ * If there is no event dispatcher or if the event is null, this method
+ * is a noop.
+ *
+ * @param event event to be posted; may be null
+ */
+ protected void post(E event) {
+ if (event != null && eventDispatcher != null) {
+ eventDispatcher.post(event);
+ }
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProvider.java
new file mode 100644
index 00000000..a4926dd3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.provider;
+
+/**
+ * Base provider implementation.
+ */
+public abstract class AbstractProvider implements Provider {
+
+ private final ProviderId providerId;
+
+ /**
+ * Creates a provider with the supplier identifier.
+ *
+ * @param id provider id
+ */
+ protected AbstractProvider(ProviderId id) {
+ this.providerId = id;
+ }
+
+ @Override
+ public ProviderId id() {
+ return providerId;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProviderRegistry.java
new file mode 100644
index 00000000..bcf5fae0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProviderRegistry.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.provider;
+
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.DeviceId;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Base implementation of provider registry.
+ *
+ * @param <P> type of the information provider
+ * @param <S> type of the provider service
+ */
+public abstract class AbstractProviderRegistry<P extends Provider, S extends ProviderService<P>>
+ implements ProviderRegistry<P, S> {
+
+ private final Map<ProviderId, P> providers = new HashMap<>();
+ private final Map<ProviderId, S> services = new HashMap<>();
+ private final Map<String, P> providersByScheme = new HashMap<>();
+
+ /**
+ * Creates a new provider service bound to the specified provider.
+ *
+ * @param provider provider
+ * @return provider service
+ */
+ protected abstract S createProviderService(P provider);
+
+ @Override
+ public synchronized S register(P provider) {
+ checkNotNull(provider, "Provider cannot be null");
+ checkState(!services.containsKey(provider.id()), "Provider %s already registered", provider.id());
+
+ // If the provider is a primary one, check for a conflict.
+ ProviderId pid = provider.id();
+ checkState(pid.isAncillary() || !providersByScheme.containsKey(pid.scheme()),
+ "A primary provider with id %s is already registered",
+ providersByScheme.get(pid.scheme()));
+
+ S service = createProviderService(provider);
+ services.put(provider.id(), service);
+ providers.put(provider.id(), provider);
+
+ // Register the provider by URI scheme only if it is not ancillary.
+ if (!pid.isAncillary()) {
+ providersByScheme.put(pid.scheme(), provider);
+ }
+
+ return service;
+ }
+
+ @Override
+ public synchronized void unregister(P provider) {
+ checkNotNull(provider, "Provider cannot be null");
+ S service = services.get(provider.id());
+ if (service != null && service instanceof AbstractProviderService) {
+ ((AbstractProviderService) service).invalidate();
+ services.remove(provider.id());
+ providers.remove(provider.id());
+ if (!provider.id().isAncillary()) {
+ providersByScheme.remove(provider.id().scheme());
+ }
+ }
+ }
+
+ @Override
+ public synchronized Set<ProviderId> getProviders() {
+ return ImmutableSet.copyOf(services.keySet());
+ }
+
+ /**
+ * Returns the provider registered with the specified provider ID.
+ *
+ * @param providerId provider identifier
+ * @return provider
+ */
+ protected synchronized P getProvider(ProviderId providerId) {
+ return providers.get(providerId);
+ }
+
+ /**
+ * Returns the provider for the specified device ID based on URI scheme.
+ *
+ * @param deviceId device identifier
+ * @return provider bound to the URI scheme
+ */
+ protected synchronized P getProvider(DeviceId deviceId) {
+ return providersByScheme.get(deviceId.uri().getScheme());
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProviderService.java
new file mode 100644
index 00000000..6c926d88
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/AbstractProviderService.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.provider;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Base implementation of a provider service, which tracks the provider to
+ * which it is issued and can be invalidated.
+ *
+ * @param <P> type of the information provider
+ */
+public abstract class AbstractProviderService<P extends Provider> implements ProviderService<P> {
+
+ private boolean isValid = true;
+ private final P provider;
+
+ /**
+ * Creates a provider service on behalf of the specified provider.
+ *
+ * @param provider provider to which this service is being issued
+ */
+ protected AbstractProviderService(P provider) {
+ this.provider = provider;
+ }
+
+ /**
+ * Invalidates this provider service.
+ */
+ public void invalidate() {
+ isValid = false;
+ }
+
+ /**
+ * Checks the validity of this provider service.
+ *
+ * @throws java.lang.IllegalStateException if the service is no longer valid
+ */
+ public void checkValidity() {
+ checkState(isValid, "Provider service is no longer valid");
+ }
+
+ @Override
+ public P provider() {
+ return provider;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/Provider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/Provider.java
new file mode 100644
index 00000000..84465ab7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/Provider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.provider;
+
+/**
+ * Abstraction of a provider of information about network environment.
+ */
+public interface Provider {
+
+ /**
+ * Returns the provider identifier.
+ *
+ * @return provider identification
+ */
+ ProviderId id();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderId.java
new file mode 100644
index 00000000..2c959afd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderId.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.provider;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * External identity of a {@link org.onosproject.net.provider.Provider} family.
+ * It also carriers two designations of external characteristics, the URI
+ * scheme and primary/ancillary indicator.
+ * <p>
+ * The device URI scheme is used to determine applicability of a provider to
+ * operations on a specific device. The ancillary indicator serves to designate
+ * a provider as a primary or ancillary.
+ * </p>
+ * <p>
+ * A {@link org.onosproject.net.provider.ProviderRegistry} uses this designation
+ * to permit only one primary provider per device URI scheme. Multiple
+ * ancillary providers can register with the same device URI scheme however.
+ * </p>
+ */
+public class ProviderId {
+
+ /**
+ * Represents no provider ID.
+ */
+ public static final ProviderId NONE = new ProviderId("none", "none");
+
+ private final String scheme;
+ private final String id;
+ private final boolean ancillary;
+
+ // For serialization
+ private ProviderId() {
+ scheme = null;
+ id = null;
+ ancillary = false;
+ }
+
+ /**
+ * Creates a new primary provider identifier from the specified string.
+ * The providers are expected to follow the reverse DNS convention, e.g.
+ * {@code org.onosproject.provider.of.device}
+ *
+ * @param scheme device URI scheme to which this provider is bound, e.g. "of", "snmp"
+ * @param id string identifier
+ */
+ public ProviderId(String scheme, String id) {
+ this(scheme, id, false);
+ }
+
+ /**
+ * Creates a new provider identifier from the specified string.
+ * The providers are expected to follow the reverse DNS convention, e.g.
+ * {@code org.onosproject.provider.of.device}
+ *
+ * @param scheme device URI scheme to which this provider is bound, e.g. "of", "snmp"
+ * @param id string identifier
+ * @param ancillary ancillary provider indicator
+ */
+ public ProviderId(String scheme, String id, boolean ancillary) {
+ this.scheme = checkNotNull(scheme, "Scheme cannot be null");
+ this.id = checkNotNull(id, "ID cannot be null");
+ this.ancillary = ancillary;
+ }
+
+ /**
+ * Returns the device URI scheme to which this provider is bound.
+ *
+ * @return device URI scheme
+ */
+ public String scheme() {
+ return scheme;
+ }
+
+ /**
+ * Returns the device URI scheme specific id portion.
+ *
+ * @return id
+ */
+ public String id() {
+ return id;
+ }
+
+ /**
+ * Indicates whether this identifier designates an ancillary providers.
+ *
+ * @return true if the provider is ancillary; false if primary
+ */
+ public boolean isAncillary() {
+ return ancillary;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(scheme, id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ProviderId) {
+ final ProviderId other = (ProviderId) obj;
+ return Objects.equals(this.scheme, other.scheme) &&
+ Objects.equals(this.id, other.id) &&
+ this.ancillary == other.ancillary;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("scheme", scheme).add("id", id)
+ .add("ancillary", ancillary).toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderRegistry.java
new file mode 100644
index 00000000..3c2009ad
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderRegistry.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.provider;
+
+import java.util.Set;
+
+/**
+ * Registry for tracking information providers with the core.
+ *
+ * @param <P> type of the information provider
+ * @param <S> type of the provider service
+ */
+public interface ProviderRegistry<P extends Provider, S extends ProviderService<P>> {
+
+ /**
+ * Registers the supplied provider with the core.
+ *
+ * @param provider provider to be registered
+ * @return provider service for injecting information into core
+ * @throws java.lang.IllegalArgumentException if the provider is registered already
+ */
+ S register(P provider);
+
+ /**
+ * Unregisters the supplied provider. As a result the previously issued
+ * provider service will be invalidated and any subsequent invocations
+ * of its methods may throw {@link java.lang.IllegalStateException}.
+ * <p>
+ * Unregistering a provider that has not been previously registered results
+ * in a no-op.
+ * </p>
+ *
+ * @param provider provider to be unregistered
+ */
+ void unregister(P provider);
+
+ /**
+ * Returns a set of currently registered provider identities.
+ *
+ * @return set of provider identifiers
+ */
+ Set<ProviderId> getProviders();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderService.java
new file mode 100644
index 00000000..5c469276
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/ProviderService.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.provider;
+
+/**
+ * Abstraction of a service through which providers can inject information
+ * about the network environment into the core.
+ *
+ * @param <P> type of the information provider
+ */
+public interface ProviderService<P extends Provider> {
+
+ /**
+ * Returns the provider to which this service has been issued.
+ *
+ * @return provider to which this service has been assigned
+ */
+ P provider();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/package-info.java
new file mode 100644
index 00000000..d279f56a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/provider/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Base abstractions related to network entity providers and their brokers.
+ */
+package org.onosproject.net.provider;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java
new file mode 100644
index 00000000..8ffe17a4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.proxyarp;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.packet.PacketContext;
+
+/**
+ * Service for processing arp requests on behalf of applications.
+ */
+// TODO: move to the peer host package
+public interface ProxyArpService {
+
+ /**
+ * Returns whether this particular IP address is known to the system.
+ *
+ * @param addr an IP address
+ * @return true if know, false otherwise
+ */
+ boolean isKnown(IpAddress addr);
+
+ /**
+ * Sends a reply for a given request. If the host is not known then the
+ * arp or neighbor solicitation will be flooded at all edge ports.
+ *
+ * @param eth an arp or neighbor solicitation request
+ * @param inPort the port the request was received on
+ */
+ void reply(Ethernet eth, ConnectPoint inPort);
+
+ /**
+ * Forwards an ARP or neighbor solicitation request to its destination.
+ * Floods at the edg the request if the destination is not known.
+ *
+ * @param eth an ethernet frame containing an ARP or neighbor solicitation
+ * request.
+ * @param inPort the port the request was received on
+ */
+ void forward(Ethernet eth, ConnectPoint inPort);
+
+ /**
+ * Handles a arp or neighbor solicitation packet.
+ * Replies to arp or neighbor solicitation requests and forwards request
+ * to the right place.
+ * @param context the packet context to handle
+ * @return true if handled, false otherwise.
+ */
+ boolean handlePacket(PacketContext context);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java
new file mode 100644
index 00000000..b6564212
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.proxyarp;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Host;
+
+import java.nio.ByteBuffer;
+
+/**
+ * State distribution mechanism for the proxy ARP service.
+ */
+public interface ProxyArpStore {
+
+ /**
+ * Forwards an ARP or neighbor solicitation request to its destination.
+ * Floods at the edg the request if the destination is not known.
+ *
+ * @param outPort the port the request was received on
+ * @param subject subject host
+ * @param packet an ethernet frame containing an ARP or neighbor
+ * solicitation request
+ */
+ void forward(ConnectPoint outPort, Host subject, ByteBuffer packet);
+
+ /**
+ * Associates the specified delegate with the store.
+ *
+ * @param delegate store delegate
+ */
+ void setDelegate(ProxyArpStoreDelegate delegate);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStoreDelegate.java
new file mode 100644
index 00000000..d0e273c8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStoreDelegate.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.proxyarp;
+
+import org.onosproject.net.ConnectPoint;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Proxy ARP store delegate.
+ */
+public interface ProxyArpStoreDelegate {
+
+ /**
+ * Emits ARP or neighbour discovery response packet.
+ *
+ * @param outPort output connection point
+ * @param packet packet to emit
+ */
+ void emitResponse(ConnectPoint outPort, ByteBuffer packet);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/package-info.java
new file mode 100644
index 00000000..6ddd4926
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/proxyarp/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Base abstractions related to the proxy arp service.
+ */
+package org.onosproject.net.proxyarp;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceAllocation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceAllocation.java
new file mode 100644
index 00000000..01b69b2a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceAllocation.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Abstraction of allocated resource.
+ */
+@Beta
+public interface ResourceAllocation {
+ /**
+ * Returns the resource type.
+ *
+ * @return the resource type
+ */
+ ResourceType type();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceAllocationException.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceAllocationException.java
new file mode 100644
index 00000000..c3d1fcc7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceAllocationException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Exception thrown for resource allocation errors.
+ */
+@Beta
+public class ResourceAllocationException extends ResourceException {
+ public ResourceAllocationException() {
+ super();
+ }
+
+ public ResourceAllocationException(String message) {
+ super(message);
+ }
+
+ public ResourceAllocationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceException.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceException.java
new file mode 100644
index 00000000..31e82d5d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceException.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents a resource related error.
+ */
+@Beta
+public class ResourceException extends RuntimeException {
+
+ /**
+ * Constructs an exception with no message and no underlying cause.
+ */
+ public ResourceException() {
+ }
+
+ /**
+ * Constructs an exception with the specified message.
+ *
+ * @param message the message describing the specific nature of the error
+ */
+ public ResourceException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception with the specified message and the underlying cause.
+ *
+ * @param message the message describing the specific nature of the error
+ * @param cause the underlying cause of this error
+ */
+ public ResourceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceId.java
new file mode 100644
index 00000000..722ec4d7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceId.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Resource identifier.
+ */
+@Beta
+public interface ResourceId {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceRequest.java
new file mode 100644
index 00000000..fb53f120
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceRequest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Abstraction of resource request.
+ */
+@Beta
+public interface ResourceRequest {
+ /**
+ * Returns the resource type.
+ *
+ * @return the resource type
+ */
+ ResourceType type();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceType.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceType.java
new file mode 100644
index 00000000..75832134
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/ResourceType.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents types for link resources.
+ */
+@Beta
+public enum ResourceType {
+ /**
+ * Lambda resource type.
+ */
+ LAMBDA,
+
+ /**
+ * Bandwidth resource type.
+ */
+ BANDWIDTH,
+
+ /**
+ * MPLS label resource type.
+ */
+ MPLS_LABEL,
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/DeviceResourceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/DeviceResourceService.java
new file mode 100644
index 00000000..5468dfb7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/DeviceResourceService.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.device;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.Port;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentId;
+
+import java.util.Set;
+
+/**
+ * Service for providing device resources.
+ */
+@Beta
+public interface DeviceResourceService {
+ /**
+ * Request a set of ports needed to satisfy the intent.
+ *
+ * @param ports set of ports to allocate
+ * @param intent the intent
+ * @return true if ports were successfully allocated, false otherwise
+ */
+ boolean requestPorts(Set<Port> ports, Intent intent);
+
+ /**
+ * Returns the set of ports allocated for an intent.
+ *
+ * @param intentId the intent ID
+ * @return set of allocated ports
+ */
+ Set<Port> getAllocations(IntentId intentId);
+
+ /**
+ * Returns the intent allocated to a port.
+ *
+ * @param port the port
+ * @return intent ID allocated to the port
+ */
+ IntentId getAllocations(Port port);
+
+ /**
+ * Request a mapping between the given intents.
+ *
+ * @param keyIntentId the key intent ID
+ * @param valIntentId the value intent ID
+ * @return true if mapping was successful, false otherwise
+ */
+ boolean requestMapping(IntentId keyIntentId, IntentId valIntentId);
+
+ /**
+ * Returns the intents mapped to a lower intent.
+ *
+ * @param intentId the intent ID
+ * @return the set of intent IDs
+ */
+ Set<IntentId> getMapping(IntentId intentId);
+
+ /**
+ * Release mapping of given intent.
+ *
+ * @param intentId intent ID
+ */
+ void releaseMapping(IntentId intentId);
+
+ /**
+ * Release ports associated with given intent ID.
+ *
+ * @param intentId intent ID
+ */
+ void releasePorts(IntentId intentId);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/DeviceResourceStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/DeviceResourceStore.java
new file mode 100644
index 00000000..a52a843f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/DeviceResourceStore.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.device;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.intent.IntentId;
+
+import java.util.Set;
+
+public interface DeviceResourceStore {
+ /**
+ * Returns unallocated ports on the given device.
+ *
+ * @param deviceId device ID
+ * @return set of unallocated ports
+ */
+ Set<Port> getFreePorts(DeviceId deviceId);
+
+ /**
+ * Allocates the given ports to the given intent.
+ *
+ * @param ports set of ports to allocate
+ * @param intentId intent ID
+ * @return true if allocation was successful, false otherwise
+ */
+ boolean allocatePorts(Set<Port> ports, IntentId intentId);
+
+ /**
+ * Returns set of ports allocated for an intent.
+ *
+ * @param intentId the intent ID
+ * @return set of allocated ports
+ */
+ Set<Port> getAllocations(IntentId intentId);
+
+ /**
+ * Returns intent allocated to a port.
+ *
+ * @param port the port
+ * @return intent ID allocated to the port
+ */
+ IntentId getAllocations(Port port);
+
+ /**
+ * Allocates the mapping between the given intents.
+ *
+ * @param keyIntentId key intent ID
+ * @param valIntentId value intent ID
+ * @return true if mapping was successful, false otherwise
+ */
+ boolean allocateMapping(IntentId keyIntentId, IntentId valIntentId);
+
+ /**
+ * Returns the set of intents mapped to a lower intent.
+ *
+ * @param intentId intent ID
+ * @return set of intent IDs
+ */
+ Set<IntentId> getMapping(IntentId intentId);
+
+ /**
+ * Releases the mapping of the given intent.
+ *
+ * @param intentId intent ID
+ */
+ void releaseMapping(IntentId intentId);
+
+ /**
+ * Releases the ports allocated to the given intent.
+ *
+ * @param intentId intent ID
+ * @return true if release was successful, false otherwise
+ */
+ boolean releasePorts(IntentId intentId);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/package-info.java
new file mode 100644
index 00000000..3ced37dc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/device/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Services for reserving devices as network resources.
+ */
+package org.onosproject.net.resource.device;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java
new file mode 100644
index 00000000..fe21e042
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import org.onlab.util.Bandwidth;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of bandwidth resource in bps.
+ */
+public final class BandwidthResource implements LinkResource {
+
+ private final Bandwidth bandwidth;
+
+ /**
+ * Creates a new instance with given bandwidth.
+ *
+ * @param bandwidth bandwidth value to be assigned
+ */
+ public BandwidthResource(Bandwidth bandwidth) {
+ this.bandwidth = checkNotNull(bandwidth);
+ }
+
+ // Constructor for serialization
+ private BandwidthResource() {
+ this.bandwidth = null;
+ }
+
+ /**
+ * Returns bandwidth as a double value.
+ *
+ * @return bandwidth as a double value
+ */
+ public double toDouble() {
+ return bandwidth.bps();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof BandwidthResource) {
+ BandwidthResource that = (BandwidthResource) obj;
+ return Objects.equals(this.bandwidth, that.bandwidth);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.bandwidth);
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(this.bandwidth);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceAllocation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceAllocation.java
new file mode 100644
index 00000000..74f6e102
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceAllocation.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceType;
+
+import java.util.Objects;
+
+/**
+ * Representation of allocated bandwidth resource.
+ */
+public class BandwidthResourceAllocation implements ResourceAllocation {
+ private final BandwidthResource bandwidth;
+
+ /**
+ * Creates a new {@link BandwidthResourceRequest} with {@link BandwidthResource}
+ * object.
+ *
+ * @param bandwidth {@link BandwidthResource} object to be requested
+ */
+ public BandwidthResourceAllocation(BandwidthResource bandwidth) {
+ this.bandwidth = bandwidth;
+ }
+
+ /**
+ * Returns the bandwidth resource.
+ *
+ * @return the bandwidth resource
+ */
+ public BandwidthResource bandwidth() {
+ return bandwidth;
+ }
+
+ @Override
+ public ResourceType type() {
+ return ResourceType.BANDWIDTH;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(bandwidth);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final BandwidthResourceAllocation other = (BandwidthResourceAllocation) obj;
+ return Objects.equals(this.bandwidth, other.bandwidth());
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("bandwidth", bandwidth)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceRequest.java
new file mode 100644
index 00000000..91cc3d19
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceRequest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.resource.ResourceRequest;
+import org.onosproject.net.resource.ResourceType;
+
+/**
+ * Representation of a request for bandwidth resource.
+ */
+public class BandwidthResourceRequest implements ResourceRequest {
+ private final BandwidthResource bandwidth;
+
+ /**
+ * Creates a new {@link BandwidthResourceRequest} with {@link BandwidthResource}
+ * object.
+ *
+ * @param bandwidth {@link BandwidthResource} object to be requested
+ */
+ public BandwidthResourceRequest(BandwidthResource bandwidth) {
+ this.bandwidth = bandwidth;
+ }
+
+ /**
+ * Returns the bandwidth resource.
+ *
+ * @return the bandwidth resource
+ */
+ public BandwidthResource bandwidth() {
+ return bandwidth;
+ }
+
+ @Override
+ public ResourceType type() {
+ return ResourceType.BANDWIDTH;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(bandwidth);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final BandwidthResourceAllocation other = (BandwidthResourceAllocation) obj;
+ return Objects.equals(this.bandwidth, other.bandwidth());
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("bandwidth", bandwidth)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceAllocations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceAllocations.java
new file mode 100644
index 00000000..379bf71e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceAllocations.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceRequest;
+import org.onosproject.net.resource.ResourceType;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Implementation of {@link LinkResourceAllocations}.
+ */
+public class DefaultLinkResourceAllocations implements LinkResourceAllocations {
+ private final LinkResourceRequest request;
+ // TODO: probably should be using LinkKey instead
+ private final Map<Link, Set<ResourceAllocation>> allocations;
+
+ /**
+ * Creates a new link resource allocations.
+ *
+ * @param request requested resources
+ * @param allocations allocated resources
+ */
+ public DefaultLinkResourceAllocations(LinkResourceRequest request,
+ Map<Link, Set<ResourceAllocation>> allocations) {
+ this.request = checkNotNull(request);
+ ImmutableMap.Builder<Link, Set<ResourceAllocation>> builder
+ = ImmutableMap.builder();
+ for (Entry<Link, Set<ResourceAllocation>> e : allocations.entrySet()) {
+ builder.put(e.getKey(), ImmutableSet.copyOf(e.getValue()));
+ }
+ this.allocations = builder.build();
+ }
+
+ public IntentId intentId() {
+ return request.intentId();
+ }
+
+ public Collection<Link> links() {
+ return request.links();
+ }
+
+ public Set<ResourceRequest> resources() {
+ return request.resources();
+ }
+
+ @Override
+ public ResourceType type() {
+ return null;
+ }
+
+ @Override
+ public Set<ResourceAllocation> getResourceAllocation(Link link) {
+ Set<ResourceAllocation> result = allocations.get(link);
+ if (result == null) {
+ result = Collections.emptySet();
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(request, allocations);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final DefaultLinkResourceAllocations other = (DefaultLinkResourceAllocations) obj;
+ return Objects.equals(this.request, other.request)
+ && Objects.equals(this.allocations, other.allocations);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("allocations", allocations)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java
new file mode 100644
index 00000000..5153aebf
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Objects;
+
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.Link;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.IntentId;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.LambdaConstraint;
+import org.onosproject.net.resource.ResourceRequest;
+import org.onosproject.net.resource.ResourceType;
+
+/**
+ * Implementation of {@link LinkResourceRequest}.
+ */
+public final class DefaultLinkResourceRequest implements LinkResourceRequest {
+
+ private final IntentId intentId;
+ private final Collection<Link> links;
+ private final Set<ResourceRequest> resources;
+
+ /**
+ * Creates a new link resource request with the given ID, links, and
+ * resource requests.
+ *
+ * @param intentId intent ID related to this request
+ * @param links a set of links for the request
+ * @param resources a set of resources to be requested
+ */
+ private DefaultLinkResourceRequest(IntentId intentId,
+ Collection<Link> links,
+ Set<ResourceRequest> resources) {
+ this.intentId = intentId;
+ this.links = ImmutableSet.copyOf(links);
+ this.resources = ImmutableSet.copyOf(resources);
+ }
+
+
+ @Override
+ public ResourceType type() {
+ return null;
+ }
+
+ @Override
+ public IntentId intentId() {
+ return intentId;
+ }
+
+ @Override
+ public Collection<Link> links() {
+ return links;
+ }
+
+ @Override
+ public Set<ResourceRequest> resources() {
+ return resources;
+ }
+
+ /**
+ * Returns builder of link resource request.
+ *
+ * @param intentId intent ID related to this request
+ * @param links a set of links for the request
+ * @return builder of link resource request
+ */
+ public static LinkResourceRequest.Builder builder(
+ IntentId intentId, Collection<Link> links) {
+ return new Builder(intentId, links);
+ }
+
+ /**
+ * Builder of link resource request.
+ */
+ public static final class Builder implements LinkResourceRequest.Builder {
+ private IntentId intentId;
+ private Collection<Link> links;
+ private Set<ResourceRequest> resources;
+
+ /**
+ * Creates a new link resource request.
+ *
+ * @param intentId intent ID related to this request
+ * @param links a set of links for the request
+ */
+ private Builder(IntentId intentId, Collection<Link> links) {
+ this.intentId = intentId;
+ this.links = links;
+ this.resources = new HashSet<>();
+ }
+
+ /**
+ * Adds lambda request.
+ *
+ * @return self
+ */
+ @Override
+ public Builder addLambdaRequest() {
+ resources.add(new LambdaResourceRequest());
+ return this;
+ }
+
+ /**
+ * Adds Mpls request.
+ *
+ * @return self
+ */
+ @Override
+ public Builder addMplsRequest() {
+ resources.add(new MplsLabelResourceRequest());
+ return this;
+ }
+
+ /**
+ * Adds bandwidth request with bandwidth value.
+ *
+ * @param bandwidth bandwidth value in bits per second to be requested
+ * @return self
+ */
+ @Override
+ public Builder addBandwidthRequest(double bandwidth) {
+ resources.add(new BandwidthResourceRequest(new BandwidthResource(Bandwidth.bps(bandwidth))));
+ return this;
+ }
+
+ @Override
+ public LinkResourceRequest.Builder addConstraint(Constraint constraint) {
+ if (constraint instanceof LambdaConstraint) {
+ return addLambdaRequest();
+ } else if (constraint instanceof BandwidthConstraint) {
+ BandwidthConstraint bw = (BandwidthConstraint) constraint;
+ return addBandwidthRequest(bw.bandwidth().toDouble());
+ }
+ return this;
+ }
+
+ /**
+ * Returns link resource request.
+ *
+ * @return link resource request
+ */
+ @Override
+ public LinkResourceRequest build() {
+ return new DefaultLinkResourceRequest(intentId, links, resources);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(intentId, links);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final DefaultLinkResourceRequest other = (DefaultLinkResourceRequest) obj;
+ return Objects.equals(this.intentId, other.intentId)
+ && Objects.equals(this.links, other.links);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResource.java
new file mode 100644
index 00000000..3733e467
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResource.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import org.onosproject.net.IndexedLambda;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of lambda resource.
+ */
+public final class LambdaResource implements LinkResource {
+
+ private final IndexedLambda lambda;
+
+ /**
+ * Creates a new instance with given lambda.
+ *
+ * @param lambda lambda to be assigned
+ */
+ private LambdaResource(IndexedLambda lambda) {
+ this.lambda = checkNotNull(lambda);
+ }
+
+ // Constructor for serialization
+ private LambdaResource() {
+ this.lambda = null;
+ }
+
+ /**
+ * Creates a new instance with the given index of lambda.
+ *
+ * @param lambda index value of lambda to be assigned
+ * @return {@link LambdaResource} instance with the given lambda
+ */
+ public static LambdaResource valueOf(int lambda) {
+ return valueOf(new IndexedLambda(lambda));
+ }
+
+ /**
+ * Creates a new instance with the given lambda.
+ *
+ * @param lambda lambda to be assigned
+ * @return {@link LambdaResource} instance with the given lambda
+ */
+ public static LambdaResource valueOf(IndexedLambda lambda) {
+ return new LambdaResource(lambda);
+ }
+
+ /**
+ * Returns lambda as an int value.
+ *
+ * @return lambda as an int value
+ */
+ public int toInt() {
+ return (int) lambda.index();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof LambdaResource) {
+ LambdaResource that = (LambdaResource) obj;
+ return Objects.equals(this.lambda, that.lambda);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return lambda.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(this.lambda);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceAllocation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceAllocation.java
new file mode 100644
index 00000000..545f025f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceAllocation.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceType;
+
+import java.util.Objects;
+
+/**
+ * Representation of allocated lambda resource.
+ */
+public class LambdaResourceAllocation implements ResourceAllocation {
+ private final LambdaResource lambda;
+
+ @Override
+ public ResourceType type() {
+ return ResourceType.LAMBDA;
+ }
+
+ /**
+ * Creates a new {@link LambdaResourceAllocation} with {@link LambdaResource}
+ * object.
+ *
+ * @param lambda allocated lambda
+ */
+ public LambdaResourceAllocation(LambdaResource lambda) {
+ this.lambda = lambda;
+ }
+
+ /**
+ * Returns the lambda resource.
+ *
+ * @return the lambda resource
+ */
+ public LambdaResource lambda() {
+ return lambda;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(lambda);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final LambdaResourceAllocation other = (LambdaResourceAllocation) obj;
+ return Objects.equals(this.lambda, other.lambda);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("lambda", lambda)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java
new file mode 100644
index 00000000..b0391f5a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.resource.ResourceRequest;
+import org.onosproject.net.resource.ResourceType;
+
+/**
+ * Representation of a request for lambda resource.
+ */
+public class LambdaResourceRequest implements ResourceRequest {
+
+ @Override
+ public ResourceType type() {
+ return ResourceType.LAMBDA;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResource.java
new file mode 100644
index 00000000..ec06611e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResource.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+/**
+ * Abstraction of link resource.
+ */
+public interface LinkResource {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceAllocations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceAllocations.java
new file mode 100644
index 00000000..7828867c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceAllocations.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceRequest;
+
+/**
+ * Representation of allocated link resources.
+ */
+public interface LinkResourceAllocations extends ResourceAllocation {
+
+ /**
+ * Returns the {@link IntentId} associated with the request.
+ *
+ * @return the {@link IntentId} associated with the request
+ */
+ IntentId intentId();
+
+ /**
+ * 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();
+
+ /**
+ * Returns allocated resource for the given link.
+ *
+ * @param link the target link
+ * @return allocated resource for the link
+ */
+ Set<ResourceAllocation> getResourceAllocation(Link link);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceEvent.java
new file mode 100644
index 00000000..3edb386a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceEvent.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import java.util.Collection;
+
+import org.onosproject.event.AbstractEvent;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Describes an event related to a Link Resource.
+ */
+public final class LinkResourceEvent
+ extends AbstractEvent<LinkResourceEvent.Type, Collection<LinkResourceAllocations>> {
+
+ /**
+ * Type of resource this event is for.
+ */
+ public enum Type {
+ /** Additional resources are now available. */
+ ADDITIONAL_RESOURCES_AVAILABLE
+ }
+
+ /**
+ * Constructs a link resource event.
+ *
+ * @param type type of resource event to create
+ * @param linkResourceAllocations allocations that are now available
+ */
+ public LinkResourceEvent(Type type,
+ Collection<LinkResourceAllocations> linkResourceAllocations) {
+ super(type, ImmutableList.copyOf(linkResourceAllocations));
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceListener.java
new file mode 100644
index 00000000..599dd4fb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity for receiving link resource events.
+ */
+public interface LinkResourceListener extends EventListener<LinkResourceEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java
new file mode 100644
index 00000000..8023a92e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.resource.ResourceRequest;
+
+/**
+ * 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 intentId();
+
+ /**
+ * 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();
+
+ /**
+ * Builder of link resource request.
+ */
+ interface Builder {
+ /**
+ * Adds lambda request.
+ *
+ * @return self
+ */
+ Builder addLambdaRequest();
+
+ /**
+ * Adds MPLS request.
+ *
+ * @return self
+ */
+ Builder addMplsRequest();
+
+ /**
+ * Adds bandwidth request with bandwidth value.
+ *
+ * @param bandwidth bandwidth value to be requested
+ * @return self
+ */
+ Builder addBandwidthRequest(double bandwidth);
+
+ /**
+ * Adds the resources required for a constraint.
+ *
+ * @param constraint the constraint
+ * @return self
+ */
+ Builder addConstraint(Constraint constraint);
+
+ /**
+ * Returns link resource request.
+ *
+ * @return link resource request
+ */
+ LinkResourceRequest build();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java
new file mode 100644
index 00000000..6dc04dfc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.Link;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.resource.ResourceRequest;
+
+/**
+ * Service for providing link resource allocation.
+ */
+public interface LinkResourceService
+ extends ListenerService<LinkResourceEvent, LinkResourceListener> {
+
+ /**
+ * Requests resources.
+ *
+ * @param req resources to be allocated
+ * @return allocated resources
+ */
+ LinkResourceAllocations requestResources(LinkResourceRequest req);
+
+ /**
+ * Releases resources.
+ *
+ * @param allocations resources to be released
+ */
+ void releaseResources(LinkResourceAllocations allocations);
+
+ /**
+ * Updates previously made allocations with a new resource request.
+ *
+ * @param req updated resource request
+ * @param oldAllocations old resource allocations
+ * @return new resource allocations
+ */
+ LinkResourceAllocations updateResources(LinkResourceRequest req,
+ LinkResourceAllocations oldAllocations);
+
+ /**
+ * Returns all allocated resources.
+ *
+ * @return allocated resources
+ */
+ Iterable<LinkResourceAllocations> getAllocations();
+
+ /**
+ * Returns all allocated resources to given link.
+ *
+ * @param link a target link
+ * @return allocated resources
+ */
+ Iterable<LinkResourceAllocations> getAllocations(Link link);
+
+ /**
+ * Returns the resources allocated for an Intent.
+ *
+ * @param intentId the target Intent's id
+ * @return allocated resources for Intent
+ */
+ LinkResourceAllocations getAllocations(IntentId intentId);
+
+ /**
+ * Returns available resources for given link.
+ *
+ * @param link a target link
+ * @return available resources for the target link
+ */
+ Iterable<ResourceRequest> getAvailableResources(Link link);
+
+ /**
+ * Returns available resources for given link.
+ *
+ * @param link a target link
+ * @param allocations allocations to be included as available
+ * @return available resources for the target link
+ */
+ Iterable<ResourceRequest> getAvailableResources(Link link,
+ LinkResourceAllocations allocations);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStore.java
new file mode 100644
index 00000000..e6674dbd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStore.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import java.util.Set;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.resource.ResourceAllocation;
+
+/**
+ * Manages link resources.
+ */
+public interface LinkResourceStore {
+ /**
+ * Returns free resources for given link.
+ *
+ * @param link a target link
+ * @return free resources for given link
+ */
+ Set<ResourceAllocation> getFreeResources(Link link);
+
+ /**
+ * Allocates resources.
+ *
+ * @param allocations resources to be allocated
+ */
+ void allocateResources(LinkResourceAllocations allocations);
+
+ /**
+ * Releases resources.
+ *
+ * @param allocations resources to be released
+ * @return the link resource event
+ */
+ LinkResourceEvent releaseResources(LinkResourceAllocations allocations);
+
+ /**
+ * Returns resources allocated for an Intent.
+ *
+ * @param intentId the target Intent's ID
+ * @return allocated resources or null if no resource is allocated
+ */
+ LinkResourceAllocations getAllocations(IntentId intentId);
+
+ /**
+ * Returns resources allocated for a link.
+ *
+ * @param link the target link
+ * @return allocated resources
+ */
+ Iterable<LinkResourceAllocations> getAllocations(Link link);
+
+ /**
+ * Returns all allocated resources.
+ *
+ * @return allocated resources
+ */
+ Iterable<LinkResourceAllocations> getAllocations();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStoreDelegate.java
new file mode 100644
index 00000000..6c051d6a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Link resource store delegate abstraction.
+ */
+public interface LinkResourceStoreDelegate extends StoreDelegate<LinkResourceEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResources.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResources.java
new file mode 100644
index 00000000..dc005227
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResources.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import java.util.Set;
+
+/**
+ * Abstraction of a resources of a link.
+ */
+public interface LinkResources {
+
+ /**
+ * Returns resources as a set of {@link LinkResource}s.
+ *
+ * @return a set of {@link LinkResource}s
+ */
+ Set<LinkResource> resources();
+
+ /**
+ * Builder of {@link LinkResources}.
+ */
+ interface Builder {
+
+ /**
+ * Adds bandwidth resource.
+ * <p>
+ * This operation adds given bandwidth to previous bandwidth and
+ * generates single bandwidth resource.
+ *
+ * @param bandwidth bandwidth value to be added
+ * @return self
+ */
+ Builder addBandwidth(double bandwidth);
+
+ /**
+ * Adds lambda resource.
+ *
+ * @param lambda lambda value to be added
+ * @return self
+ */
+ Builder addLambda(int lambda);
+
+ /**
+ * Builds an immutable link resources.
+ *
+ * @return link resources
+ */
+ LinkResources build();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabel.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabel.java
new file mode 100644
index 00000000..89c87760
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabel.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.resource.link;
+
+import java.util.Objects;
+
+/**
+ * Representation of MPLS label resource.
+ */
+public final class MplsLabel implements LinkResource {
+
+ private final org.onlab.packet.MplsLabel mplsLabel;
+
+
+ /**
+ * Creates a new instance with given MPLS label.
+ *
+ * @param mplsLabel MPLS Label value to be assigned
+ */
+ public MplsLabel(int mplsLabel) {
+ this.mplsLabel = org.onlab.packet.MplsLabel.mplsLabel(mplsLabel);
+ }
+
+ /**
+ * Creates a new instance with given MPLS label.
+ *
+ * @param mplsLabel mplsLabel value to be assigned
+ * @return {@link MplsLabel} instance with given bandwidth
+ */
+ public static MplsLabel valueOf(int mplsLabel) {
+ return new MplsLabel(mplsLabel);
+ }
+
+ /**
+ * Returns MPLS Label as an MPLS Label Object.
+ *
+ * @return MPLS label as an MPLS Label Object.
+ */
+ public org.onlab.packet.MplsLabel label() {
+ return mplsLabel;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof MplsLabel) {
+ MplsLabel that = (MplsLabel) obj;
+ return Objects.equals(this.mplsLabel, that.mplsLabel);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.mplsLabel);
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(this.mplsLabel);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceAllocation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceAllocation.java
new file mode 100644
index 00000000..10911539
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceAllocation.java
@@ -0,0 +1,78 @@
+ /*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.resource.link;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceType;
+
+import java.util.Objects;
+
+/**
+ * Representation of allocated MPLS label resource.
+ */
+public class MplsLabelResourceAllocation implements ResourceAllocation {
+ private final MplsLabel mplsLabel;
+
+ @Override
+ public ResourceType type() {
+ return ResourceType.MPLS_LABEL;
+ }
+
+ /**
+ * Creates a new {@link MplsLabelResourceAllocation} with {@link MplsLabel}
+ * object.
+ *
+ * @param mplsLabel allocated MPLS Label
+ */
+ public MplsLabelResourceAllocation(MplsLabel mplsLabel) {
+ this.mplsLabel = mplsLabel;
+ }
+
+ /**
+ * Returns the MPLS label resource.
+ *
+ * @return the MPLS label resource
+ */
+ public MplsLabel mplsLabel() {
+ return mplsLabel;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mplsLabel);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final MplsLabelResourceAllocation other = (MplsLabelResourceAllocation) obj;
+ return Objects.equals(this.mplsLabel, other.mplsLabel);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("mplsLabel", mplsLabel)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java
new file mode 100644
index 00000000..0a03f450
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.resource.link;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.resource.ResourceRequest;
+import org.onosproject.net.resource.ResourceType;
+
+/**
+ * Representation of a request for lambda resource.
+ */
+public class MplsLabelResourceRequest implements ResourceRequest {
+
+ @Override
+ public ResourceType type() {
+ return ResourceType.MPLS_LABEL;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/package-info.java
new file mode 100644
index 00000000..b10e4ba4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Services for reserving links and their capacity as network resources,
+ * e.g.&nbsp;bandwidth, lambdas.
+ */
+package org.onosproject.net.resource.link;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/package-info.java
new file mode 100644
index 00000000..e676fc87
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Abstractions for reserving network resources.
+ */
+package org.onosproject.net.resource;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/DefaultLoad.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/DefaultLoad.java
new file mode 100644
index 00000000..45e85372
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/DefaultLoad.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.statistic;
+
+import com.google.common.base.MoreObjects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Implementation of a load.
+ */
+public class DefaultLoad implements Load {
+
+ private final boolean isValid;
+ private final long current;
+ private final long previous;
+ private final long time;
+ private final long interval;
+
+ /**
+ * Indicates the flow statistics poll interval in seconds.
+ */
+ private static long pollInterval = 10;
+
+ /**
+ * Creates an invalid load.
+ */
+ public DefaultLoad() {
+ this.isValid = false;
+ this.time = System.currentTimeMillis();
+ this.current = -1;
+ this.previous = -1;
+ this.interval = pollInterval;
+ }
+
+ /**
+ * Creates a load value from the parameters.
+ *
+ * @param current the current value
+ * @param previous the previous value
+ */
+ public DefaultLoad(long current, long previous) {
+ this(current, previous, pollInterval);
+ }
+
+ /**
+ * Creates a load value from the parameters.
+ *
+ * @param current the current value
+ * @param previous the previous value
+ * @param interval poll interval for this load
+ */
+ public DefaultLoad(long current, long previous, long interval) {
+ checkArgument(interval > 0, "Interval must be greater than 0");
+ this.current = current;
+ this.previous = previous;
+ this.time = System.currentTimeMillis();
+ this.isValid = true;
+ this.interval = interval;
+ }
+
+ /**
+ * Sets the poll interval in seconds. Used solely for the purpose of
+ * computing the load.
+ *
+ * @param newPollInterval poll interval duration in seconds
+ */
+ public static void setPollInterval(long newPollInterval) {
+ pollInterval = newPollInterval;
+ }
+
+ @Override
+ public long rate() {
+ return (current - previous) / interval;
+ }
+
+ @Override
+ public long latest() {
+ return current;
+ }
+
+ @Override
+ public boolean isValid() {
+ return isValid;
+ }
+
+ @Override
+ public long time() {
+ return time;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper("Load").add("rate", rate())
+ .add("latest", latest()).toString();
+
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/Load.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/Load.java
new file mode 100644
index 00000000..38fed04e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/Load.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.statistic;
+
+/**
+ * Simple data repository for link load information.
+ */
+public interface Load {
+
+ /**
+ * Obtain the current observed rate (in bytes/s) on a link.
+ *
+ * @return long value
+ */
+ long rate();
+
+ /**
+ * Obtain the latest bytes counter viewed on that link.
+ *
+ * @return long value
+ */
+ long latest();
+
+ /**
+ * Indicates whether this load was built on valid values.
+ *
+ * @return boolean
+ */
+ boolean isValid();
+
+ /**
+ * Returns when this value was seen.
+ *
+ * @return epoch time
+ */
+ long time();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/StatisticService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/StatisticService.java
new file mode 100644
index 00000000..b9f7cc91
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/StatisticService.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.statistic;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.flow.FlowRule;
+
+import java.util.Optional;
+
+/**
+ * Service for obtaining statistic information about link in the system.
+ * Statistics are obtained from the FlowRuleService in order to minimize the
+ * amount of hammering occuring at the dataplane.
+ */
+public interface StatisticService {
+
+ /**
+ * Obtain the load for a the ingress to the given link.
+ *
+ * @param link the link to query.
+ * @return a {@link org.onosproject.net.statistic.Load Load}
+ */
+ Load load(Link link);
+
+ /**
+ * Obtain the load for the given port.
+ *
+ * @param connectPoint the port to query
+ * @return a {@link org.onosproject.net.statistic.Load}
+ */
+ Load load(ConnectPoint connectPoint);
+
+ /**
+ * Find the most loaded link along a path.
+ *
+ * @param path the path to search in
+ * @return the most loaded {@link org.onosproject.net.Link}.
+ */
+ Link max(Path path);
+
+ /**
+ * Find the least loaded link along a path.
+ *
+ * @param path the path to search in
+ * @return the least loaded {@link org.onosproject.net.Link}.
+ */
+ Link min(Path path);
+
+ /**
+ * Returns the highest hitter (a flow rule) for a given port, ie. the
+ * flow rule which is generating the most load.
+ *
+ * @param connectPoint the port
+ * @return the flow rule
+ */
+ FlowRule highestHitter(ConnectPoint connectPoint);
+
+ /**
+ * Obtain the load for a the ingress to the given link used by
+ * the specified application ID and group ID.
+ *
+ * @param link link to query
+ * @param appId application ID to filter with
+ * @param groupId group ID to filter with
+ * @return {@link Load Load}
+ */
+ Load load(Link link, ApplicationId appId, Optional<GroupId> groupId);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/StatisticStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/StatisticStore.java
new file mode 100644
index 00000000..8566ef5b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/StatisticStore.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.statistic;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+
+import java.util.Set;
+
+/**
+ * Store to house the computed statistics.
+ */
+public interface StatisticStore {
+
+ /**
+ * Lay the foundation for receiving flow stats for this rule.
+ *
+ * @param rule a {@link org.onosproject.net.flow.FlowRule}
+ */
+ void prepareForStatistics(FlowRule rule);
+
+ /**
+ * Remove entries associated with this rule.
+ *
+ * @param rule {@link org.onosproject.net.flow.FlowRule}
+ */
+ void removeFromStatistics(FlowRule rule);
+
+ /**
+ * Adds a stats observation for a flow rule.
+ *
+ * @param rule a {@link org.onosproject.net.flow.FlowEntry}
+ */
+ void addOrUpdateStatistic(FlowEntry rule);
+
+ /**
+ * Fetches the current observed stats values.
+ *
+ * @param connectPoint the port to fetch information for
+ * @return set of current flow rules
+ */
+ Set<FlowEntry> getCurrentStatistic(ConnectPoint connectPoint);
+
+ /**
+ * Fetches the current observed stats values.
+ *
+ * @param connectPoint the port to fetch information for
+ * @return set of current values
+ */
+ Set<FlowEntry> getPreviousStatistic(ConnectPoint connectPoint);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/package-info.java
new file mode 100644
index 00000000..37889f3d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/statistic/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service for looking up statistics on links.
+ */
+package org.onosproject.net.statistic;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/ClusterId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/ClusterId.java
new file mode 100644
index 00000000..676f0068
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/ClusterId.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Representation of the topology cluster identity.
+ */
+public final class ClusterId {
+
+ private final int id;
+
+ // Public construction is prohibit
+ private ClusterId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * Returns the cluster identifier, represented by the specified integer
+ * serial number.
+ *
+ * @param id integer serial number
+ * @return cluster identifier
+ */
+ public static ClusterId clusterId(int id) {
+ return new ClusterId(id);
+ }
+
+ /**
+ * Returns the backing integer index.
+ *
+ * @return backing integer index
+ */
+ public int index() {
+ return id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ClusterId) {
+ final ClusterId other = (ClusterId) obj;
+ return Objects.equals(this.id, other.id);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("id", id).toString();
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultGraphDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultGraphDescription.java
new file mode 100644
index 00000000..f1e20dac
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultGraphDescription.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import org.onosproject.net.AbstractDescription;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.SparseAnnotations;
+import org.slf4j.Logger;
+
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Default implementation of an immutable topology graph data carrier.
+ */
+public class DefaultGraphDescription extends AbstractDescription
+ implements GraphDescription {
+
+ private static final Logger log = getLogger(DefaultGraphDescription.class);
+
+ private final long nanos;
+ private final long creationTime;
+ private final ImmutableSet<TopologyVertex> vertexes;
+ private final ImmutableSet<TopologyEdge> edges;
+
+ private final Map<DeviceId, TopologyVertex> vertexesById = Maps.newHashMap();
+
+ /**
+ * Creates a minimal topology graph description to allow core to construct
+ * and process the topology graph.
+ *
+ * @param nanos time in nanos of when the topology description was created
+ * @param devices collection of infrastructure devices
+ * @param links collection of infrastructure links
+ * @param annotations optional key/value annotations map
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ public DefaultGraphDescription(long nanos, Iterable<Device> devices,
+ Iterable<Link> links,
+ SparseAnnotations... annotations) {
+ this(nanos, System.currentTimeMillis(), devices, links, annotations);
+ }
+
+ /**
+ * Creates a minimal topology graph description to allow core to construct
+ * and process the topology graph.
+ *
+ * @param nanos time in nanos of when the topology description was created
+ * @param millis time in millis of when the topology description was created
+ * @param devices collection of infrastructure devices
+ * @param links collection of infrastructure links
+ * @param annotations optional key/value annotations map
+ */
+ public DefaultGraphDescription(long nanos, long millis,
+ Iterable<Device> devices,
+ Iterable<Link> links,
+ SparseAnnotations... annotations) {
+ super(annotations);
+ this.nanos = nanos;
+ this.creationTime = millis;
+ this.vertexes = buildVertexes(devices);
+ this.edges = buildEdges(links);
+ vertexesById.clear();
+ }
+
+ @Override
+ public long timestamp() {
+ return nanos;
+ }
+
+ @Override
+ public long creationTime() {
+ return creationTime;
+ }
+
+ @Override
+ public ImmutableSet<TopologyVertex> vertexes() {
+ return vertexes;
+ }
+
+ @Override
+ public ImmutableSet<TopologyEdge> edges() {
+ return edges;
+ }
+
+ // Builds a set of topology vertexes from the specified list of devices
+ private ImmutableSet<TopologyVertex> buildVertexes(Iterable<Device> devices) {
+ ImmutableSet.Builder<TopologyVertex> vertexes = ImmutableSet.builder();
+ for (Device device : devices) {
+ TopologyVertex vertex = new DefaultTopologyVertex(device.id());
+ vertexes.add(vertex);
+ vertexesById.put(vertex.deviceId(), vertex);
+ }
+ return vertexes.build();
+ }
+
+ // Builds a set of topology vertexes from the specified list of links
+ private ImmutableSet<TopologyEdge> buildEdges(Iterable<Link> links) {
+ ImmutableSet.Builder<TopologyEdge> edges = ImmutableSet.builder();
+ for (Link link : links) {
+ try {
+ edges.add(new DefaultTopologyEdge(vertexOf(link.src()),
+ vertexOf(link.dst()),
+ link));
+ } catch (IllegalArgumentException e) {
+ log.debug("Ignoring {}, missing vertex", link);
+ }
+ }
+ return edges.build();
+ }
+
+ // Fetches a vertex corresponding to the given connection point device.
+ private TopologyVertex vertexOf(ConnectPoint connectPoint) {
+ DeviceId id = connectPoint.deviceId();
+ TopologyVertex vertex = vertexesById.get(id);
+ checkArgument(vertex != null, "Vertex missing for %s", id);
+ return vertex;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyCluster.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyCluster.java
new file mode 100644
index 00000000..ac32316c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyCluster.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of a network topology cluster.
+ */
+public class DefaultTopologyCluster implements TopologyCluster {
+
+ private final ClusterId id;
+ private final int deviceCount;
+ private final int linkCount;
+ private final TopologyVertex root;
+
+ /**
+ * Creates a new topology cluster descriptor with the specified attributes.
+ *
+ * @param id cluster id
+ * @param deviceCount number of devices in the cluster
+ * @param linkCount number of links in the cluster
+ * @param root cluster root node
+ */
+ public DefaultTopologyCluster(ClusterId id, int deviceCount, int linkCount,
+ TopologyVertex root) {
+ this.id = id;
+ this.deviceCount = deviceCount;
+ this.linkCount = linkCount;
+ this.root = root;
+ }
+
+ @Override
+ public ClusterId id() {
+ return id;
+ }
+
+ @Override
+ public int deviceCount() {
+ return deviceCount;
+ }
+
+ @Override
+ public int linkCount() {
+ return linkCount;
+ }
+
+ @Override
+ public TopologyVertex root() {
+ return root;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, deviceCount, linkCount, root);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultTopologyCluster) {
+ final DefaultTopologyCluster other = (DefaultTopologyCluster) obj;
+ return Objects.equals(this.id, other.id) &&
+ Objects.equals(this.deviceCount, other.deviceCount) &&
+ Objects.equals(this.linkCount, other.linkCount) &&
+ Objects.equals(this.root, other.root);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("id", id)
+ .add("deviceCount", deviceCount)
+ .add("linkCount", linkCount)
+ .add("root", root)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyEdge.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyEdge.java
new file mode 100644
index 00000000..dacb5fd8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyEdge.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.net.Link;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of the topology edge backed by a link.
+ */
+public class DefaultTopologyEdge implements TopologyEdge {
+
+ private final Link link;
+ private final TopologyVertex src;
+ private final TopologyVertex dst;
+
+ /**
+ * Creates a new topology edge.
+ *
+ * @param src source vertex
+ * @param dst destination vertex
+ * @param link infrastructure link
+ */
+ public DefaultTopologyEdge(TopologyVertex src, TopologyVertex dst, Link link) {
+ this.src = src;
+ this.dst = dst;
+ this.link = link;
+ }
+
+ @Override
+ public Link link() {
+ return link;
+ }
+
+ @Override
+ public TopologyVertex src() {
+ return src;
+ }
+
+ @Override
+ public TopologyVertex dst() {
+ return dst;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(link);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultTopologyEdge) {
+ final DefaultTopologyEdge other = (DefaultTopologyEdge) obj;
+ return Objects.equals(this.link, other.link);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("src", src).add("dst", dst).toString();
+ }
+
+}
+
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyVertex.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyVertex.java
new file mode 100644
index 00000000..07a09cbd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyVertex.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.net.DeviceId;
+
+import java.util.Objects;
+
+/**
+ * Implementation of the topology vertex backed by a device id.
+ */
+public class DefaultTopologyVertex implements TopologyVertex {
+
+ private final DeviceId deviceId;
+
+ /**
+ * Creates a new topology vertex.
+ *
+ * @param deviceId backing infrastructure device identifier
+ */
+ public DefaultTopologyVertex(DeviceId deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deviceId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultTopologyVertex) {
+ final DefaultTopologyVertex other = (DefaultTopologyVertex) obj;
+ return Objects.equals(this.deviceId, other.deviceId);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return deviceId.toString();
+ }
+
+}
+
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/GraphDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/GraphDescription.java
new file mode 100644
index 00000000..806a5a45
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/GraphDescription.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.net.Description;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Describes attribute(s) of a network graph.
+ */
+public interface GraphDescription extends Description {
+
+ /**
+ * Returns the creation timestamp of the graph description. This is
+ * expressed in system nanos to allow proper sequencing.
+ *
+ * @return graph description creation timestamp
+ */
+ long timestamp();
+
+ /**
+ * Returns the creation timestamp of the graph description. This is
+ * expressed in system millis to allow proper date and time formatting.
+ *
+ * @return graph description creation timestamp in millis
+ */
+ long creationTime();
+
+ /**
+ * Returns the set of topology graph vertexes.
+ *
+ * @return set of graph vertexes
+ */
+ ImmutableSet<TopologyVertex> vertexes();
+
+ /**
+ * Returns the set of topology graph edges.
+ *
+ * @return set of graph edges
+ */
+ ImmutableSet<TopologyEdge> edges();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/LinkWeight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/LinkWeight.java
new file mode 100644
index 00000000..a19abd40
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/LinkWeight.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onlab.graph.EdgeWeight;
+
+/**
+ * Entity capable of determining cost or weight of a specified topology
+ * graph edge.
+ */
+public interface LinkWeight extends EdgeWeight<TopologyVertex, TopologyEdge> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathService.java
new file mode 100644
index 00000000..be8c7cfc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/PathService.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.net.ElementId;
+import org.onosproject.net.Path;
+
+import java.util.Set;
+
+/**
+ * Service for obtaining pre-computed paths or for requesting computation of
+ * paths using the current topology snapshot.
+ */
+public interface PathService {
+
+ /**
+ * Returns the set of all shortest paths, precomputed in terms of hop-count,
+ * between the specified source and destination elements.
+ *
+ * @param src source element
+ * @param dst destination element
+ * @return set of all shortest paths between the two elements
+ */
+ Set<Path> getPaths(ElementId src, ElementId dst);
+
+ /**
+ * Returns the set of all shortest paths, computed using the supplied
+ * edge-weight entity, between the specified source and destination
+ * network elements.
+ *
+ * @param src source element
+ * @param dst destination element
+ * @param weight edge-weight entity
+ * @return set of all shortest paths between the two element
+ */
+ Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/Topology.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/Topology.java
new file mode 100644
index 00000000..6337807c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/Topology.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.net.Provided;
+
+/**
+ * Represents a network topology computation snapshot.
+ */
+public interface Topology extends Provided {
+
+ /**
+ * Returns the time, specified in system nanos of when the topology became
+ * available.
+ *
+ * @return time in system nanos
+ */
+ long time();
+
+ /**
+ * Returns the time, specified in system millis of when the topology became
+ * available.
+ *
+ * @return time in system nanos
+ */
+ long creationTime();
+
+ /**
+ * Returns the time, specified in system nanos of how long the topology took
+ * to compute.
+ *
+ * @return elapsed time in system nanos
+ */
+ long computeCost();
+
+ /**
+ * Returns the number of SCCs (strongly connected components) in the
+ * topology.
+ *
+ * @return number of clusters
+ */
+ int clusterCount();
+
+ /**
+ * Returns the number of infrastructure devices in the topology.
+ *
+ * @return number of devices
+ */
+ int deviceCount();
+
+ /**
+ * Returns the number of infrastructure links in the topology.
+ *
+ * @return number of links
+ */
+ int linkCount();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyCluster.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyCluster.java
new file mode 100644
index 00000000..8e685534
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyCluster.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+/**
+ * Representation of an SCC (strongly-connected component) in a network topology.
+ */
+public interface TopologyCluster {
+
+ /**
+ * Returns the cluster id.
+ *
+ * @return cluster identifier
+ */
+ ClusterId id();
+
+ /**
+ * Returns the number of devices in the cluster.
+ *
+ * @return number of cluster devices
+ */
+ int deviceCount();
+
+ /**
+ * Returns the number of infrastructure links in the cluster.
+ *
+ * @return number of cluster links
+ */
+ int linkCount();
+
+ /**
+ * Returns the cluster root vertex.
+ *
+ * @return cluster root vertex
+ */
+ TopologyVertex root();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyEdge.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyEdge.java
new file mode 100644
index 00000000..008c8c44
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyEdge.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onlab.graph.Edge;
+import org.onosproject.net.Link;
+
+/**
+ * Represents an edge in the topology graph.
+ */
+public interface TopologyEdge extends Edge<TopologyVertex> {
+
+ /**
+ * Returns the associated infrastructure link.
+ *
+ * @return backing infrastructure link
+ */
+ Link link();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyEvent.java
new file mode 100644
index 00000000..10c8dfc3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyEvent.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.event.Event;
+
+import java.util.List;
+
+/**
+ * Describes network topology event.
+ */
+public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> {
+
+ private final List<Event> reasons;
+
+ /**
+ * Type of topology events.
+ */
+ public enum Type {
+ /**
+ * Signifies that topology has changed.
+ */
+ TOPOLOGY_CHANGED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified topology and the
+ * current time.
+ *
+ * @param type topology event type
+ * @param topology event topology subject
+ * @param reasons list of events that triggered topology change
+ */
+ public TopologyEvent(Type type, Topology topology, List<Event> reasons) {
+ super(type, topology);
+ this.reasons = reasons;
+ }
+
+ /**
+ * Creates an event of a given type and for the specified topology and time.
+ *
+ * @param type link event type
+ * @param topology event topology subject
+ * @param reasons list of events that triggered topology change
+ * @param time occurrence time
+ */
+ public TopologyEvent(Type type, Topology topology, List<Event> reasons,
+ long time) {
+ super(type, topology, time);
+ this.reasons = reasons;
+ }
+
+
+ /**
+ * Returns the list of events that triggered the topology change.
+ *
+ * @return list of events responsible for change in topology; null if
+ * initial topology computation
+ */
+ public List<Event> reasons() {
+ return reasons;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyGraph.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyGraph.java
new file mode 100644
index 00000000..f3565fa4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyGraph.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onlab.graph.Graph;
+
+/**
+ * Represents an immutable topology graph.
+ */
+public interface TopologyGraph extends Graph<TopologyVertex, TopologyEdge> {
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyListener.java
new file mode 100644
index 00000000..625587b0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving network topology related events.
+ */
+public interface TopologyListener extends EventListener<TopologyEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProvider.java
new file mode 100644
index 00000000..f52b798b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProvider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Means for injecting topology information into the core.
+ */
+public interface TopologyProvider extends Provider {
+
+ /**
+ * Triggers topology recomputation.
+ */
+ void triggerRecompute();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProviderRegistry.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProviderRegistry.java
new file mode 100644
index 00000000..15eeed45
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction of a network topology provider registry.
+ */
+public interface TopologyProviderRegistry extends
+ ProviderRegistry<TopologyProvider, TopologyProviderService> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProviderService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProviderService.java
new file mode 100644
index 00000000..742110a2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyProviderService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.event.Event;
+import org.onosproject.net.provider.ProviderService;
+
+import java.util.List;
+
+/**
+ * Means for injecting topology information into the core.
+ */
+public interface TopologyProviderService extends ProviderService<TopologyProvider> {
+
+ /**
+ * Signals the core that some aspect of the topology has changed.
+ *
+ * @param graphDescription information about the network graph
+ * @param reasons events that triggered topology change
+ */
+ void topologyChanged(GraphDescription graphDescription,
+ List<Event> reasons);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyService.java
new file mode 100644
index 00000000..41eac2c4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyService.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+
+import java.util.Set;
+
+/**
+ * Service for providing network topology information.
+ */
+public interface TopologyService
+ extends ListenerService<TopologyEvent, TopologyListener> {
+
+ /**
+ * Returns the current topology descriptor.
+ *
+ * @return current topology
+ */
+ Topology currentTopology();
+
+ /**
+ * Indicates whether the specified topology is the latest or not.
+ *
+ * @param topology topology descriptor
+ * @return true if the topology is the most recent; false otherwise
+ */
+ boolean isLatest(Topology topology);
+
+ /**
+ * Returns the graph view of the specified topology.
+ *
+ * @param topology topology descriptor
+ * @return topology graph view
+ */
+ TopologyGraph getGraph(Topology topology);
+
+ /**
+ * Returns the set of clusters in the specified topology.
+ *
+ * @param topology topology descriptor
+ * @return set of topology clusters
+ */
+ Set<TopologyCluster> getClusters(Topology topology);
+
+ /**
+ * Returns the cluster with the specified ID.
+ *
+ * @param topology topology descriptor
+ * @param clusterId cluster identifier
+ * @return topology cluster
+ */
+ TopologyCluster getCluster(Topology topology, ClusterId clusterId);
+
+ /**
+ * Returns the set of devices that belong to the specified cluster.
+ *
+ * @param topology topology descriptor
+ * @param cluster topology cluster
+ * @return set of cluster devices
+ */
+ Set<DeviceId> getClusterDevices(Topology topology, TopologyCluster cluster);
+
+ /**
+ * Returns the set of links that form the specified cluster.
+ *
+ * @param topology topology descriptor
+ * @param cluster topology cluster
+ * @return set of cluster links
+ */
+ Set<Link> getClusterLinks(Topology topology, TopologyCluster cluster);
+
+ /**
+ * Returns the set of all shortest paths, precomputed in terms of hop-count,
+ * between the specified source and destination devices.
+ *
+ * @param topology topology descriptor
+ * @param src source device
+ * @param dst destination device
+ * @return set of all shortest paths between the two devices
+ */
+ Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst);
+
+ /**
+ * Returns the set of all shortest paths, computed using the supplied
+ * edge-weight entity, between the specified source and destination devices.
+ *
+ * @param topology topology descriptor
+ * @param src source device
+ * @param dst destination device
+ * @param weight edge-weight entity
+ * @return set of all shortest paths between the two devices
+ */
+ Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
+ LinkWeight weight);
+
+ /**
+ * Indicates whether the specified connection point is part of the network
+ * infrastructure or part of network edge.
+ *
+ * @param topology topology descriptor
+ * @param connectPoint connection point
+ * @return true of connection point is in infrastructure; false if edge
+ */
+ boolean isInfrastructure(Topology topology, ConnectPoint connectPoint);
+
+
+ /**
+ * Indicates whether broadcast is allowed for traffic received on the
+ * specified connection point.
+ *
+ * @param topology topology descriptor
+ * @param connectPoint connection point
+ * @return true if broadcast is permissible
+ */
+ boolean isBroadcastPoint(Topology topology, ConnectPoint connectPoint);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyStore.java
new file mode 100644
index 00000000..983e616e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyStore.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.event.Event;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.store.Store;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Manages inventory of topology snapshots; not intended for direct use.
+ */
+public interface TopologyStore extends Store<TopologyEvent, TopologyStoreDelegate> {
+
+ /**
+ * Returns the current topology snapshot.
+ *
+ * @return current topology descriptor
+ */
+ Topology currentTopology();
+
+ /**
+ * Indicates whether the topology is the latest.
+ *
+ * @param topology topology descriptor
+ * @return true if topology is the most recent one
+ */
+ boolean isLatest(Topology topology);
+
+ /**
+ * Returns the immutable graph view of the current topology.
+ *
+ * @param topology topology descriptor
+ * @return graph view
+ */
+ TopologyGraph getGraph(Topology topology);
+
+ /**
+ * Returns the set of topology SCC clusters.
+ *
+ * @param topology topology descriptor
+ * @return set of clusters
+ */
+ Set<TopologyCluster> getClusters(Topology topology);
+
+ /**
+ * Returns the cluster of the specified topology.
+ *
+ * @param topology topology descriptor
+ * @param clusterId cluster identity
+ * @return topology cluster
+ */
+ TopologyCluster getCluster(Topology topology, ClusterId clusterId);
+
+ /**
+ * Returns the cluster of the specified topology.
+ *
+ * @param topology topology descriptor
+ * @param cluster topology cluster
+ * @return set of cluster links
+ */
+ Set<DeviceId> getClusterDevices(Topology topology, TopologyCluster cluster);
+
+ /**
+ * Returns the cluster of the specified topology.
+ *
+ * @param topology topology descriptor
+ * @param cluster topology cluster
+ * @return set of cluster links
+ */
+ Set<Link> getClusterLinks(Topology topology, TopologyCluster cluster);
+
+ /**
+ * Returns the set of pre-computed shortest paths between src and dest.
+ *
+ * @param topology topology descriptor
+ * @param src source device
+ * @param dst destination device
+ * @return set of shortest paths
+ */
+ Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst);
+
+ /**
+ * Computes and returns the set of shortest paths between src and dest.
+ *
+ * @param topology topology descriptor
+ * @param src source device
+ * @param dst destination device
+ * @param weight link weight function
+ * @return set of shortest paths
+ */
+ Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
+ LinkWeight weight);
+
+ /**
+ * Indicates whether the given connect point is part of the network fabric.
+ *
+ * @param topology topology descriptor
+ * @param connectPoint connection point
+ * @return true if infrastructure; false otherwise
+ */
+ boolean isInfrastructure(Topology topology, ConnectPoint connectPoint);
+
+ /**
+ * Indicates whether broadcast is allowed for traffic received on the
+ * given connection point.
+ *
+ * @param topology topology descriptor
+ * @param connectPoint connection point
+ * @return true if broadcast allowed; false otherwise
+ */
+ boolean isBroadcastPoint(Topology topology, ConnectPoint connectPoint);
+
+ /**
+ * Generates a new topology snapshot from the specified description.
+ *
+ * @param providerId provider identification
+ * @param graphDescription topology graph description
+ * @param reasons list of events that triggered the update
+ * @return topology update event or null if the description is old
+ */
+ TopologyEvent updateTopology(ProviderId providerId,
+ GraphDescription graphDescription,
+ List<Event> reasons);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyStoreDelegate.java
new file mode 100644
index 00000000..c425970b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Topology store delegate abstraction.
+ */
+public interface TopologyStoreDelegate extends StoreDelegate<TopologyEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyVertex.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyVertex.java
new file mode 100644
index 00000000..9f37dcb4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/TopologyVertex.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.topology;
+
+import org.onlab.graph.Vertex;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Represents a vertex in the topology graph.
+ */
+public interface TopologyVertex extends Vertex {
+
+ /**
+ * Returns the associated infrastructure device identification.
+ *
+ * @return device identifier
+ */
+ DeviceId deviceId();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/package-info.java
new file mode 100644
index 00000000..3cd6ceb8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Network topology model &amp; related services API definitions.
+ */
+package org.onosproject.net.topology;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractApiDocRegistrator.java b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractApiDocRegistrator.java
new file mode 100644
index 00000000..7349c69e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractApiDocRegistrator.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.rest;
+
+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;
+
+/**
+ * Self-registering REST API provider.
+ */
+@Component(immediate = true, componentAbstract = true)
+public abstract class AbstractApiDocRegistrator {
+
+ protected final ApiDocProvider provider;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ApiDocService service;
+
+ /**
+ * Creates registrator for the specified REST API doc provider.
+ *
+ * @param provider REST API provider
+ */
+ protected AbstractApiDocRegistrator(ApiDocProvider provider) {
+ this.provider = provider;
+ }
+
+ @Activate
+ protected void activate() {
+ service.register(provider);
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ service.unregister(provider);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractInjectionResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractInjectionResource.java
new file mode 100644
index 00000000..de182f03
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractInjectionResource.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.rest;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Resource for serving semi-static resources.
+ */
+public class AbstractInjectionResource extends AbstractWebResource {
+
+ /**
+ * Returns the index into the supplied string where the end of the
+ * specified pattern is located.
+ *
+ * @param string string to split
+ * @param start index where to start looking for pattern
+ * @param stopPattern optional pattern where to stop
+ * @return index where the split should occur
+ */
+ protected int split(String string, int start, String stopPattern) {
+ int i = stopPattern != null ? string.indexOf(stopPattern, start) : string.length();
+ checkArgument(i >= 0, "Unable to locate pattern %s", stopPattern);
+ return i + (stopPattern != null ? stopPattern.length() : 0);
+ }
+
+ /**
+ * Produces an input stream from the bytes of the specified sub-string.
+ *
+ * @param string source string
+ * @param start index where to start stream
+ * @param end index where to end stream
+ * @return input stream
+ */
+ protected InputStream stream(String string, int start, int end) {
+ return new ByteArrayInputStream(string.substring(start, end).getBytes());
+ }
+
+ /**
+ * Auxiliary enumeration to sequence input streams.
+ */
+ protected class StreamEnumeration implements Enumeration<InputStream> {
+ private final Iterator<InputStream> iterator;
+
+ public StreamEnumeration(List<InputStream> streams) {
+ this.iterator = streams.iterator();
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public InputStream nextElement() {
+ return iterator.next();
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractWebResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractWebResource.java
new file mode 100644
index 00000000..d3249ba5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/AbstractWebResource.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.rest;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.rest.BaseResource;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.CodecService;
+import org.onosproject.codec.JsonCodec;
+
+/**
+ * Abstract REST resource.
+ */
+public class AbstractWebResource extends BaseResource implements CodecContext {
+
+ private final ObjectMapper mapper = new ObjectMapper();
+
+ @Override
+ public ObjectMapper mapper() {
+ return mapper;
+ }
+
+ /**
+ * Returns the JSON codec for the specified entity class.
+ *
+ * @param entityClass entity class
+ * @param <T> entity type
+ * @return JSON codec
+ */
+ public <T> JsonCodec<T> codec(Class<T> entityClass) {
+ return get(CodecService.class).getCodec(entityClass);
+ }
+
+ /**
+ * Returns JSON object wrapping the array encoding of the specified
+ * collection of items.
+ *
+ * @param codecClass codec item class
+ * @param field field holding the array
+ * @param items collection of items to be encoded into array
+ * @param <T> item type
+ * @return JSON object
+ */
+ protected <T> ObjectNode encodeArray(Class<T> codecClass, String field,
+ Iterable<T> items) {
+ ObjectNode result = mapper().createObjectNode();
+ result.set(field, codec(codecClass).encode(items, this));
+ return result;
+ }
+
+ @Override
+ public <T> T getService(Class<T> serviceClass) {
+ return get(serviceClass);
+ }
+
+ /**
+ * Creates and returns a new child object within the specified parent and
+ * bound to the given key.
+ *
+ * @param parent parent object
+ * @param key key for the new child object
+ * @return child object
+ */
+ public ObjectNode newObject(ObjectNode parent, String key) {
+ ObjectNode node = mapper.createObjectNode();
+ parent.set(key, node);
+ return node;
+ }
+
+ /**
+ * Creates and returns a new child array within the specified parent and
+ * bound to the given key.
+ *
+ * @param parent parent object
+ * @param key key for the new child array
+ * @return child array
+ */
+ public ArrayNode newArray(ObjectNode parent, String key) {
+ ArrayNode node = mapper.createArrayNode();
+ parent.set(key, node);
+ return node;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/rest/ApiDocProvider.java b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/ApiDocProvider.java
new file mode 100644
index 00000000..50cac4cd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/ApiDocProvider.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.rest;
+
+import com.google.common.annotations.Beta;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Entity capable of providing REST API documentation resources.
+ */
+@Beta
+public class ApiDocProvider {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private static final String DOCS = "/apidoc/swagger.json";
+ private static final String MODEL = "/apidoc/model.json";
+
+ private final String key;
+ private final String name;
+ private final ClassLoader classLoader;
+
+ /**
+ * Creates a new REST API documentation provider.
+ *
+ * @param key REST API key
+ * @param name REST API name
+ * @param classLoader class loader
+ */
+ public ApiDocProvider(String key, String name, ClassLoader classLoader) {
+ this.key = checkNotNull(key, "Key cannot be null");
+ this.name = checkNotNull(name, "Name cannot be null");
+ this.classLoader = checkNotNull(classLoader, "Class loader cannot be null");
+ }
+
+ /**
+ * Returns the REST API key.
+ *
+ * @return REST API key
+ */
+ public String key() {
+ return key;
+ }
+
+ /**
+ * Returns the REST API name.
+ *
+ * @return REST API name
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns input stream containing Swagger UI compatible JSON.
+ *
+ * @return input stream with Swagger JSON data
+ */
+ public InputStream docs() {
+ return get(DOCS);
+ }
+
+ /**
+ * Returns input stream containing JSON model schema.
+ *
+ * @return input stream with JSON model schema
+ */
+ public InputStream model() {
+ return get(MODEL);
+ }
+
+ private InputStream get(String resource) {
+ InputStream stream = classLoader.getResourceAsStream(resource);
+ if (stream == null) {
+ log.warn("Unable to find JSON resource {}", resource);
+ }
+ return stream;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/rest/ApiDocService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/ApiDocService.java
new file mode 100644
index 00000000..f7268532
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/ApiDocService.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.rest;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Set;
+
+/**
+ * Service for registering REST API documentation resources.
+ */
+@Beta
+public interface ApiDocService {
+
+ /**
+ * Registers the specified REST API documentation provider.
+ *
+ * @param provider REST API documentation provider
+ */
+ void register(ApiDocProvider provider);
+
+ /**
+ * Unregisters the specified REST API documentation provider.
+ *
+ * @param provider REST API documentation provider
+ */
+ void unregister(ApiDocProvider provider);
+
+ /**
+ * Returns the set of all registered REST API documentation providers.
+ *
+ * @return set of registered documentation providers
+ */
+ Set<ApiDocProvider> getDocProviders();
+
+ /**
+ * Returns the specified REST API documentation provider with the specified
+ * key.
+ *
+ * @param key REST API key
+ * @return documentation provider
+ */
+ ApiDocProvider getDocProvider(String key);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/rest/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/package-info.java
new file mode 100644
index 00000000..15e5d20d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/rest/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Base abstractions and utilities for developing REST APIs.
+ */
+package org.onosproject.rest; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/security/AppGuard.java b/framework/src/onos/core/api/src/main/java/org/onosproject/security/AppGuard.java
new file mode 100644
index 00000000..800135f4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/security/AppGuard.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.security;
+
+
+/**
+ * Aids SM-ONOS to perform API-level permission checking.
+ */
+public final class AppGuard {
+
+ private AppGuard() {
+ }
+
+ /**
+ * Checks if the caller has the required permission only when security-mode is enabled.
+ * @param permission permission to be checked
+ */
+ public static void checkPermission(AppPermission.Type permission) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ System.getSecurityManager().checkPermission(new AppPermission(permission));
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/security/AppPermission.java b/framework/src/onos/core/api/src/main/java/org/onosproject/security/AppPermission.java
new file mode 100644
index 00000000..21a70d2b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/security/AppPermission.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.security;
+
+import java.security.BasicPermission;
+
+/**
+ * Implementation of API access permission.
+ */
+public class AppPermission extends BasicPermission {
+
+ public enum Type {
+ APP_READ,
+ APP_EVENT,
+ CONFIG_READ,
+ CONFIG_WRITE,
+ CLUSTER_READ,
+ CLUSTER_WRITE,
+ CLUSTER_EVENT,
+ DEVICE_READ,
+ DEVICE_EVENT,
+ DRIVER_READ,
+ DRIVER_WRITE,
+ FLOWRULE_READ,
+ FLOWRULE_WRITE,
+ FLOWRULE_EVENT,
+ GROUP_READ,
+ GROUP_WRITE,
+ GROUP_EVENT,
+ HOST_READ,
+ HOST_WRITE,
+ HOST_EVENT,
+ INTENT_READ,
+ INTENT_WRITE,
+ INTENT_EVENT,
+ LINK_READ,
+ LINK_WRITE,
+ LINK_EVENT,
+ PACKET_READ,
+ PACKET_WRITE,
+ PACKET_EVENT,
+ STATISTIC_READ,
+ TOPOLOGY_READ,
+ TOPOLOGY_EVENT,
+ TUNNEL_READ,
+ TUNNEL_WRITE,
+ TUNNEL_EVENT,
+ STORAGE_WRITE
+ }
+
+ protected Type type;
+ /**
+ * Creates new application permission using the supplied data.
+ * @param name permission name
+ */
+ public AppPermission(String name) {
+ super(name.toUpperCase(), "");
+ try {
+ type = Type.valueOf(name);
+ } catch (IllegalArgumentException e) {
+ type = null;
+ }
+ }
+
+ /**
+ * Creates new application permission using the supplied data.
+ * @param name permission name
+ * @param actions permission action
+ */
+ public AppPermission(String name, String actions) {
+ super(name.toUpperCase(), actions);
+ try {
+ type = Type.valueOf(name);
+ } catch (IllegalArgumentException e) {
+ type = null;
+ }
+ }
+
+ /**
+ * Crates new application permission using the supplied data.
+ * @param type permission type
+ */
+ public AppPermission(Type type) {
+ super(type.name(), "");
+ this.type = type;
+ }
+
+ /**
+ * Returns type of permission.
+ * @return application permission type
+ */
+ public Type getType() {
+ return this.type;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/security/Permission.java b/framework/src/onos/core/api/src/main/java/org/onosproject/security/Permission.java
new file mode 100644
index 00000000..75d9433f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/security/Permission.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.security;
+
+public class Permission {
+
+ protected String classname;
+ protected String name;
+ protected String actions;
+
+ public Permission(String classname, String name, String actions) {
+ this.classname = classname;
+ this.name = name;
+ if (actions == null) {
+ this.actions = "";
+ } else {
+ this.actions = actions;
+ }
+ }
+
+ public Permission(String classname, String name) {
+ this.classname = classname;
+ this.name = name;
+ this.actions = "";
+ }
+
+ public String getClassName() {
+ return classname;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getActions() {
+ return actions;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object thatPerm) {
+ if (this == thatPerm) {
+ return true;
+ }
+
+ if (!(thatPerm instanceof Permission)) {
+ return false;
+ }
+
+ Permission that = (Permission) thatPerm;
+ return (this.classname.equals(that.classname)) && (this.name.equals(that.name))
+ && (this.actions.equals(that.actions));
+ }
+
+ @Override
+ public String toString() {
+ return String.format("(%s, %s, %s)", classname, name, actions);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/security/SecurityAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/security/SecurityAdminService.java
new file mode 100644
index 00000000..16ea94d1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/security/SecurityAdminService.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.security;
+
+import org.onosproject.core.ApplicationId;
+
+import java.security.Permission;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Security-Mode ONOS service.
+ */
+public interface SecurityAdminService {
+
+ /**
+ * Returns true if security policy has been enforced to specified application.
+ * @param appId application identifier
+ * @return true if secured.
+ */
+ boolean isSecured(ApplicationId appId);
+
+ /**
+ * Changes SecurityModeState of specified application to REVIEWED.
+ * @param appId application identifier
+ */
+ void review(ApplicationId appId);
+
+ /**
+ * Accepts and enforces security policy to specified application.
+ * @param appId application identifier
+ */
+ void acceptPolicy(ApplicationId appId);
+
+ /**
+ * Register application to SM-ONOS subsystem.
+ * @param appId application identifier
+ */
+ void register(ApplicationId appId);
+
+ /**
+ * Returns sorted developer specified permission Map.
+ * @param appId application identifier
+ * @return Map of list of permissions sorted by permission type
+ */
+ Map<Integer, List<Permission>> getPrintableSpecifiedPermissions(ApplicationId appId);
+
+ /**
+ * Returns sorted granted permission Map.
+ * @param appId application identifier
+ * @return Map of list of permissions sorted by permission type
+ */
+ Map<Integer, List<Permission>> getPrintableGrantedPermissions(ApplicationId appId);
+
+ /**
+ * Returns sorted requested permission Map.
+ * @param appId application identifier
+ * @return Map of list of permissions sorted by permission type
+ */
+ Map<Integer, List<Permission>> getPrintableRequestedPermissions(ApplicationId appId);
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/security/SecurityUtil.java b/framework/src/onos/core/api/src/main/java/org/onosproject/security/SecurityUtil.java
new file mode 100644
index 00000000..34b4e78a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/security/SecurityUtil.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.security;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.ServiceNotFoundException;
+import org.onosproject.core.ApplicationId;
+
+/**
+ * Utility class to aid Security-Mode ONOS.
+ */
+public final class SecurityUtil {
+
+ protected static ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+
+ private SecurityUtil() {
+ }
+
+ public static boolean isSecurityModeEnabled() {
+ if (System.getSecurityManager() != null) {
+ try {
+ SecurityAdminService securityService = serviceDirectory.get(SecurityAdminService.class);
+ if (securityService != null) {
+ return true;
+ }
+ } catch (ServiceNotFoundException e) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ public static SecurityAdminService getSecurityService() {
+ if (System.getSecurityManager() != null) {
+ try {
+ SecurityAdminService securityService = serviceDirectory.get(SecurityAdminService.class);
+ if (securityService != null) {
+ return securityService;
+ }
+ } catch (ServiceNotFoundException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public static boolean isAppSecured(ApplicationId appId) {
+ SecurityAdminService service = getSecurityService();
+ if (service != null) {
+ if (!service.isSecured(appId)) {
+ System.out.println("\n*******************************");
+ System.out.println(" SM-ONOS APP WARNING ");
+ System.out.println("*******************************");
+ System.out.println(appId.name() + " has not been secured.");
+ System.out.println("Please review before activating.");
+ return false;
+ }
+ }
+ return true;
+ }
+ public static void register(ApplicationId appId) {
+ SecurityAdminService service = getSecurityService();
+ if (service != null) {
+ service.register(appId);
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/security/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/security/package-info.java
new file mode 100644
index 00000000..88c3529d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/security/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Application security constructs.
+ */
+package org.onosproject.security; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/AbstractStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/AbstractStore.java
new file mode 100644
index 00000000..a3005e45
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/AbstractStore.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store;
+
+import java.util.List;
+
+import org.onosproject.event.Event;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Base implementation of a store.
+ */
+public class AbstractStore<E extends Event, D extends StoreDelegate<E>>
+ implements Store<E, D> {
+
+ protected D delegate;
+
+ @Override
+ public void setDelegate(D delegate) {
+ checkState(this.delegate == null || this.delegate == delegate,
+ "Store delegate already set");
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void unsetDelegate(D delegate) {
+ if (this.delegate == delegate) {
+ this.delegate = null;
+ }
+ }
+
+ @Override
+ public boolean hasDelegate() {
+ return delegate != null;
+ }
+
+ /**
+ * Notifies the delegate with the specified event.
+ *
+ * @param event event to delegate
+ */
+ protected void notifyDelegate(E event) {
+ if (delegate != null) {
+ delegate.notify(event);
+ }
+ }
+
+ /**
+ * Notifies the delegate with the specified list of events.
+ *
+ * @param events list of events to delegate
+ */
+ protected void notifyDelegate(List<E> events) {
+ for (E event: events) {
+ notifyDelegate(event);
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/Store.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/Store.java
new file mode 100644
index 00000000..8d5b53c4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/Store.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store;
+
+import org.onosproject.event.Event;
+
+/**
+ * Abstraction of a entity capable of storing and/or distributing information
+ * across a cluster.
+ */
+public interface Store<E extends Event, D extends StoreDelegate<E>> {
+
+ /**
+ * Sets the delegate on the store.
+ *
+ * @param delegate new store delegate
+ * @throws java.lang.IllegalStateException if a delegate is already
+ * currently set on the store and is a different one that
+ */
+ void setDelegate(D delegate);
+
+ /**
+ * Withdraws the delegate from the store.
+ *
+ * @param delegate store delegate to withdraw
+ * @throws java.lang.IllegalArgumentException if the delegate is not
+ * currently set on the store
+ */
+ void unsetDelegate(D delegate);
+
+ /**
+ * Indicates whether the store has a delegate.
+ *
+ * @return true if delegate is set
+ */
+ boolean hasDelegate();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/StoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/StoreDelegate.java
new file mode 100644
index 00000000..71ca8cc0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/StoreDelegate.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store;
+
+import org.onosproject.event.Event;
+
+/**
+ * Entity associated with a store and capable of receiving notifications of
+ * events within the store.
+ */
+public interface StoreDelegate<E extends Event> {
+
+ /**
+ * Notifies the delegate via the specified event.
+ *
+ * @param event store generated event
+ */
+ void notify(E event);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/Timestamp.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/Timestamp.java
new file mode 100644
index 00000000..44238ff2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/Timestamp.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Opaque version structure.
+ * <p>
+ * Classes implementing this interface must also implement
+ * {@link #hashCode()} and {@link #equals(Object)}.
+ */
+public interface Timestamp extends Comparable<Timestamp> {
+
+ @Override
+ int hashCode();
+
+ @Override
+ boolean equals(Object obj);
+
+ /**
+ * Tests if this timestamp is newer than the specified timestamp.
+ *
+ * @param other timestamp to compare against
+ * @return true if this instance is newer
+ */
+ default boolean isNewerThan(Timestamp other) {
+ return this.compareTo(checkNotNull(other)) > 0;
+ }
+
+ /**
+ * Tests if this timestamp is older than the specified timestamp.
+ *
+ * @param other timestamp to compare against
+ * @return true if this instance is older
+ */
+ default boolean isOlderThan(Timestamp other) {
+ return this.compareTo(checkNotNull(other)) < 0;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterCommunicationService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterCommunicationService.java
new file mode 100644
index 00000000..161a8528
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterCommunicationService.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.cluster.messaging;
+
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.onosproject.cluster.NodeId;
+
+/**
+ * Service for assisting communications between controller cluster nodes.
+ */
+public interface ClusterCommunicationService {
+
+ /**
+ * Adds a new subscriber for the specified message subject.
+ *
+ * @param subject message subject
+ * @param subscriber message subscriber
+ * @param executor executor to use for running handler.
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ void addSubscriber(MessageSubject subject, ClusterMessageHandler subscriber, ExecutorService executor);
+
+ /**
+ * Broadcasts a message to all controller nodes.
+ *
+ * @param message message to send
+ * @param subject message subject
+ * @param encoder function for encoding message to byte[]
+ * @param <M> message type
+ */
+ <M> void broadcast(M message,
+ MessageSubject subject,
+ Function<M, byte[]> encoder);
+
+ /**
+ * Broadcasts a message to all controller nodes including self.
+ *
+ * @param message message to send
+ * @param subject message subject
+ * @param encoder function for encoding message to byte[]
+ * @param <M> message type
+ */
+ <M> void broadcastIncludeSelf(M message,
+ MessageSubject subject,
+ Function<M, byte[]> encoder);
+
+ /**
+ * Sends a message to the specified controller node.
+ *
+ * @param message message to send
+ * @param subject message subject
+ * @param encoder function for encoding message to byte[]
+ * @param toNodeId destination node identifier
+ * @param <M> message type
+ * @return future that is completed when the message is sent
+ */
+ <M> CompletableFuture<Void> unicast(M message,
+ MessageSubject subject,
+ Function<M, byte[]> encoder,
+ NodeId toNodeId);
+
+ /**
+ * Multicasts a message to a set of controller nodes.
+ *
+ * @param message message to send
+ * @param subject message subject
+ * @param encoder function for encoding message to byte[]
+ * @param nodeIds recipient node identifiers
+ * @param <M> message type
+ */
+ <M> void multicast(M message,
+ MessageSubject subject,
+ Function<M, byte[]> encoder,
+ Set<NodeId> nodeIds);
+
+ /**
+ * Sends a message and expects a reply.
+ *
+ * @param message message to send
+ * @param subject message subject
+ * @param encoder function for encoding request to byte[]
+ * @param decoder function for decoding response from byte[]
+ * @param toNodeId recipient node identifier
+ * @param <M> request type
+ * @param <R> reply type
+ * @return reply future
+ */
+ <M, R> CompletableFuture<R> sendAndReceive(M message,
+ MessageSubject subject,
+ Function<M, byte[]> encoder,
+ Function<byte[], R> decoder,
+ NodeId toNodeId);
+
+ /**
+ * Adds a new subscriber for the specified message subject.
+ *
+ * @param subject message subject
+ * @param decoder decoder for resurrecting incoming message
+ * @param handler handler function that processes the incoming message and produces a reply
+ * @param encoder encoder for serializing reply
+ * @param executor executor to run this handler on
+ * @param <M> incoming message type
+ * @param <R> reply message type
+ */
+ <M, R> void addSubscriber(MessageSubject subject,
+ Function<byte[], M> decoder,
+ Function<M, R> handler,
+ Function<R, byte[]> encoder,
+ Executor executor);
+
+ /**
+ * Adds a new subscriber for the specified message subject.
+ *
+ * @param subject message subject
+ * @param decoder decoder for resurrecting incoming message
+ * @param handler handler function that processes the incoming message and produces a reply
+ * @param encoder encoder for serializing reply
+ * @param <M> incoming message type
+ * @param <R> reply message type
+ */
+ <M, R> void addSubscriber(MessageSubject subject,
+ Function<byte[], M> decoder,
+ Function<M, CompletableFuture<R>> handler,
+ Function<R, byte[]> encoder);
+
+ /**
+ * Adds a new subscriber for the specified message subject.
+ *
+ * @param subject message subject
+ * @param decoder decoder to resurrecting incoming message
+ * @param handler handler for handling message
+ * @param executor executor to run this handler on
+ * @param <M> incoming message type
+ */
+ <M> void addSubscriber(MessageSubject subject,
+ Function<byte[], M> decoder,
+ Consumer<M> handler,
+ Executor executor);
+
+ /**
+ * Removes a subscriber for the specified message subject.
+ *
+ * @param subject message subject
+ */
+ void removeSubscriber(MessageSubject subject);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessage.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessage.java
new file mode 100644
index 00000000..46560e4c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessage.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.cluster.messaging;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Objects;
+
+import org.onlab.util.ByteArraySizeHashPrinter;
+import org.onosproject.cluster.NodeId;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.MoreObjects;
+
+// TODO: Should payload type be ByteBuffer?
+/**
+ * Base message for cluster-wide communications.
+ */
+public class ClusterMessage {
+
+ private final NodeId sender;
+ private final MessageSubject subject;
+ private final byte[] payload;
+ private transient byte[] response;
+
+ /**
+ * Creates a cluster message.
+ *
+ * @param sender message sender
+ * @param subject message subject
+ * @param payload message payload
+ */
+ public ClusterMessage(NodeId sender, MessageSubject subject, byte[] payload) {
+ this.sender = sender;
+ this.subject = subject;
+ this.payload = payload;
+ }
+
+ /**
+ * Returns the id of the controller sending this message.
+ *
+ * @return message sender id.
+ */
+ public NodeId sender() {
+ return sender;
+ }
+
+ /**
+ * Returns the message subject indicator.
+ *
+ * @return message subject
+ */
+ public MessageSubject subject() {
+ return subject;
+ }
+
+ /**
+ * Returns the message payload.
+ *
+ * @return message payload.
+ */
+ public byte[] payload() {
+ return payload;
+ }
+
+ /**
+ * Records the response to be sent to the sender.
+ *
+ * @param data response payload
+ */
+ public void respond(byte[] data) {
+ response = data;
+ }
+
+ /**
+ * Returns the response to be sent to the sender.
+ *
+ * @return response bytes
+ */
+ public byte[] response() {
+ return response;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("sender", sender)
+ .add("subject", subject)
+ .add("payload", ByteArraySizeHashPrinter.of(payload))
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof ClusterMessage)) {
+ return false;
+ }
+
+ ClusterMessage that = (ClusterMessage) o;
+
+ return Objects.equals(this.sender, that.sender) &&
+ Objects.equals(this.subject, that.subject) &&
+ Arrays.equals(this.payload, that.payload);
+ }
+
+ /**
+ * Serializes this instance.
+ * @return bytes
+ */
+ public byte[] getBytes() {
+ byte[] senderBytes = sender.toString().getBytes(Charsets.UTF_8);
+ byte[] subjectBytes = subject.value().getBytes(Charsets.UTF_8);
+ int capacity = 12 + senderBytes.length + subjectBytes.length + payload.length;
+ ByteBuffer buffer = ByteBuffer.allocate(capacity);
+ buffer.putInt(senderBytes.length);
+ buffer.put(senderBytes);
+ buffer.putInt(subjectBytes.length);
+ buffer.put(subjectBytes);
+ buffer.putInt(payload.length);
+ buffer.put(payload);
+ return buffer.array();
+ }
+
+ /**
+ * Decodes a new ClusterMessage from raw bytes.
+ * @param bytes raw bytes
+ * @return cluster message
+ */
+ public static ClusterMessage fromBytes(byte[] bytes) {
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ byte[] senderBytes = new byte[buffer.getInt()];
+ buffer.get(senderBytes);
+ byte[] subjectBytes = new byte[buffer.getInt()];
+ buffer.get(subjectBytes);
+ byte[] payloadBytes = new byte[buffer.getInt()];
+ buffer.get(payloadBytes);
+
+ return new ClusterMessage(new NodeId(new String(senderBytes, Charsets.UTF_8)),
+ new MessageSubject(new String(subjectBytes, Charsets.UTF_8)),
+ payloadBytes);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(sender, subject, payload);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessageHandler.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessageHandler.java
new file mode 100644
index 00000000..ce770a81
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessageHandler.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.cluster.messaging;
+
+/**
+ * Interface for handling cluster messages.
+ */
+public interface ClusterMessageHandler {
+
+ /**
+ * Handles/Processes the cluster message.
+ * @param message cluster message.
+ */
+ void handle(ClusterMessage message);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/Endpoint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/Endpoint.java
new file mode 100644
index 00000000..2ac50dfd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/Endpoint.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.cluster.messaging;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+import org.onlab.packet.IpAddress;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Representation of a TCP/UDP communication end point.
+ */
+public final class Endpoint {
+
+ private final int port;
+ private final IpAddress ip;
+
+ public Endpoint(IpAddress host, int port) {
+ this.ip = checkNotNull(host);
+ this.port = port;
+ }
+
+ public IpAddress host() {
+ return ip;
+ }
+
+ public int port() {
+ return port;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("ip", ip)
+ .add("port", port)
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ip, port);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Endpoint that = (Endpoint) obj;
+ return Objects.equals(this.port, that.port) &&
+ Objects.equals(this.ip, that.ip);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/MessageSubject.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/MessageSubject.java
new file mode 100644
index 00000000..8d5e313d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/MessageSubject.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.cluster.messaging;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+/**
+ * Representation of a message subject.
+ * Cluster messages have associated subjects that dictate how they get handled
+ * on the receiving side.
+ */
+public final class MessageSubject {
+
+ private final String value;
+
+ public MessageSubject(String value) {
+ this.value = checkNotNull(value);
+ }
+
+ public String value() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ MessageSubject that = (MessageSubject) obj;
+ return Objects.equals(this.value, that.value);
+ }
+
+ // for serializer
+ protected MessageSubject() {
+ this.value = "";
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/MessagingService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/MessagingService.java
new file mode 100644
index 00000000..6ccd4835
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/MessagingService.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.cluster.messaging;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * Interface for low level messaging primitives.
+ */
+public interface MessagingService {
+
+ /**
+ * Sends a message asynchronously to the specified communication end point.
+ * The message is specified using the type and payload.
+ * @param ep end point to send the message to.
+ * @param type type of message.
+ * @param payload message payload bytes.
+ * @return future that is completed when the message is sent
+ */
+ CompletableFuture<Void> sendAsync(Endpoint ep, String type, byte[] payload);
+
+ /**
+ * Sends a message synchronously and waits for a response.
+ * @param ep end point to send the message to.
+ * @param type type of message.
+ * @param payload message payload.
+ * @return a response future
+ */
+ CompletableFuture<byte[]> sendAndReceive(Endpoint ep, String type, byte[] payload);
+
+ /**
+ * Registers a new message handler for message type.
+ * @param type message type.
+ * @param handler message handler
+ * @param executor executor to use for running message handler logic.
+ */
+ void registerHandler(String type, Consumer<byte[]> handler, Executor executor);
+
+ /**
+ * Registers a new message handler for message type.
+ * @param type message type.
+ * @param handler message handler
+ * @param executor executor to use for running message handler logic.
+ */
+ void registerHandler(String type, Function<byte[], byte[]> handler, Executor executor);
+
+ /**
+ * Registers a new message handler for message type.
+ * @param type message type.
+ * @param handler message handler
+ */
+ void registerHandler(String type, Function<byte[], CompletableFuture<byte[]>> handler);
+
+ /**
+ * Unregister current handler, if one exists for message type.
+ * @param type message type
+ */
+ void unregisterHandler(String type);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/package-info.java
new file mode 100644
index 00000000..582c50ed
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/cluster/messaging/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Cluster messaging APIs for the use by the various distributed stores.
+ */
+package org.onosproject.store.cluster.messaging;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/package-info.java
new file mode 100644
index 00000000..b6269ea5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Abstractions for creating and interacting with distributed stores.
+ */
+package org.onosproject.store;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AsyncAtomicCounter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AsyncAtomicCounter.java
new file mode 100644
index 00000000..a879cc59
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AsyncAtomicCounter.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * An async atomic counter dispenses monotonically increasing values.
+ */
+public interface AsyncAtomicCounter {
+
+ /**
+ * Atomically increment by one the current value.
+ *
+ * @return updated value
+ */
+ CompletableFuture<Long> incrementAndGet();
+
+ /**
+ * Atomically increment by one the current value.
+ *
+ * @return previous value
+ */
+ CompletableFuture<Long> getAndIncrement();
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return previous value
+ */
+ CompletableFuture<Long> getAndAdd(long delta);
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return updated value
+ */
+ CompletableFuture<Long> addAndGet(long delta);
+
+ /**
+ * Returns the current value of the counter without modifying it.
+ *
+ * @return current value
+ */
+ CompletableFuture<Long> get();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AsyncConsistentMap.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AsyncConsistentMap.java
new file mode 100644
index 00000000..fee8cfa6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AsyncConsistentMap.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+import java.util.Collection;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * A distributed, strongly consistent map whose methods are all executed asynchronously.
+ * <p>
+ * This map offers strong read-after-update (where update == create/update/delete)
+ * consistency. All operations to the map are serialized and applied in a consistent
+ * manner.
+ * <p>
+ * The stronger consistency comes at the expense of availability in
+ * the event of a network partition. A network partition can be either due to
+ * a temporary disruption in network connectivity between participating nodes
+ * or due to a node being temporarily down.
+ * </p><p>
+ * All values stored in this map are versioned and the API supports optimistic
+ * concurrency by allowing conditional updates that take into consideration
+ * the version or value that was previously read.
+ * </p><p>
+ * This map does not allow null values. All methods can throw a ConsistentMapException
+ * (which extends RuntimeException) to indicate failures.
+ *
+ */
+public interface AsyncConsistentMap<K, V> {
+
+ /**
+ * Returns the number of entries in the map.
+ *
+ * @return a future for map size.
+ */
+ CompletableFuture<Integer> size();
+
+ /**
+ * Returns true if the map is empty.
+ *
+ * @return a future whose value will be true if map has no entries, false otherwise.
+ */
+ CompletableFuture<Boolean> isEmpty();
+
+ /**
+ * Returns true if this map contains a mapping for the specified key.
+ *
+ * @param key key
+ * @return a future whose value will be true if map contains key, false otherwise.
+ */
+ CompletableFuture<Boolean> containsKey(K key);
+
+ /**
+ * Returns true if this map contains the specified value.
+ *
+ * @param value value
+ * @return a future whose value will be true if map contains value, false otherwise.
+ */
+ CompletableFuture<Boolean> containsValue(V value);
+
+ /**
+ * Returns the value (and version) to which the specified key is mapped, or null if this
+ * map contains no mapping for the key.
+ *
+ * @param key the key whose associated value (and version) is to be returned
+ * @return a future value (and version) to which the specified key is mapped, or null if
+ * this map contains no mapping for the key
+ */
+ CompletableFuture<Versioned<V>> get(K key);
+
+ /**
+ * If the specified key is not already associated with a value (or is mapped to null),
+ * attempts to compute its value using the given mapping function and enters it into
+ * this map unless null.
+ * If a conflicting concurrent modification attempt is detected, the returned future
+ * will be completed exceptionally with ConsistentMapException.ConcurrentModification.
+ * @param key key with which the specified value is to be associated
+ * @param mappingFunction the function to compute a value
+ * @return the current (existing or computed) value associated with the specified key,
+ * or null if the computed value is null
+ */
+ CompletableFuture<Versioned<V>> computeIfAbsent(K key,
+ Function<? super K, ? extends V> mappingFunction);
+
+ /**
+ * If the value for the specified key is present and non-null, attempts to compute a new
+ * mapping given the key and its current mapped value.
+ * If the computed value is null, the current mapping will be removed from the map.
+ * If a conflicting concurrent modification attempt is detected, the returned future
+ * will be completed exceptionally with ConsistentMapException.ConcurrentModification.
+ * @param key key with which the specified value is to be associated
+ * @param remappingFunction the function to compute a value
+ * @return the new value associated with the specified key, or null if computed value is null
+ */
+ CompletableFuture<Versioned<V>> computeIfPresent(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction);
+
+ /**
+ * Attempts to compute a mapping for the specified key and its current mapped value (or
+ * null if there is no current mapping).
+ * If the computed value is null, the current mapping (if one exists) will be removed from the map.
+ * If a conflicting concurrent modification attempt is detected, the returned future
+ * will be completed exceptionally with ConsistentMapException.ConcurrentModification.
+ * @param key key with which the specified value is to be associated
+ * @param remappingFunction the function to compute a value
+ * @return the new value associated with the specified key, or null if computed value is null
+ */
+ CompletableFuture<Versioned<V>> compute(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction);
+
+ /**
+ * If the value for the specified key satisfies a condition, attempts to compute a new
+ * mapping given the key and its current mapped value.
+ * If the computed value is null, the current mapping will be removed from the map.
+ * If a conflicting concurrent modification attempt is detected, the returned future
+ * will be completed exceptionally with ConsistentMapException.ConcurrentModification.
+ * @param key key with which the specified value is to be associated
+ * @param condition condition that should evaluate to true for the computation to proceed
+ * @param remappingFunction the function to compute a value
+ * @return the new value associated with the specified key, or the old value if condition evaluates to false
+ */
+ CompletableFuture<Versioned<V>> computeIf(K key,
+ Predicate<? super V> condition,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction);
+
+ /**
+ * Associates the specified value with the specified key in this map (optional operation).
+ * If the map previously contained a mapping for the key, the old value is replaced by the
+ * specified value.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value (and version) associated with key, or null if there was
+ * no mapping for key.
+ */
+ CompletableFuture<Versioned<V>> put(K key, V value);
+
+ /**
+ * Associates the specified value with the specified key in this map (optional operation).
+ * If the map previously contained a mapping for the key, the old value is replaced by the
+ * specified value.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return new value.
+ */
+ CompletableFuture<Versioned<V>> putAndGet(K key, V value);
+
+ /**
+ * Removes the mapping for a key from this map if it is present (optional operation).
+ *
+ * @param key key whose value is to be removed from the map
+ * @return the value (and version) to which this map previously associated the key,
+ * or null if the map contained no mapping for the key.
+ */
+ CompletableFuture<Versioned<V>> remove(K key);
+
+ /**
+ * Removes all of the mappings from this map (optional operation).
+ * The map will be empty after this call returns.
+ * @return future that will be successfully completed when the map is cleared
+ */
+ CompletableFuture<Void> clear();
+
+ /**
+ * Returns a Set view of the keys contained in this map.
+ * This method differs from the behavior of java.util.Map.keySet() in that
+ * what is returned is a unmodifiable snapshot view of the keys in the ConsistentMap.
+ * Attempts to modify the returned set, whether direct or via its iterator,
+ * result in an UnsupportedOperationException.
+ *
+ * @return a set of the keys contained in this map
+ */
+ CompletableFuture<Set<K>> keySet();
+
+ /**
+ * Returns the collection of values (and associated versions) contained in this map.
+ * This method differs from the behavior of java.util.Map.values() in that
+ * what is returned is a unmodifiable snapshot view of the values in the ConsistentMap.
+ * Attempts to modify the returned collection, whether direct or via its iterator,
+ * result in an UnsupportedOperationException.
+ *
+ * @return a collection of the values (and associated versions) contained in this map
+ */
+ CompletableFuture<Collection<Versioned<V>>> values();
+
+ /**
+ * Returns the set of entries contained in this map.
+ * This method differs from the behavior of java.util.Map.entrySet() in that
+ * what is returned is a unmodifiable snapshot view of the entries in the ConsistentMap.
+ * Attempts to modify the returned set, whether direct or via its iterator,
+ * result in an UnsupportedOperationException.
+ *
+ * @return set of entries contained in this map.
+ */
+ CompletableFuture<Set<Entry<K, Versioned<V>>>> entrySet();
+
+ /**
+ * If the specified key is not already associated with a value
+ * associates it with the given value and returns null, else returns the current value.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with the specified key or null
+ * if key does not already mapped to a value.
+ */
+ CompletableFuture<Versioned<V>> putIfAbsent(K key, V value);
+
+ /**
+ * Removes the entry for the specified key only if it is currently
+ * mapped to the specified value.
+ *
+ * @param key key with which the specified value is associated
+ * @param value value expected to be associated with the specified key
+ * @return true if the value was removed
+ */
+ CompletableFuture<Boolean> remove(K key, V value);
+
+ /**
+ * Removes the entry for the specified key only if its current
+ * version in the map is equal to the specified version.
+ *
+ * @param key key with which the specified version is associated
+ * @param version version expected to be associated with the specified key
+ * @return true if the value was removed
+ */
+ CompletableFuture<Boolean> remove(K key, long version);
+
+ /**
+ * Replaces the entry for the specified key only if currently mapped
+ * to the specified value.
+ *
+ * @param key key with which the specified value is associated
+ * @param oldValue value expected to be associated with the specified key
+ * @param newValue value to be associated with the specified key
+ * @return true if the value was replaced
+ */
+ CompletableFuture<Boolean> replace(K key, V oldValue, V newValue);
+
+ /**
+ * Replaces the entry for the specified key only if it is currently mapped to the
+ * specified version.
+ *
+ * @param key key key with which the specified value is associated
+ * @param oldVersion version expected to be associated with the specified key
+ * @param newValue value to be associated with the specified key
+ * @return true if the value was replaced
+ */
+ CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue);
+
+ /**
+ * Registers the specified listener to be notified whenever the map is updated.
+ *
+ * @param listener listener to notify about map events
+ */
+ void addListener(MapEventListener<K, V> listener);
+
+ /**
+ * Unregisters the specified listener such that it will no longer
+ * receive map change notifications.
+ *
+ * @param listener listener to unregister
+ */
+ void removeListener(MapEventListener<K, V> listener);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicCounter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicCounter.java
new file mode 100644
index 00000000..f620e082
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicCounter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Distributed version of java.util.concurrent.atomic.AtomicLong.
+ */
+public interface AtomicCounter {
+
+ /**
+ * Atomically increment by one the current value.
+ *
+ * @return updated value
+ */
+ long incrementAndGet();
+
+ /**
+ * Atomically increment by one the current value.
+ *
+ * @return previous value
+ */
+ long getAndIncrement();
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return previous value
+ */
+ long getAndAdd(long delta);
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return updated value
+ */
+ long addAndGet(long delta);
+
+ /**
+ * Returns the current value of the counter without modifying it.
+ *
+ * @return current value
+ */
+ long get();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicCounterBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicCounterBuilder.java
new file mode 100644
index 00000000..41a19f0d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicCounterBuilder.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Builder for AtomicCounter.
+ */
+public interface AtomicCounterBuilder {
+
+ /**
+ * Sets the name for the atomic counter.
+ * <p>
+ * Each atomic counter is identified by a unique name.
+ * </p>
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param name name of the atomic counter
+ * @return this AtomicCounterBuilder
+ */
+ AtomicCounterBuilder withName(String name);
+
+ /**
+ * Creates this counter on the partition that spans the entire cluster.
+ * <p>
+ * When partitioning is disabled, the counter state will be
+ * ephemeral and does not survive a full cluster restart.
+ * </p>
+ * <p>
+ * Note: By default partitions are enabled.
+ * </p>
+ * @return this AtomicCounterBuilder
+ */
+ AtomicCounterBuilder withPartitionsDisabled();
+
+ /**
+ * Instantiates Metering service to gather usage and performance metrics.
+ * By default, usage data will be stored.
+ *
+ * @return this AtomicCounterBuilder
+ */
+ AtomicCounterBuilder withMeteringDisabled();
+
+ /**
+ * Builds a AtomicCounter based on the configuration options
+ * supplied to this builder.
+ *
+ * @return new AtomicCounter
+ * @throws java.lang.RuntimeException if a mandatory parameter is missing
+ */
+ AtomicCounter build();
+
+ /**
+ * Builds a AsyncAtomicCounter based on the configuration options
+ * supplied to this builder.
+ *
+ * @return new AsyncAtomicCounter
+ * @throws java.lang.RuntimeException if a mandatory parameter is missing
+ */
+ AsyncAtomicCounter buildAsyncCounter();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValue.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValue.java
new file mode 100644
index 00000000..dfa0fb3c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValue.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Distributed version of java.util.concurrent.atomic.AtomicReference.
+ *
+ * @param <V> value type
+ */
+public interface AtomicValue<V> {
+
+ /**
+ * Atomically sets the value to the given updated value if the current value is equal to the expected value.
+ * <p>
+ * IMPORTANT: Equality is based on the equality of the serialized byte[] representations.
+ * <p>
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. false return indicates that the actual value was not equal to the expected value.
+ */
+ boolean compareAndSet(V expect, V update);
+
+ /**
+ * Gets the current value.
+ * @return current value
+ */
+ V get();
+
+ /**
+ * Atomically sets to the given value and returns the old value.
+ * @param value the new value
+ * @return previous value
+ */
+ V getAndSet(V value);
+
+ /**
+ * Sets to the given value.
+ * @param value new value
+ */
+ void set(V value);
+
+ /**
+ * Registers the specified listener to be notified whenever the atomic value is updated.
+ *
+ * @param listener listener to notify about events
+ */
+ void addListener(AtomicValueEventListener<V> listener);
+
+ /**
+ * Unregisters the specified listener such that it will no longer
+ * receive atomic value update notifications.
+ *
+ * @param listener listener to unregister
+ */
+ void removeListener(AtomicValueEventListener<V> listener);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueBuilder.java
new file mode 100644
index 00000000..3478ce00
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueBuilder.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Builder for constructing new AtomicValue instances.
+ *
+ * @param <V> atomic value type
+ */
+public interface AtomicValueBuilder<V> {
+ /**
+ * Sets the name for the atomic value.
+ * <p>
+ * Each atomic value is identified by a unique name.
+ * </p>
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param name name of the atomic value
+ * @return this AtomicValueBuilder for method chaining
+ */
+ AtomicValueBuilder<V> withName(String name);
+
+ /**
+ * Sets a serializer that can be used to serialize the value.
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param serializer serializer
+ * @return this AtomicValueBuilder for method chaining
+ */
+ AtomicValueBuilder<V> withSerializer(Serializer serializer);
+
+ /**
+ * Creates this atomic value on the partition that spans the entire cluster.
+ * <p>
+ * When partitioning is disabled, the value state will be
+ * ephemeral and does not survive a full cluster restart.
+ * </p>
+ * <p>
+ * Note: By default partitions are enabled.
+ * </p>
+ * @return this AtomicValueBuilder for method chaining
+ */
+ AtomicValueBuilder<V> withPartitionsDisabled();
+
+ /**
+ * Instantiates Metering service to gather usage and performance metrics.
+ * By default, usage data will be stored.
+ *
+ * @return this AtomicValueBuilder for method chaining
+ */
+ AtomicValueBuilder<V> withMeteringDisabled();
+
+ /**
+ * Builds a AtomicValue based on the configuration options
+ * supplied to this builder.
+ *
+ * @return new AtomicValue
+ * @throws java.lang.RuntimeException if a mandatory parameter is missing
+ */
+ AtomicValue<V> build();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueEvent.java
new file mode 100644
index 00000000..1bce1365
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueEvent.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Representation of a AtomicValue update notification.
+ *
+ * @param <V> atomic value type
+ */
+public final class AtomicValueEvent<V> {
+
+ /**
+ * AtomicValueEvent type.
+ */
+ public enum Type {
+
+ /**
+ * Value was updated.
+ */
+ UPDATE,
+ }
+
+ private final String name;
+ private final Type type;
+ private final V value;
+
+ /**
+ * Creates a new event object.
+ *
+ * @param name AtomicValue name
+ * @param type the type of the event
+ * @param value the new value
+ */
+ public AtomicValueEvent(String name, Type type, V value) {
+ this.name = name;
+ this.type = type;
+ this.value = value;
+ }
+
+ /**
+ * Returns the AtomicValue name.
+ *
+ * @return name of atomic value
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the type of the event.
+ *
+ * @return the type of the event
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the new updated value.
+ *
+ * @return the value
+ */
+ public V value() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof AtomicValueEvent)) {
+ return false;
+ }
+
+ AtomicValueEvent that = (AtomicValueEvent) o;
+ return Objects.equals(this.name, that.name) &&
+ Objects.equals(this.type, that.type) &&
+ Objects.equals(this.value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, type, value);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("name", name)
+ .add("type", type)
+ .add("value", value)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueEventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueEventListener.java
new file mode 100644
index 00000000..b29d903b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/AtomicValueEventListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Listener to be notified about updates to a AtomicValue.
+ */
+public interface AtomicValueEventListener<V> {
+ /**
+ * Reacts to the specified event.
+ *
+ * @param event the event
+ */
+ void event(AtomicValueEvent<V> event);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMap.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMap.java
new file mode 100644
index 00000000..289da202
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMap.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * A distributed, strongly consistent key-value map.
+ * <p>
+ * This map offers strong read-after-update (where update == create/update/delete)
+ * consistency. All operations to the map are serialized and applied in a consistent
+ * manner.
+ * <p>
+ * The stronger consistency comes at the expense of availability in
+ * the event of a network partition. A network partition can be either due to
+ * a temporary disruption in network connectivity between participating nodes
+ * or due to a node being temporarily down.
+ * </p><p>
+ * All values stored in this map are versioned and the API supports optimistic
+ * concurrency by allowing conditional updates that take into consideration
+ * the version or value that was previously read.
+ * </p><p>
+ * This map does not allow null values. All methods can throw a ConsistentMapException
+ * (which extends RuntimeException) to indicate failures.
+ *
+ */
+public interface ConsistentMap<K, V> {
+
+ /**
+ * Returns the number of entries in the map.
+ *
+ * @return map size.
+ */
+ int size();
+
+ /**
+ * Returns true if the map is empty.
+ *
+ * @return true if map has no entries, false otherwise
+ */
+ boolean isEmpty();
+
+ /**
+ * Returns true if this map contains a mapping for the specified key.
+ *
+ * @param key key
+ * @return true if map contains key, false otherwise
+ */
+ boolean containsKey(K key);
+
+ /**
+ * Returns true if this map contains the specified value.
+ *
+ * @param value value
+ * @return true if map contains value, false otherwise.
+ */
+ boolean containsValue(V value);
+
+ /**
+ * Returns the value (and version) to which the specified key is mapped, or null if this
+ * map contains no mapping for the key.
+ *
+ * @param key the key whose associated value (and version) is to be returned
+ * @return the value (and version) to which the specified key is mapped, or null if
+ * this map contains no mapping for the key
+ */
+ Versioned<V> get(K key);
+
+ /**
+ * If the specified key is not already associated with a value (or is mapped to null),
+ * attempts to compute its value using the given mapping function and enters it into
+ * this map unless null.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param mappingFunction the function to compute a value
+ * @return the current (existing or computed) value associated with the specified key,
+ * or null if the computed value is null. Method throws {@code ConsistentMapException.ConcurrentModification}
+ * if a concurrent modification of map is detected
+ */
+ Versioned<V> computeIfAbsent(K key,
+ Function<? super K, ? extends V> mappingFunction);
+
+ /**
+ * Attempts to compute a mapping for the specified key and its current mapped value (or
+ * null if there is no current mapping).
+ * If the computed value is null, the current mapping will be removed from the map.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param remappingFunction the function to compute a value
+ * @return the new value associated with the specified key, or null if none.
+ * This method throws {@code ConsistentMapException.ConcurrentModification}
+ * if a concurrent modification of map is detected
+ */
+ Versioned<V> compute(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction);
+
+ /**
+ * If the value for the specified key is present and non-null, attempts to compute a new
+ * mapping given the key and its current mapped value.
+ * If the computed value is null, the current mapping will be removed from the map.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param remappingFunction the function to compute a value
+ * @return the new value associated with the specified key, or null if none.
+ * This method throws {@code ConsistentMapException.ConcurrentModification}
+ * if a concurrent modification of map is detected
+ */
+ Versioned<V> computeIfPresent(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction);
+
+ /**
+ * If the value for the specified key satisfies a condition, attempts to compute a new
+ * mapping given the key and its current mapped value.
+ * If the computed value is null, the current mapping will be removed from the map.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param condition condition that should evaluate to true for the computation to proceed
+ * @param remappingFunction the function to compute a value
+ * @return the new value associated with the specified key, or the old value if condition evaluates to false.
+ * This method throws {@code ConsistentMapException.ConcurrentModification} if a concurrent
+ * modification of map is detected
+ */
+ Versioned<V> computeIf(K key,
+ Predicate<? super V> condition,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction);
+
+ /**
+ * Associates the specified value with the specified key in this map (optional operation).
+ * If the map previously contained a mapping for the key, the old value is replaced by the
+ * specified value.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value (and version) associated with key, or null if there was
+ * no mapping for key.
+ */
+ Versioned<V> put(K key, V value);
+
+ /**
+ * Associates the specified value with the specified key in this map (optional operation).
+ * If the map previously contained a mapping for the key, the old value is replaced by the
+ * specified value.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return new value.
+ */
+ Versioned<V> putAndGet(K key, V value);
+
+ /**
+ * Removes the mapping for a key from this map if it is present (optional operation).
+ *
+ * @param key key whose value is to be removed from the map
+ * @return the value (and version) to which this map previously associated the key,
+ * or null if the map contained no mapping for the key.
+ */
+ Versioned<V> remove(K key);
+
+ /**
+ * Removes all of the mappings from this map (optional operation).
+ * The map will be empty after this call returns.
+ */
+ void clear();
+
+ /**
+ * Returns a Set view of the keys contained in this map.
+ * This method differs from the behavior of java.util.Map.keySet() in that
+ * what is returned is a unmodifiable snapshot view of the keys in the ConsistentMap.
+ * Attempts to modify the returned set, whether direct or via its iterator,
+ * result in an UnsupportedOperationException.
+ *
+ * @return a set of the keys contained in this map
+ */
+ Set<K> keySet();
+
+ /**
+ * Returns the collection of values (and associated versions) contained in this map.
+ * This method differs from the behavior of java.util.Map.values() in that
+ * what is returned is a unmodifiable snapshot view of the values in the ConsistentMap.
+ * Attempts to modify the returned collection, whether direct or via its iterator,
+ * result in an UnsupportedOperationException.
+ *
+ * @return a collection of the values (and associated versions) contained in this map
+ */
+ Collection<Versioned<V>> values();
+
+ /**
+ * Returns the set of entries contained in this map.
+ * This method differs from the behavior of java.util.Map.entrySet() in that
+ * what is returned is a unmodifiable snapshot view of the entries in the ConsistentMap.
+ * Attempts to modify the returned set, whether direct or via its iterator,
+ * result in an UnsupportedOperationException.
+ *
+ * @return set of entries contained in this map.
+ */
+ Set<Entry<K, Versioned<V>>> entrySet();
+
+ /**
+ * If the specified key is not already associated with a value
+ * associates it with the given value and returns null, else returns the current value.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with the specified key or null
+ * if key does not already mapped to a value.
+ */
+ Versioned<V> putIfAbsent(K key, V value);
+
+ /**
+ * Removes the entry for the specified key only if it is currently
+ * mapped to the specified value.
+ *
+ * @param key key with which the specified value is associated
+ * @param value value expected to be associated with the specified key
+ * @return true if the value was removed
+ */
+ boolean remove(K key, V value);
+
+ /**
+ * Removes the entry for the specified key only if its current
+ * version in the map is equal to the specified version.
+ *
+ * @param key key with which the specified version is associated
+ * @param version version expected to be associated with the specified key
+ * @return true if the value was removed
+ */
+ boolean remove(K key, long version);
+
+ /**
+ * Replaces the entry for the specified key only if currently mapped
+ * to the specified value.
+ *
+ * @param key key with which the specified value is associated
+ * @param oldValue value expected to be associated with the specified key
+ * @param newValue value to be associated with the specified key
+ * @return true if the value was replaced
+ */
+ boolean replace(K key, V oldValue, V newValue);
+
+ /**
+ * Replaces the entry for the specified key only if it is currently mapped to the
+ * specified version.
+ *
+ * @param key key key with which the specified value is associated
+ * @param oldVersion version expected to be associated with the specified key
+ * @param newValue value to be associated with the specified key
+ * @return true if the value was replaced
+ */
+ boolean replace(K key, long oldVersion, V newValue);
+
+ /**
+ * Registers the specified listener to be notified whenever the map is updated.
+ *
+ * @param listener listener to notify about map events
+ */
+ void addListener(MapEventListener<K, V> listener);
+
+ /**
+ * Unregisters the specified listener such that it will no longer
+ * receive map change notifications.
+ *
+ * @param listener listener to unregister
+ */
+ void removeListener(MapEventListener<K, V> listener);
+
+ /**
+ * Returns a java.util.Map instance backed by this ConsistentMap.
+ * @return java.util.Map
+ */
+ Map<K, V> asJavaMap();
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMapBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMapBuilder.java
new file mode 100644
index 00000000..847adaf6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMapBuilder.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import org.onosproject.core.ApplicationId;
+
+/**
+ * Builder for consistent maps.
+ *
+ * @param <K> type for map key
+ * @param <V> type for map value
+ */
+public interface ConsistentMapBuilder<K, V> {
+
+ /**
+ * Sets the name of the map.
+ * <p>
+ * Each consistent map is identified by a unique map name.
+ * </p>
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param name name of the consistent map
+ * @return this ConsistentMapBuilder
+ */
+ ConsistentMapBuilder<K, V> withName(String name);
+
+ /**
+ * Sets the owner applicationId for the map.
+ * <p>
+ * Note: If {@code purgeOnUninstall} option is enabled, applicationId
+ * must be specified.
+ * </p>
+ *
+ * @param id applicationId owning the consistent map
+ * @return this ConsistentMapBuilder
+ */
+ ConsistentMapBuilder<K, V> withApplicationId(ApplicationId id);
+
+ /**
+ * Sets a serializer that can be used to serialize
+ * both the keys and values inserted into the map. The serializer
+ * builder should be pre-populated with any classes that will be
+ * put into the map.
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param serializer serializer
+ * @return this ConsistentMapBuilder
+ */
+ ConsistentMapBuilder<K, V> withSerializer(Serializer serializer);
+
+ /**
+ * Disables distribution of map entries across multiple database partitions.
+ * <p>
+ * When partitioning is disabled, the returned map will have a single partition
+ * that spans the entire cluster. Furthermore, the changes made to the map are
+ * ephemeral and do not survive a full cluster restart.
+ * </p>
+ * <p>
+ * Disabling partitions is more appropriate when the returned map is used for
+ * coordination activities such as leader election and not for long term data persistence.
+ * </p>
+ * <p>
+ * Note: By default partitions are enabled and entries in the map are durable.
+ * </p>
+ * @return this ConsistentMapBuilder
+ */
+ ConsistentMapBuilder<K, V> withPartitionsDisabled();
+
+ /**
+ * Disables map updates.
+ * <p>
+ * Attempt to update the built map will throw {@code UnsupportedOperationException}.
+ *
+ * @return this ConsistentMapBuilder
+ */
+ ConsistentMapBuilder<K, V> withUpdatesDisabled();
+
+ /**
+ * Purges map contents when the application owning the map is uninstalled.
+ * <p>
+ * When this option is enabled, the caller must provide a applicationId via
+ * the {@code withAppliationId} builder method.
+ * <p>
+ * By default map entries will NOT be purged when owning application is uninstalled.
+ *
+ * @return this ConsistentMapBuilder
+ */
+ ConsistentMapBuilder<K, V> withPurgeOnUninstall();
+
+ /**
+ * Instantiates Metering service to gather usage and performance metrics.
+ * By default, usage data will be stored.
+ *
+ * @return this ConsistentMapBuilder
+ */
+ ConsistentMapBuilder<K, V> withMeteringDisabled();
+
+ /**
+ * Provides weak consistency for map gets.
+ * <p>
+ * While this can lead to improved read performance, it can also make the behavior
+ * heard to reason. Only turn this on if you know what you are doing. By default
+ * reads are strongly consistent.
+ *
+ * @return this ConsistentMapBuilder
+ */
+ ConsistentMapBuilder<K, V> withRelaxedReadConsistency();
+
+ /**
+ * Builds an consistent map based on the configuration options
+ * supplied to this builder.
+ *
+ * @return new consistent map
+ * @throws java.lang.RuntimeException if a mandatory parameter is missing
+ */
+ ConsistentMap<K, V> build();
+
+ /**
+ * Builds an async consistent map based on the configuration options
+ * supplied to this builder.
+ *
+ * @return new async consistent map
+ * @throws java.lang.RuntimeException if a mandatory parameter is missing
+ */
+ AsyncConsistentMap<K, V> buildAsyncMap();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMapException.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMapException.java
new file mode 100644
index 00000000..94ed649f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/ConsistentMapException.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+/**
+ * Top level exception for ConsistentMap failures.
+ */
+@SuppressWarnings("serial")
+public class ConsistentMapException extends StorageException {
+ public ConsistentMapException() {
+ }
+
+ public ConsistentMapException(Throwable t) {
+ super(t);
+ }
+
+ /**
+ * ConsistentMap operation timeout.
+ */
+ public static class Timeout extends ConsistentMapException {
+ }
+
+ /**
+ * ConsistentMap update conflicts with an in flight transaction.
+ */
+ public static class ConcurrentModification extends ConsistentMapException {
+ }
+
+ /**
+ * ConsistentMap operation interrupted.
+ */
+ public static class Interrupted extends ConsistentMapException {
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DatabaseUpdate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DatabaseUpdate.java
new file mode 100644
index 00000000..8cac5968
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DatabaseUpdate.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Database update operation.
+ *
+ */
+public final class DatabaseUpdate {
+
+ /**
+ * Type of database update operation.
+ */
+ public static enum Type {
+ /**
+ * Insert/Update entry without any checks.
+ */
+ PUT,
+ /**
+ * Insert an entry iff there is no existing entry for that key.
+ */
+ PUT_IF_ABSENT,
+
+ /**
+ * Update entry if the current version matches specified version.
+ */
+ PUT_IF_VERSION_MATCH,
+
+ /**
+ * Update entry if the current value matches specified value.
+ */
+ PUT_IF_VALUE_MATCH,
+
+ /**
+ * Remove entry without any checks.
+ */
+ REMOVE,
+
+ /**
+ * Remove entry if the current version matches specified version.
+ */
+ REMOVE_IF_VERSION_MATCH,
+
+ /**
+ * Remove entry if the current value matches specified value.
+ */
+ REMOVE_IF_VALUE_MATCH,
+ }
+
+ private Type type;
+ private String mapName;
+ private String key;
+ private byte[] value;
+ private byte[] currentValue;
+ private long currentVersion = -1;
+
+ /**
+ * Returns the type of update operation.
+ * @return type of update.
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the name of map being updated.
+ * @return map name.
+ */
+ public String mapName() {
+ return mapName;
+ }
+
+ /**
+ * Returns the item key being updated.
+ * @return item key
+ */
+ public String key() {
+ return key;
+ }
+
+ /**
+ * Returns the new value.
+ * @return item's target value.
+ */
+ public byte[] value() {
+ return value;
+ }
+
+ /**
+ * Returns the expected current value in the database value for the key.
+ * @return current value in database.
+ */
+ public byte[] currentValue() {
+ return currentValue;
+ }
+
+ /**
+ * Returns the expected current version in the database for the key.
+ * @return expected version.
+ */
+ public long currentVersion() {
+ return currentVersion;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("type", type)
+ .add("mapName", mapName)
+ .add("key", key)
+ .add("value", value)
+ .add("currentValue", currentValue)
+ .add("currentVersion", currentVersion)
+ .toString();
+ }
+
+ /**
+ * Creates a new builder instance.
+ *
+ * @return builder.
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * DatabaseUpdate builder.
+ *
+ */
+ public static final class Builder {
+
+ private DatabaseUpdate update = new DatabaseUpdate();
+
+ public DatabaseUpdate build() {
+ validateInputs();
+ return update;
+ }
+
+ public Builder withType(Type type) {
+ update.type = checkNotNull(type, "type cannot be null");
+ return this;
+ }
+
+ public Builder withMapName(String mapName) {
+ update.mapName = checkNotNull(mapName, "mapName cannot be null");
+ return this;
+ }
+
+ public Builder withKey(String key) {
+ update.key = checkNotNull(key, "key cannot be null");
+ return this;
+ }
+
+ public Builder withCurrentValue(byte[] value) {
+ update.currentValue = checkNotNull(value, "currentValue cannot be null");
+ return this;
+ }
+
+ public Builder withValue(byte[] value) {
+ update.value = checkNotNull(value, "value cannot be null");
+ return this;
+ }
+
+ public Builder withCurrentVersion(long version) {
+ checkArgument(version >= 0, "version cannot be negative");
+ update.currentVersion = version;
+ return this;
+ }
+
+ private void validateInputs() {
+ checkNotNull(update.type, "type must be specified");
+ checkNotNull(update.mapName, "map name must be specified");
+ checkNotNull(update.key, "key must be specified");
+ switch (update.type) {
+ case PUT:
+ case PUT_IF_ABSENT:
+ checkNotNull(update.value, "value must be specified.");
+ break;
+ case PUT_IF_VERSION_MATCH:
+ checkNotNull(update.value, "value must be specified.");
+ checkState(update.currentVersion >= 0, "current version must be specified");
+ break;
+ case PUT_IF_VALUE_MATCH:
+ checkNotNull(update.value, "value must be specified.");
+ checkNotNull(update.currentValue, "currentValue must be specified.");
+ break;
+ case REMOVE:
+ break;
+ case REMOVE_IF_VERSION_MATCH:
+ checkState(update.currentVersion >= 0, "current version must be specified");
+ break;
+ case REMOVE_IF_VALUE_MATCH:
+ checkNotNull(update.currentValue, "currentValue must be specified.");
+ break;
+ default:
+ throw new IllegalStateException("Unknown operation type");
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedQueue.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedQueue.java
new file mode 100644
index 00000000..cc0b00d3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedQueue.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * A distributed collection designed for holding elements prior to processing.
+ * A queue provides insertion, extraction and inspection operations. The extraction operation
+ * is designed to be non-blocking.
+ *
+ * @param <E> queue entry type
+ */
+public interface DistributedQueue<E> {
+
+ /**
+ * Returns total number of entries in the queue.
+ * @return queue size
+ */
+ long size();
+
+ /**
+ * Returns true if queue has elements in it.
+ * @return true is queue has elements, false otherwise
+ */
+ default boolean isEmpty() {
+ return size() == 0;
+ }
+
+ /**
+ * Inserts an entry into the queue.
+ * @param entry entry to insert
+ */
+ void push(E entry);
+
+ /**
+ * If the queue is non-empty, an entry will be removed from the queue and the returned future
+ * will be immediately completed with it. If queue is empty when this call is made, the returned
+ * future will be eventually completed when an entry is added to the queue.
+ * @return queue entry
+ */
+ CompletableFuture<E> pop();
+
+ /**
+ * Returns an entry from the queue without removing it. If the queue is empty returns null.
+ * @return queue entry or null if queue is empty
+ */
+ E peek();
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedQueueBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedQueueBuilder.java
new file mode 100644
index 00000000..646dc28c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedQueueBuilder.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Builder for distributed queue.
+ *
+ * @param <E> type queue elements.
+ */
+public interface DistributedQueueBuilder<E> {
+
+ /**
+ * Sets the name of the queue.
+ * <p>
+ * Each queue is identified by a unique name.
+ * </p>
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param name name of the queue
+ * @return this DistributedQueueBuilder for method chaining
+ */
+ DistributedQueueBuilder<E> withName(String name);
+
+ /**
+ * Sets a serializer that can be used to serialize
+ * the elements pushed into the queue. The serializer
+ * builder should be pre-populated with any classes that will be
+ * put into the queue.
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param serializer serializer
+ * @return this DistributedQueueBuilder for method chaining
+ */
+ DistributedQueueBuilder<E> withSerializer(Serializer serializer);
+
+ /**
+ *
+ *
+ * @return this DistributedQueueBuilder for method chaining
+ */
+ DistributedQueueBuilder<E> withMeteringDisabled();
+
+
+ /**
+ * Disables persistence of queues entries.
+ * <p>
+ * When persistence is disabled, a full cluster restart will wipe out all
+ * queue entries.
+ * </p>
+ * @return this DistributedQueueBuilder for method chaining
+ */
+ DistributedQueueBuilder<E> withPersistenceDisabled();
+
+ /**
+ * Builds a queue based on the configuration options
+ * supplied to this builder.
+ *
+ * @return new distributed queue
+ * @throws java.lang.RuntimeException if a mandatory parameter is missing
+ */
+ DistributedQueue<E> build();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedSet.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedSet.java
new file mode 100644
index 00000000..460206ec
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedSet.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.Set;
+
+/**
+ * A distributed collection designed for holding unique elements.
+ *
+ * @param <E> set entry type
+ */
+public interface DistributedSet<E> extends Set<E> {
+
+ /**
+ * Registers the specified listener to be notified whenever
+ * the set is updated.
+ *
+ * @param listener listener to notify about set update events
+ */
+ void addListener(SetEventListener<E> listener);
+
+ /**
+ * Unregisters the specified listener.
+ *
+ * @param listener listener to unregister.
+ */
+ void removeListener(SetEventListener<E> listener);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedSetBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedSetBuilder.java
new file mode 100644
index 00000000..f5a44c93
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/DistributedSetBuilder.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import org.onosproject.core.ApplicationId;
+
+/**
+ * Builder for distributed set.
+ *
+ * @param <E> type set elements.
+ */
+public interface DistributedSetBuilder<E> {
+
+ /**
+ * Sets the name of the set.
+ * <p>
+ * Each set is identified by a unique name.
+ * </p>
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param name name of the set
+ * @return this DistributedSetBuilder
+ */
+ DistributedSetBuilder<E> withName(String name);
+
+ /**
+ * Sets the owner applicationId for the set.
+ * <p>
+ * Note: If {@code purgeOnUninstall} option is enabled, applicationId
+ * must be specified.
+ * </p>
+ *
+ * @param id applicationId owning the set
+ * @return this DistributedSetBuilder
+ */
+ DistributedSetBuilder<E> withApplicationId(ApplicationId id);
+
+ /**
+ * Sets a serializer that can be used to serialize
+ * the elements add to the set. The serializer
+ * builder should be pre-populated with any classes that will be
+ * put into the set.
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param serializer serializer
+ * @return this DistributedSetBuilder
+ */
+ DistributedSetBuilder<E> withSerializer(Serializer serializer);
+
+ /**
+ * Disables set updates.
+ * <p>
+ * Attempt to update the built set will throw {@code UnsupportedOperationException}.
+ *
+ * @return this DistributedSetBuilder
+ */
+ DistributedSetBuilder<E> withUpdatesDisabled();
+
+ /**
+ * Provides weak consistency for set reads.
+ * <p>
+ * While this can lead to improved read performance, it can also make the behavior
+ * heard to reason. Only turn this on if you know what you are doing. By default
+ * reads are strongly consistent.
+ *
+ * @return this DistributedSetBuilder
+ */
+ DistributedSetBuilder<E> withRelaxedReadConsistency();
+
+ /**
+ * Disables distribution of set entries across multiple database partitions.
+ * <p>
+ * When partitioning is disabled, the returned set will have a single partition
+ * that spans the entire cluster. Furthermore, the changes made to the set are
+ * ephemeral and do not survive a full cluster restart.
+ * </p>
+ * <p>
+ * Disabling partitions is more appropriate when the returned set is used for
+ * simple coordination activities and not for long term data persistence.
+ * </p>
+ * <p>
+ * Note: By default partitions are enabled and entries in the set are durable.
+ * </p>
+ * @return this DistributedSetBuilder
+ */
+ DistributedSetBuilder<E> withPartitionsDisabled();
+
+ /**
+ * Instantiate Metrics service to gather usage and performance metrics.
+ * By default usage information is enabled
+ * @return this DistributedSetBuilder
+ */
+ DistributedSetBuilder<E> withMeteringDisabled();
+
+ /**
+ * Purges set contents when the application owning the set is uninstalled.
+ * <p>
+ * When this option is enabled, the caller must provide a applicationId via
+ * the {@code withAppliationId} builder method.
+ * <p>
+ * By default set contents will NOT be purged when owning application is uninstalled.
+ *
+ * @return this DistributedSetBuilder
+ */
+ DistributedSetBuilder<E> withPurgeOnUninstall();
+
+ /**
+ * Builds an set based on the configuration options
+ * supplied to this builder.
+ *
+ * @return new set
+ * @throws java.lang.RuntimeException if a mandatory parameter is missing
+ */
+ DistributedSet<E> build();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMap.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMap.java
new file mode 100644
index 00000000..06395b8e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMap.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+/**
+ * A distributed, eventually consistent map.
+ * <p>
+ * This map does not offer read after writes consistency. Operations are
+ * serialized via the timestamps issued by the clock service. If two updates
+ * are in conflict, the update with the more recent timestamp will endure.
+ * </p><p>
+ * The interface is mostly similar to {@link java.util.Map} with some minor
+ * semantic changes and the addition of a listener framework (because the map
+ * can be mutated by clients on other instances, not only through the local Java
+ * API).
+ * </p><p>
+ * Clients are expected to register an
+ * {@link EventuallyConsistentMapListener} if they
+ * are interested in receiving notifications of update to the map.
+ * </p><p>
+ * Null values are not allowed in this map.
+ * </p>
+ */
+public interface EventuallyConsistentMap<K, V> {
+
+ /**
+ * Returns the number of key-value mappings in this map.
+ *
+ * @return number of key-value mappings
+ */
+ int size();
+
+ /**
+ * Returns true if this map is empty.
+ *
+ * @return true if this map is empty, otherwise false
+ */
+ boolean isEmpty();
+
+ /**
+ * Returns true if the map contains a mapping for the specified key.
+ *
+ * @param key the key to check if this map contains
+ * @return true if this map has a mapping for the key, otherwise false
+ */
+ boolean containsKey(K key);
+
+ /**
+ * Returns true if the map contains a mapping from any key to the specified
+ * value.
+ *
+ * @param value the value to check if this map has a mapping for
+ * @return true if this map has a mapping to this value, otherwise false
+ */
+ boolean containsValue(V value);
+
+ /**
+ * Returns the value mapped to the specified key.
+ *
+ * @param key the key to look up in this map
+ * @return the value mapped to the key, or null if no mapping is found
+ */
+ V get(K key);
+
+ /**
+ * Associates the specified value to the specified key in this map.
+ * <p>
+ * Note: this differs from the specification of {@link java.util.Map}
+ * because it does not return the previous value associated with the key.
+ * Clients are expected to register an
+ * {@link EventuallyConsistentMapListener} if
+ * they are interested in receiving notification of updates to the map.
+ * </p><p>
+ * Null values are not allowed in the map.
+ * </p>
+ *
+ * @param key the key to add a mapping for in this map
+ * @param value the value to associate with the key in this map
+ */
+ void put(K key, V value);
+
+ /**
+ * Removes the mapping associated with the specified key from the map.
+ * <p>
+ * Clients are expected to register an {@link EventuallyConsistentMapListener} if
+ * they are interested in receiving notification of updates to the map.
+ * </p>
+ *
+ * @param key the key to remove the mapping for
+ * @return previous value associated with key, or null if there was no mapping for key.
+ */
+ V remove(K key);
+
+ /**
+ * Removes the given key-value mapping from the map, if it exists.
+ * <p>
+ * This actually means remove any values up to and including the timestamp
+ * given by the map's timestampProvider.
+ * Any mappings that produce an earlier timestamp than this given key-value
+ * pair will be removed, and any mappings that produce a later timestamp
+ * will supersede this remove.
+ * </p><p>
+ * Note: this differs from the specification of {@link java.util.Map}
+ * because it does not return a boolean indication whether a value was removed.
+ * Clients are expected to register an
+ * {@link EventuallyConsistentMapListener} if
+ * they are interested in receiving notification of updates to the map.
+ * </p>
+ *
+ * @param key the key to remove the mapping for
+ * @param value the value mapped to the key
+ */
+ void remove(K key, V value);
+
+ /**
+ * Attempts to compute a mapping for the specified key and its current mapped
+ * value (or null if there is no current mapping).
+ * <p>
+ * If the function returns null, the mapping is removed (or remains absent if initially absent).
+ * @param key map key
+ * @param recomputeFunction function to recompute a new value
+ * @return new value
+ */
+ V compute(K key, BiFunction<K, V, V> recomputeFunction);
+
+ /**
+ * Adds mappings for all key-value pairs in the specified map to this map.
+ * <p>
+ * This will be more efficient in communication than calling individual put
+ * operations.
+ * </p>
+ *
+ * @param m a map of values to add to this map
+ */
+ void putAll(Map<? extends K, ? extends V> m);
+
+ /**
+ * Removes all mappings from this map.
+ */
+ void clear();
+
+ /**
+ * Returns a set of the keys in this map. Changes to the set are not
+ * reflected back to the map.
+ *
+ * @return set of keys in the map
+ */
+ Set<K> keySet();
+
+ /**
+ * Returns a collections of values in this map. Changes to the collection
+ * are not reflected back to the map.
+ *
+ * @return collection of values in the map
+ */
+ Collection<V> values();
+
+ /**
+ * Returns a set of mappings contained in this map. Changes to the set are
+ * not reflected back to the map.
+ *
+ * @return set of key-value mappings in this map
+ */
+ Set<Map.Entry<K, V>> entrySet();
+
+ /**
+ * Adds the specified listener to the map which will be notified whenever
+ * the mappings in the map are changed.
+ *
+ * @param listener listener to register for events
+ */
+ void addListener(EventuallyConsistentMapListener<K, V> listener);
+
+ /**
+ * Removes the specified listener from the map such that it will no longer
+ * receive change notifications.
+ *
+ * @param listener listener to deregister for events
+ */
+ void removeListener(EventuallyConsistentMapListener<K, V> listener);
+
+ /**
+ * Shuts down the map and breaks communication between different instances.
+ * This allows the map objects to be cleaned up and garbage collected.
+ * Calls to any methods on the map subsequent to calling destroy() will
+ * throw a {@link java.lang.RuntimeException}.
+ */
+ void destroy();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapBuilder.java
new file mode 100644
index 00000000..9471321c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapBuilder.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.store.Timestamp;
+
+import java.util.Collection;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiFunction;
+
+/**
+ * Builder for eventually consistent maps.
+ *
+ * @param <K> type for map keys
+ * @param <V> type for map values
+ */
+public interface EventuallyConsistentMapBuilder<K, V> {
+
+ /**
+ * Sets the name of the map.
+ * <p>
+ * Each map is identified by a string map name. EventuallyConsistentMapImpl
+ * objects in different JVMs that use the same map name will form a
+ * distributed map across JVMs (provided the cluster service is aware of
+ * both nodes).
+ * </p>
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param name name of the map
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withName(String name);
+
+ /**
+ * Sets a serializer builder that can be used to create a serializer that
+ * can serialize both the keys and values put into the map. The serializer
+ * builder should be pre-populated with any classes that will be put into
+ * the map.
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param serializerBuilder serializer builder
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withSerializer(
+ KryoNamespace.Builder serializerBuilder);
+
+ /**
+ * Sets the function to use for generating timestamps for map updates.
+ * <p>
+ * The client must provide an {@code BiFunction<K, V, Timestamp>}
+ * which can generate timestamps for a given key. The function is free
+ * to generate timestamps however it wishes, however these timestamps will
+ * be used to serialize updates to the map so they must be strict enough
+ * to ensure updates are properly ordered for the use case (i.e. in some
+ * cases wallclock time will suffice, whereas in other cases logical time
+ * will be necessary).
+ * </p>
+ * <p>
+ * Note: This is a mandatory parameter.
+ * </p>
+ *
+ * @param timestampProvider provides a new timestamp
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withTimestampProvider(
+ BiFunction<K, V, Timestamp> timestampProvider);
+
+ /**
+ * Sets the executor to use for processing events coming in from peers.
+ *
+ * @param executor event executor
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withEventExecutor(
+ ExecutorService executor);
+
+ /**
+ * Sets the executor to use for sending events to peers.
+ *
+ * @param executor event executor
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withCommunicationExecutor(
+ ExecutorService executor);
+
+ /**
+ * Sets the executor to use for background anti-entropy tasks.
+ *
+ * @param executor event executor
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withBackgroundExecutor(
+ ScheduledExecutorService executor);
+
+ /**
+ * Sets a function that can determine which peers to replicate updates to.
+ * <p>
+ * The default function replicates to all nodes.
+ * </p>
+ *
+ * @param peerUpdateFunction function that takes a K, V input and returns
+ * a collection of NodeIds to replicate the event
+ * to
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withPeerUpdateFunction(
+ BiFunction<K, V, Collection<NodeId>> peerUpdateFunction);
+
+ /**
+ * Prevents this map from writing tombstones of items that have been
+ * removed. This may result in zombie items reappearing after they have
+ * been removed.
+ * <p>
+ * The default behavior is tombstones are enabled.
+ * </p>
+ *
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withTombstonesDisabled();
+
+ /**
+ * Configures how often to run the anti-entropy background task.
+ * <p>
+ * The default anti-entropy period is 5 seconds.
+ * </p>
+ *
+ * @param period anti-entropy period
+ * @param unit time unit for the period
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withAntiEntropyPeriod(
+ long period, TimeUnit unit);
+
+ /**
+ * Configure anti-entropy to converge faster at the cost of doing more work
+ * for each anti-entropy cycle. Suited to maps with low update rate where
+ * convergence time is more important than throughput.
+ * <p>
+ * The default behavior is to do less anti-entropy work at the cost of
+ * slower convergence.
+ * </p>
+ *
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withFasterConvergence();
+
+ /**
+ * Configure the map to persist data to disk.
+ * <p>
+ * The default behavior is no persistence
+ * </p>
+ *
+ * @return this EventuallyConsistentMapBuilder
+ */
+ EventuallyConsistentMapBuilder<K, V> withPersistence();
+
+ /**
+ * Builds an eventually consistent map based on the configuration options
+ * supplied to this builder.
+ *
+ * @return new eventually consistent map
+ * @throws java.lang.RuntimeException if a mandatory parameter is missing
+ */
+ EventuallyConsistentMap<K, V> build();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapEvent.java
new file mode 100644
index 00000000..5814534e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapEvent.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Representation of a EventuallyConsistentMap update notification.
+ */
+public final class EventuallyConsistentMapEvent<K, V> {
+
+ public enum Type {
+ /**
+ * Entry added to map or existing entry updated.
+ */
+ PUT,
+
+ /**
+ * Entry removed from map.
+ */
+ REMOVE
+ }
+
+ private final String name;
+ private final Type type;
+ private final K key;
+ private final V value;
+
+ /**
+ * Creates a new event object.
+ *
+ * @param name map name
+ * @param type the type of the event
+ * @param key the key the event concerns
+ * @param value the value mapped to the key
+ */
+ public EventuallyConsistentMapEvent(String name, Type type, K key, V value) {
+ this.name = name;
+ this.type = type;
+ this.key = key;
+ this.value = value;
+ }
+
+ /**
+ * Returns the map name.
+ *
+ * @return name of map
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the type of the event.
+ *
+ * @return the type of the event
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the key this event concerns.
+ *
+ * @return the key
+ */
+ public K key() {
+ return key;
+ }
+
+ /**
+ * Returns the value associated with this event. If type is REMOVE,
+ * this is the value that was removed. If type is PUT, this is
+ * the new value.
+ *
+ * @return the value
+ */
+ public V value() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof EventuallyConsistentMapEvent)) {
+ return false;
+ }
+
+ EventuallyConsistentMapEvent that = (EventuallyConsistentMapEvent) o;
+ return Objects.equals(this.type, that.type) &&
+ Objects.equals(this.key, that.key) &&
+ Objects.equals(this.value, that.value) &&
+ Objects.equals(this.name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, key, value);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("name", name)
+ .add("type", type)
+ .add("key", key)
+ .add("value", value)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapListener.java
new file mode 100644
index 00000000..b2399a48
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Listener to be notified about updates to a EventuallyConsistentMap.
+ */
+public interface EventuallyConsistentMapListener<K, V> {
+
+ /**
+ * Reacts to the specified event.
+ *
+ * @param event the event
+ */
+ void event(EventuallyConsistentMapEvent<K, V> event);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/LogicalClockService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/LogicalClockService.java
new file mode 100644
index 00000000..7592b126
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/LogicalClockService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import org.onosproject.store.Timestamp;
+
+/**
+ * Service that issues logical timestamps.
+ * <p>
+ * Logical timestamps are useful for establishing a total ordering of
+ * arbitrary cluster wide events without relying on a fully synchronized
+ * system clock (wall clock)
+ */
+public interface LogicalClockService {
+
+ /**
+ * Generates a new logical timestamp.
+ *
+ * @return timestamp
+ */
+ Timestamp getTimestamp();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapEvent.java
new file mode 100644
index 00000000..6e671351
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapEvent.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Representation of a ConsistentMap update notification.
+ *
+ * @param <K> key type
+ * @param <V> value type
+ */
+public class MapEvent<K, V> {
+
+ /**
+ * MapEvent type.
+ */
+ public enum Type {
+ /**
+ * Entry inserted into the map.
+ */
+ INSERT,
+
+ /**
+ * Existing map entry updated.
+ */
+ UPDATE,
+
+ /**
+ * Entry removed from map.
+ */
+ REMOVE
+ }
+
+ private final String name;
+ private final Type type;
+ private final K key;
+ private final Versioned<V> value;
+
+ /**
+ * Creates a new event object.
+ *
+ * @param name map name
+ * @param type type of event
+ * @param key key the event concerns
+ * @param value value key is mapped to
+ */
+ public MapEvent(String name, Type type, K key, Versioned<V> value) {
+ this.name = name;
+ this.type = type;
+ this.key = key;
+ this.value = value;
+ }
+
+ /**
+ * Returns the map name.
+ *
+ * @return name of map
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the type of the event.
+ *
+ * @return the type of event
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the key this event concerns.
+ *
+ * @return the key
+ */
+ public K key() {
+ return key;
+ }
+
+ /**
+ * Returns the value associated with this event. If type is REMOVE,
+ * this is the value that was removed. If type is INSERT/UPDATE, this is
+ * the new value.
+ *
+ * @return the value
+ */
+ public Versioned<V> value() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof MapEvent)) {
+ return false;
+ }
+
+ MapEvent<K, V> that = (MapEvent) o;
+ return Objects.equals(this.name, that.name) &&
+ Objects.equals(this.type, that.type) &&
+ Objects.equals(this.key, that.key) &&
+ Objects.equals(this.value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, type, key, value);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("name", name)
+ .add("type", type)
+ .add("key", key)
+ .add("value", value)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapEventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapEventListener.java
new file mode 100644
index 00000000..359f4653
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapEventListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Listener to be notified about updates to a ConsistentMap.
+ */
+public interface MapEventListener<K, V> {
+ /**
+ * Reacts to the specified event.
+ *
+ * @param event the event
+ */
+ void event(MapEvent<K, V> event);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapInfo.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapInfo.java
new file mode 100644
index 00000000..5db17049
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MapInfo.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Metadata information for a consistent map.
+ */
+public class MapInfo {
+ private final String name;
+ private final int size;
+
+ public MapInfo(String name, int size) {
+ this.name = name;
+ this.size = size;
+ }
+
+ /**
+ * Returns the name of the map.
+ *
+ * @return map name
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the number of entries in the map.
+ *
+ * @return map size
+ */
+ public int size() {
+ return size;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MultiValuedTimestamp.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MultiValuedTimestamp.java
new file mode 100644
index 00000000..e068b8e9
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/MultiValuedTimestamp.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ComparisonChain;
+import org.onosproject.store.Timestamp;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A logical timestamp that derives its value from two input values. The first
+ * value always takes precedence over the second value when comparing timestamps.
+ */
+public class MultiValuedTimestamp<T extends Comparable<T>, U extends Comparable<U>>
+ implements Timestamp {
+
+ private final T value1;
+ private final U value2;
+
+ /**
+ * Creates a new timestamp based on two values. The first value has higher
+ * precedence than the second when comparing timestamps.
+ *
+ * @param value1 first value
+ * @param value2 second value
+ */
+ public MultiValuedTimestamp(T value1, U value2) {
+ this.value1 = checkNotNull(value1);
+ this.value2 = checkNotNull(value2);
+ }
+
+ @Override
+ public int compareTo(Timestamp o) {
+ checkArgument(o instanceof MultiValuedTimestamp,
+ "Must be MultiValuedTimestamp", o);
+ MultiValuedTimestamp that = (MultiValuedTimestamp) o;
+
+ return ComparisonChain.start()
+ .compare(this.value1, that.value1)
+ .compare(this.value2, that.value2)
+ .result();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value1, value2);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof MultiValuedTimestamp)) {
+ return false;
+ }
+ MultiValuedTimestamp that = (MultiValuedTimestamp) obj;
+ return Objects.equals(this.value1, that.value1) &&
+ Objects.equals(this.value2, that.value2);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("value1", value1)
+ .add("value2", value2)
+ .toString();
+ }
+
+ /**
+ * Returns the first value.
+ *
+ * @return first value
+ */
+ public T value1() {
+ return value1;
+ }
+
+ /**
+ * Returns the second value.
+ *
+ * @return second value
+ */
+ public U value2() {
+ return value2;
+ }
+
+ // Default constructor for serialization
+ @SuppressWarnings("unused")
+ private MultiValuedTimestamp() {
+ this.value1 = null;
+ this.value2 = null;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/PartitionInfo.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/PartitionInfo.java
new file mode 100644
index 00000000..a0f06481
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/PartitionInfo.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * Contains information about a database partition.
+ */
+public class PartitionInfo {
+ private final String name;
+ private final long term;
+ private final List<String> members;
+ private final String leader;
+
+ /**
+ * Class constructor.
+ *
+ * @param name partition name
+ * @param term term number
+ * @param members partition members
+ * @param leader leader name
+ */
+ public PartitionInfo(String name, long term, List<String> members, String leader) {
+ this.name = name;
+ this.term = term;
+ this.members = ImmutableList.copyOf(members);
+ this.leader = leader;
+ }
+
+ /**
+ * Returns the name of the partition.
+ *
+ * @return partition name
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the term number.
+ *
+ * @return term number
+ */
+ public long term() {
+ return term;
+ }
+
+ /**
+ * Returns the list of partition members.
+ *
+ * @return partition members
+ */
+ public List<String> members() {
+ return members;
+ }
+
+ /**
+ * Returns the partition leader.
+ *
+ * @return partition leader
+ */
+ public String leader() {
+ return leader;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Serializer.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Serializer.java
new file mode 100644
index 00000000..6245175f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Serializer.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.onlab.util.KryoNamespace;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Interface for serialization of store artifacts.
+ */
+public interface Serializer {
+ /**
+ * Serialize the specified object.
+ * @param object object to serialize.
+ * @return serialized bytes.
+ * @param <T> encoded type
+ */
+ <T> byte[] encode(T object);
+
+ /**
+ * Deserialize the specified bytes.
+ * @param bytes byte array to deserialize.
+ * @return deserialized object.
+ * @param <T> decoded type
+ */
+ <T> T decode(byte[] bytes);
+
+ /**
+ * Creates a new Serializer instance from a KryoNamespace.
+ *
+ * @param kryo kryo namespace
+ * @return Serializer instance
+ */
+ static Serializer using(KryoNamespace kryo) {
+ return using(Arrays.asList(kryo));
+ }
+
+ static Serializer using(List<KryoNamespace> namespaces, Class<?>... classes) {
+ KryoNamespace.Builder builder = new KryoNamespace.Builder();
+ namespaces.forEach(builder::register);
+ Lists.newArrayList(classes).forEach(builder::register);
+ builder.register(MapEvent.class, MapEvent.Type.class, Versioned.class);
+ KryoNamespace namespace = builder.build();
+ return new Serializer() {
+ @Override
+ public <T> byte[] encode(T object) {
+ return namespace.serialize(object);
+ }
+
+ @Override
+ public <T> T decode(byte[] bytes) {
+ return namespace.deserialize(bytes);
+ }
+ };
+ }
+
+ static Serializer forTypes(Class<?>... classes) {
+ return using(KryoNamespace.newBuilder()
+ .register(classes)
+ .register(MapEvent.class, MapEvent.Type.class)
+ .build());
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/SetEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/SetEvent.java
new file mode 100644
index 00000000..a869e722
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/SetEvent.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.Objects;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Representation of a DistributedSet update notification.
+ *
+ * @param <E> set element type
+ */
+public final class SetEvent<E> {
+
+ /**
+ * SetEvent type.
+ */
+ public enum Type {
+ /**
+ * Entry added to the set.
+ */
+ ADD,
+
+ /**
+ * Entry removed from the set.
+ */
+ REMOVE
+ }
+
+ private final String name;
+ private final Type type;
+ private final E entry;
+
+ /**
+ * Creates a new event object.
+ *
+ * @param name set name
+ * @param type type of the event
+ * @param entry entry the event concerns
+ */
+ public SetEvent(String name, Type type, E entry) {
+ this.name = name;
+ this.type = type;
+ this.entry = entry;
+ }
+
+ /**
+ * Returns the set name.
+ *
+ * @return name of set
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the type of the event.
+ *
+ * @return type of the event
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the entry this event concerns.
+ *
+ * @return the entry
+ */
+ public E entry() {
+ return entry;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof SetEvent)) {
+ return false;
+ }
+
+ SetEvent that = (SetEvent) o;
+ return Objects.equals(this.name, that.name) &&
+ Objects.equals(this.type, that.type) &&
+ Objects.equals(this.entry, that.entry);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, type, entry);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("name", name)
+ .add("type", type)
+ .add("entry", entry)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/SetEventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/SetEventListener.java
new file mode 100644
index 00000000..a64994ef
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/SetEventListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Listener to be notified about updates to a DistributedSet.
+ */
+public interface SetEventListener<E> {
+ /**
+ * Reacts to the specified event.
+ *
+ * @param event the event
+ */
+ void event(SetEvent<E> event);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageAdminService.java
new file mode 100644
index 00000000..22591044
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageAdminService.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Service for administering storage instances.
+ */
+public interface StorageAdminService {
+
+ /**
+ * Returns information about all partitions in the system.
+ *
+ * @return list of partition information
+ */
+ List<PartitionInfo> getPartitionInfo();
+
+ /**
+ * Returns information about all the consistent maps in the system.
+ *
+ * @return list of map information
+ */
+ List<MapInfo> getMapInfo();
+
+ /**
+ * Returns information about all the atomic counters in the system.
+ * If 2 counters belonging to 2 different databases have the same name,
+ * then only one counter from one database is returned.
+ *
+ * @return mapping from counter name to that counter's next value
+ */
+ Map<String, Long> getCounters();
+
+ /**
+ * Returns information about all the atomic partitioned database counters in the system.
+ *
+ * @return mapping from counter name to that counter's next value
+ */
+ Map<String, Long> getPartitionedDatabaseCounters();
+
+ /**
+ * Returns information about all the atomic in-memory database counters in the system.
+ *
+ * @return mapping from counter name to that counter's next value
+ */
+ Map<String, Long> getInMemoryDatabaseCounters();
+
+ /**
+ * Returns all the transactions in the system.
+ *
+ * @return collection of transactions
+ */
+ Collection<Transaction> getTransactions();
+
+ /**
+ * Redrives stuck transactions while removing those that are done.
+ */
+ void redriveTransactions();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageException.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageException.java
new file mode 100644
index 00000000..a66fc3ed
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageException.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+/**
+ * Top level exception for Store failures.
+ */
+@SuppressWarnings("serial")
+public class StorageException extends RuntimeException {
+ public StorageException() {
+ }
+
+ public StorageException(Throwable t) {
+ super(t);
+ }
+
+ /**
+ * Store operation timeout.
+ */
+ public static class Timeout extends StorageException {
+ }
+
+ /**
+ * Store update conflicts with an in flight transaction.
+ */
+ public static class ConcurrentModification extends StorageException {
+ }
+
+ /**
+ * Store operation interrupted.
+ */
+ public static class Interrupted extends StorageException {
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageService.java
new file mode 100644
index 00000000..f6b411d3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/StorageService.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Storage service.
+ * <p>
+ * This service provides builders for various distributed primitives.
+ * <p>
+ * It is expected that services and applications will leverage the primitives indirectly provided by
+ * this service for their distributed state management and coordination.
+ */
+public interface StorageService {
+
+ /**
+ * Creates a new EventuallyConsistentMapBuilder.
+ *
+ * @param <K> key type
+ * @param <V> value type
+ * @return builder for an eventually consistent map
+ */
+ <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder();
+
+ /**
+ * Creates a new ConsistentMapBuilder.
+ *
+ * @param <K> key type
+ * @param <V> value type
+ * @return builder for a consistent map
+ */
+ <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder();
+
+ /**
+ * Creates a new DistributedSetBuilder.
+ *
+ * @param <E> set element type
+ * @return builder for an distributed set
+ */
+ <E> DistributedSetBuilder<E> setBuilder();
+
+ /**
+ * Creates a new DistributedQueueBuilder.
+ *
+ * @param <E> queue entry type
+ * @return builder for an distributed queue
+ */
+ <E> DistributedQueueBuilder<E> queueBuilder();
+
+ /**
+ * Creates a new AtomicCounterBuilder.
+ *
+ * @return atomic counter builder
+ */
+ AtomicCounterBuilder atomicCounterBuilder();
+
+ /**
+ * Creates a new AtomicValueBuilder.
+ *
+ * @param <V> atomic value type
+ * @return atomic value builder
+ */
+ <V> AtomicValueBuilder<V> atomicValueBuilder();
+
+ /**
+ * Creates a new transaction context builder.
+ *
+ * @return a builder for a transaction context.
+ */
+ TransactionContextBuilder transactionContextBuilder();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Transaction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Transaction.java
new file mode 100644
index 00000000..330d8468
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Transaction.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.List;
+
+/**
+ * An immutable transaction object.
+ */
+public interface Transaction {
+
+ enum State {
+ /**
+ * Indicates a new transaction that is about to be prepared. All transactions
+ * start their life in this state.
+ */
+ PREPARING,
+
+ /**
+ * Indicates a transaction that is successfully prepared i.e. all participants voted to commit
+ */
+ PREPARED,
+
+ /**
+ * Indicates a transaction that is about to be committed.
+ */
+ COMMITTING,
+
+ /**
+ * Indicates a transaction that has successfully committed.
+ */
+ COMMITTED,
+
+ /**
+ * Indicates a transaction that is about to be rolled back.
+ */
+ ROLLINGBACK,
+
+ /**
+ * Indicates a transaction that has been rolled back and all locks are released.
+ */
+ ROLLEDBACK
+ }
+
+ /**
+ * Returns the transaction Id.
+ *
+ * @return transaction id
+ */
+ long id();
+
+ /**
+ * Returns the list of updates that are part of this transaction.
+ *
+ * @return list of database updates
+ */
+ List<DatabaseUpdate> updates();
+
+ /**
+ * Returns the current state of this transaction.
+ *
+ * @return transaction state
+ */
+ State state();
+
+ /**
+ * Returns true if this transaction has completed execution.
+ *
+ * @return true is yes, false otherwise
+ */
+ default boolean isDone() {
+ return state() == State.COMMITTED || state() == State.ROLLEDBACK;
+ }
+
+ /**
+ * Returns a new transaction that is created by transitioning this one to the specified state.
+ *
+ * @param newState destination state
+ * @return a new transaction instance similar to the current one but its state set to specified state
+ */
+ Transaction transition(State newState);
+
+ /**
+ * Returns the system time when the transaction was last updated.
+ *
+ * @return last update time
+ */
+ long lastUpdated();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java
new file mode 100644
index 00000000..94942e20
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+/**
+ * Provides a context for transactional operations.
+ * <p>
+ * A transaction context is a vehicle for grouping operations into a unit with the
+ * properties of atomicity, isolation, and durability. Transactions also provide the
+ * ability to maintain an application's invariants or integrity constraints,
+ * supporting the property of consistency. Together these properties are known as ACID.
+ * <p>
+ * A transaction context provides a boundary within which transactions
+ * are run. It also is a place where all modifications made within a transaction
+ * are cached until the point when the transaction commits or aborts. It thus ensures
+ * isolation of work happening with in the transaction boundary. Within a transaction
+ * context isolation level is REPEATABLE_READS i.e. only data that is committed can be read.
+ * The only uncommitted data that can be read is the data modified by the current transaction.
+ */
+public interface TransactionContext {
+
+ /**
+ * Returns the unique transactionId.
+ *
+ * @return transaction id
+ */
+ long transactionId();
+
+ /**
+ * Returns if this transaction context is open.
+ *
+ * @return true if open, false otherwise
+ */
+ boolean isOpen();
+
+ /**
+ * Starts a new transaction.
+ */
+ void begin();
+
+ /**
+ * Commits a transaction that was previously started thereby making its changes permanent
+ * and externally visible.
+ *
+ * @throws TransactionException if transaction fails to commit
+ */
+ void commit();
+
+ /**
+ * Aborts any changes made in this transaction context and discarding all locally cached updates.
+ */
+ void abort();
+
+ /**
+ * Returns a transactional map data structure with the specified name.
+ *
+ * @param <K> key type
+ * @param <V> value type
+ * @param mapName name of the transactional map
+ * @param serializer serializer to use for encoding/decoding keys and values of the map
+ * @return Transactional Map
+ */
+ <K, V> TransactionalMap<K, V> getTransactionalMap(String mapName, Serializer serializer);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContextBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContextBuilder.java
new file mode 100644
index 00000000..e9f3a020
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContextBuilder.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+/**
+ * Interface definition for a transaction context builder.
+ */
+public interface TransactionContextBuilder {
+
+ /**
+ * Disables distribution of map entries across multiple database partitions.
+ * <p>
+ * When partitioning is disabled, the returned map will have a single
+ * partition that spans the entire cluster. Furthermore, the changes made to
+ * the map are ephemeral and do not survive a full cluster restart.
+ * </p>
+ * <p>
+ * Note: By default, partitions are enabled. This feature is intended to
+ * simplify debugging.
+ * </p>
+ *
+ * @return this TransactionalContextBuilder
+ */
+ TransactionContextBuilder withPartitionsDisabled();
+
+ /**
+ * Builds a TransactionContext based on configuration options supplied to this
+ * builder.
+ *
+ * @return a new TransactionalContext
+ * @throws java.lang.RuntimeException if a mandatory parameter is missing
+ */
+ TransactionContext build();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionException.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionException.java
new file mode 100644
index 00000000..a3723ee7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionException.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+/**
+ * Top level exception for Transaction failures.
+ */
+@SuppressWarnings("serial")
+public class TransactionException extends StorageException {
+ public TransactionException() {
+ }
+
+ public TransactionException(Throwable t) {
+ super(t);
+ }
+
+ /**
+ * Transaction timeout.
+ */
+ public static class Timeout extends TransactionException {
+ }
+
+ /**
+ * Transaction interrupted.
+ */
+ public static class Interrupted extends TransactionException {
+ }
+
+ /**
+ * Transaction failure due to optimistic concurrency violation.
+ */
+ public static class OptimisticConcurrencyFailure extends TransactionException {
+ }
+
+ /**
+ * Transaction failure due to a conflicting transaction in progress.
+ */
+ public static class ConcurrentModification extends TransactionException {
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionalMap.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionalMap.java
new file mode 100644
index 00000000..657d9331
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionalMap.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+/**
+ * Transactional Map data structure.
+ * <p>
+ * A TransactionalMap is created by invoking {@link TransactionContext#getTransactionalMap getTransactionalMap}
+ * method. All operations performed on this map within a transaction boundary are invisible externally
+ * until the point when the transaction commits. A commit usually succeeds in the absence of conflicts.
+ *
+ * @param <K> type of key.
+ * @param <V> type of value.
+ */
+public interface TransactionalMap<K, V> {
+
+ /**
+ * Returns the value to which the specified key is mapped, or null if this
+ * map contains no mapping for the key.
+ *
+ * @param key the key whose associated value is to be returned
+ * @return the value to which the specified key is mapped, or null if
+ * this map contains no mapping for the key
+ */
+ V get(K key);
+
+ /**
+ * Associates the specified value with the specified key in this map (optional operation).
+ * If the map previously contained a mapping for the key, the old value is replaced by the
+ * specified value.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with key, or null if there was
+ * no mapping for key.
+ */
+ V put(K key, V value);
+
+ /**
+ * Removes the mapping for a key from this map if it is present (optional operation).
+ *
+ * @param key key whose value is to be removed from the map
+ * @return the value to which this map previously associated the key,
+ * or null if the map contained no mapping for the key.
+ */
+ V remove(K key);
+
+ /**
+ * If the specified key is not already associated with a value
+ * associates it with the given value and returns null, else returns the current value.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with the specified key or null
+ * if key does not already mapped to a value.
+ */
+ V putIfAbsent(K key, V value);
+
+ /**
+ * Removes the entry for the specified key only if it is currently
+ * mapped to the specified value.
+ *
+ * @param key key with which the specified value is associated
+ * @param value value expected to be associated with the specified key
+ * @return true if the value was removed
+ */
+ boolean remove(K key, V value);
+
+ /**
+ * Replaces the entry for the specified key only if currently mapped
+ * to the specified value.
+ *
+ * @param key key with which the specified value is associated
+ * @param oldValue value expected to be associated with the specified key
+ * @param newValue value to be associated with the specified key
+ * @return true if the value was replaced
+ */
+ boolean replace(K key, V oldValue, V newValue);
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Versioned.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Versioned.java
new file mode 100644
index 00000000..89bd3029
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/Versioned.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.service;
+
+import java.util.function.Function;
+
+import org.joda.time.DateTime;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+/**
+ * Versioned value.
+ *
+ * @param <V> value type.
+ */
+public class Versioned<V> {
+
+ private final V value;
+ private final long version;
+ private final long creationTime;
+
+ /**
+ * Constructs a new versioned value.
+ * @param value value
+ * @param version version
+ * @param creationTime milliseconds of the creation event
+ * from the Java epoch of 1970-01-01T00:00:00Z
+ */
+ public Versioned(V value, long version, long creationTime) {
+ this.value = value;
+ this.version = version;
+ this.creationTime = creationTime;
+ }
+
+ /**
+ * Constructs a new versioned value.
+ * @param value value
+ * @param version version
+ */
+ public Versioned(V value, long version) {
+ this(value, version, System.currentTimeMillis());
+ }
+
+ /**
+ * Returns the value.
+ *
+ * @return value.
+ */
+ public V value() {
+ return value;
+ }
+
+ /**
+ * Returns the version.
+ *
+ * @return version
+ */
+ public long version() {
+ return version;
+ }
+
+ /**
+ * Returns the system time when this version was created.
+ * <p>
+ * Care should be taken when relying on creationTime to
+ * implement any behavior in a distributed setting. Due
+ * to the possibility of clock skew it is likely that
+ * even creationTimes of causally related versions can be
+ * out or order.
+ * @return creation time
+ */
+ public long creationTime() {
+ return creationTime;
+ }
+
+ /**
+ * Maps this instance into another after transforming its
+ * value while retaining the same version and creationTime.
+ * @param transformer function for mapping the value
+ * @param <U> value type of the returned instance
+ * @return mapped instance
+ */
+ public <U> Versioned<U> map(Function<V, U> transformer) {
+ return new Versioned<>(transformer.apply(value), version, creationTime);
+ }
+
+ /**
+ * Returns the value of the specified Versioned object if non-null or else returns
+ * a default value.
+ * @param versioned versioned object
+ * @param defaultValue default value to return if versioned object is null
+ * @param <U> type of the versioned value
+ * @return versioned value or default value if versioned object is null
+ */
+ public static <U> U valueOrElse(Versioned<U> versioned, U defaultValue) {
+ return versioned == null ? defaultValue : versioned.value();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(value, version, creationTime);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Versioned)) {
+ return false;
+ }
+ Versioned<V> that = (Versioned) other;
+ return Objects.equal(this.value, that.value) &&
+ Objects.equal(this.version, that.version) &&
+ Objects.equal(this.creationTime, that.creationTime);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("value", value)
+ .add("version", version)
+ .add("creationTime", new DateTime(creationTime))
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/WallClockTimestamp.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/WallClockTimestamp.java
new file mode 100644
index 00000000..0cc7b453
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/WallClockTimestamp.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.Objects;
+
+import org.onosproject.store.Timestamp;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ComparisonChain;
+
+/**
+ * A Timestamp that derives its value from the prevailing
+ * wallclock time on the controller where it is generated.
+ */
+public class WallClockTimestamp implements Timestamp {
+
+ private final long unixTimestamp;
+
+ public WallClockTimestamp() {
+ unixTimestamp = System.currentTimeMillis();
+ }
+
+ public WallClockTimestamp(long timestamp) {
+ unixTimestamp = timestamp;
+ }
+
+ @Override
+ public int compareTo(Timestamp o) {
+ checkArgument(o instanceof WallClockTimestamp,
+ "Must be WallClockTimestamp", o);
+ WallClockTimestamp that = (WallClockTimestamp) o;
+
+ return ComparisonChain.start()
+ .compare(this.unixTimestamp, that.unixTimestamp)
+ .result();
+ }
+ @Override
+ public int hashCode() {
+ return Objects.hash(unixTimestamp);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof WallClockTimestamp)) {
+ return false;
+ }
+ WallClockTimestamp that = (WallClockTimestamp) obj;
+ return Objects.equals(this.unixTimestamp, that.unixTimestamp);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("unixTimestamp", unixTimestamp)
+ .toString();
+ }
+
+ /**
+ * Returns the unixTimestamp.
+ *
+ * @return unix timestamp
+ */
+ public long unixTimestamp() {
+ return unixTimestamp;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/package-info.java
new file mode 100644
index 00000000..3d86e351
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Distributed core state management services.
+ */
+package org.onosproject.store.service;
+
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/JsonUtils.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/JsonUtils.java
new file mode 100644
index 00000000..2ebb5545
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/JsonUtils.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.ui;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Provides convenience methods for dealing with JSON nodes, arrays etc.
+ */
+public final class JsonUtils {
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ // non-instantiable
+ private JsonUtils() { }
+
+ /**
+ * Wraps a message payload into an event structure for the given event
+ * type and sequence ID. Generally, the sequence ID should be a copy of
+ * the ID from the client request event.
+ *
+ * @param type event type
+ * @param sid sequence ID
+ * @param payload event payload
+ * @return the object node representation
+ */
+ public static ObjectNode envelope(String type, long sid, ObjectNode payload) {
+ ObjectNode event = MAPPER.createObjectNode();
+ event.put("event", type);
+ if (sid > 0) {
+ event.put("sid", sid);
+ }
+ event.set("payload", payload);
+ return event;
+ }
+
+ /**
+ * Composes a message structure for the given message type and payload.
+ *
+ * @param type message type
+ * @param payload message payload
+ * @return the object node representation
+ */
+ public static ObjectNode envelope(String type, ObjectNode payload) {
+ ObjectNode event = MAPPER.createObjectNode();
+ event.put("event", type);
+ event.set("payload", payload);
+ return event;
+ }
+
+ /**
+ * Returns the event type from the specified event.
+ * If the node does not have an "event" property, "unknown" is returned.
+ *
+ * @param event message event
+ * @return extracted event type
+ */
+ public static String eventType(ObjectNode event) {
+ return string(event, "event", "unknown");
+ }
+
+ /**
+ * Returns the sequence identifier from the specified event, or 0 (zero)
+ * if the "sid" property does not exist.
+ *
+ * @param event message event
+ * @return extracted sequence identifier
+ */
+ public static long sid(ObjectNode event) {
+ return number(event, "sid");
+ }
+
+ /**
+ * Returns the payload from the specified event.
+ *
+ * @param event message event
+ * @return extracted payload object
+ */
+ public static ObjectNode payload(ObjectNode event) {
+ return (ObjectNode) event.path("payload");
+ }
+
+ /**
+ * Returns the specified node property as a number.
+ *
+ * @param node message event
+ * @param name property name
+ * @return property as number
+ */
+ public static long number(ObjectNode node, String name) {
+ return node.path(name).asLong();
+ }
+
+ /**
+ * Returns the specified node property as a string.
+ *
+ * @param node message event
+ * @param name property name
+ * @return property as a string
+ */
+ public static String string(ObjectNode node, String name) {
+ return node.path(name).asText();
+ }
+
+ /**
+ * Returns the specified node property as a string, with a default fallback.
+ *
+ * @param node object node
+ * @param name property name
+ * @param defaultValue fallback value if property is absent
+ * @return property as a string
+ */
+ public static String string(ObjectNode node, String name, String defaultValue) {
+ return node.path(name).asText(defaultValue);
+ }
+
+ /**
+ * Returns the specified node property as an object node.
+ *
+ * @param node object node
+ * @param name property name
+ * @return property as a node
+ */
+ public static ObjectNode node(ObjectNode node, String name) {
+ return (ObjectNode) node.path(name);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/RequestHandler.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/RequestHandler.java
new file mode 100644
index 00000000..1678923d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/RequestHandler.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ui;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Abstraction of an entity that handles a specific request from the
+ * user interface client.
+ *
+ * @see UiMessageHandler
+ */
+public abstract class RequestHandler {
+
+ protected static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private final String eventType;
+ private UiMessageHandler parent;
+
+
+ public RequestHandler(String eventType) {
+ this.eventType = eventType;
+ }
+
+ // package private
+ void setParent(UiMessageHandler parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Returns the event type that this handler handles.
+ *
+ * @return event type
+ */
+ public String eventType() {
+ return eventType;
+ }
+
+ /**
+ * Processes the incoming message payload from the client.
+ *
+ * @param sid message sequence identifier
+ * @param payload request message payload
+ */
+ // TODO: remove sid from signature
+ public abstract void process(long sid, ObjectNode payload);
+
+
+
+ // ===================================================================
+ // === Convenience methods...
+
+ /**
+ * Returns implementation of the specified service class.
+ *
+ * @param serviceClass service class
+ * @param <T> type of service
+ * @return implementation class
+ * @throws org.onlab.osgi.ServiceNotFoundException if no implementation found
+ */
+ protected <T> T get(Class<T> serviceClass) {
+ return parent.directory().get(serviceClass);
+ }
+
+ /**
+ * Sends a message back to the client.
+ *
+ * @param eventType message event type
+ * @param sid message sequence identifier
+ * @param payload message payload
+ */
+ // TODO: remove sid from signature
+ protected void sendMessage(String eventType, long sid, ObjectNode payload) {
+ parent.connection().sendMessage(eventType, sid, payload);
+ }
+
+ /**
+ * Sends a message back to the client.
+ * Here, the message is preformatted; the assumption is it has its
+ * eventType, sid and payload attributes already filled in.
+ *
+ * @param message the message to send
+ */
+ protected void sendMessage(ObjectNode message) {
+ parent.connection().sendMessage(message);
+ }
+
+ /**
+ * Allows one request handler to pass the event on to another for
+ * further processing.
+ * Note that the message handlers must be defined in the same parent.
+ *
+ * @param eventType event type
+ * @param sid sequence identifier
+ * @param payload message payload
+ */
+ // TODO: remove sid from signature
+ protected void chain(String eventType, long sid, ObjectNode payload) {
+ parent.exec(eventType, sid, payload);
+ }
+
+ // ===================================================================
+
+
+ /**
+ * Returns the specified node property as a string.
+ *
+ * @param node message event
+ * @param key property name
+ * @return property as a string
+ */
+ protected String string(ObjectNode node, String key) {
+ return JsonUtils.string(node, key);
+ }
+
+ /**
+ * Returns the specified node property as a string, with a default fallback.
+ *
+ * @param node object node
+ * @param key property name
+ * @param defValue fallback value if property is absent
+ * @return property as a string
+ */
+ protected String string(ObjectNode node, String key, String defValue) {
+ return JsonUtils.string(node, key, defValue);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiConnection.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiConnection.java
new file mode 100644
index 00000000..ead7b0dc
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiConnection.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ui;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Abstraction of a user interface session connection.
+ */
+public interface UiConnection {
+
+ /**
+ * Sends the specified JSON message to the user interface client.
+ *
+ * @param message message to send
+ */
+ void sendMessage(ObjectNode message);
+
+ /**
+ * Composes a message into JSON and sends it to the user interface client.
+ *
+ * @param type message type
+ * @param sid message sequence number
+ * @param payload message payload
+ */
+ // TODO: remove sid parameter
+ void sendMessage(String type, long sid, ObjectNode payload);
+
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiExtension.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiExtension.java
new file mode 100644
index 00000000..1f5fbd48
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiExtension.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ui;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * User interface extension.
+ */
+public final class UiExtension {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private static final String VIEW_PREFIX = "app/view/";
+ private static final String EMPTY = "";
+ private static final String SLASH = "/";
+ private static final String CSS_HTML = "css.html";
+ private static final String JS_HTML = "js.html";
+
+ private final ClassLoader classLoader;
+ private final String resourcePath;
+ private final List<UiView> views;
+ private final UiMessageHandlerFactory messageHandlerFactory;
+ private final UiTopoOverlayFactory topoOverlayFactory;
+
+
+ // private constructor - only the builder calls this
+ private UiExtension(ClassLoader cl, String path, List<UiView> views,
+ UiMessageHandlerFactory mhFactory,
+ UiTopoOverlayFactory toFactory) {
+ this.classLoader = cl;
+ this.resourcePath = path;
+ this.views = views;
+ this.messageHandlerFactory = mhFactory;
+ this.topoOverlayFactory = toFactory;
+ }
+
+
+ /**
+ * Returns input stream containing CSS inclusion statements.
+ *
+ * @return CSS inclusion statements
+ */
+ public InputStream css() {
+ return getStream(resourcePath + CSS_HTML);
+ }
+
+ /**
+ * Returns input stream containing JavaScript inclusion statements.
+ *
+ * @return JavaScript inclusion statements
+ */
+ public InputStream js() {
+ return getStream(resourcePath + JS_HTML);
+ }
+
+ /**
+ * Returns list of user interface views contributed by this extension.
+ *
+ * @return contributed view descriptors
+ */
+ public List<UiView> views() {
+ return views;
+ }
+
+ /**
+ * Returns input stream containing specified view-specific resource.
+ *
+ * @param viewId view identifier
+ * @param path resource path, relative to the view directory
+ * @return resource input stream
+ */
+ public InputStream resource(String viewId, String path) {
+ return getStream(VIEW_PREFIX + viewId + SLASH + path);
+ }
+
+ /**
+ * Returns message handler factory, if one was defined.
+ *
+ * @return message handler factory
+ */
+ public UiMessageHandlerFactory messageHandlerFactory() {
+ return messageHandlerFactory;
+ }
+
+ /**
+ * Returns the topology overlay factory, if one was defined.
+ *
+ * @return topology overlay factory
+ */
+ public UiTopoOverlayFactory topoOverlayFactory() {
+ return topoOverlayFactory;
+ }
+
+
+ // Returns the resource input stream from the specified class-loader.
+ private InputStream getStream(String path) {
+ InputStream stream = classLoader.getResourceAsStream(path);
+ if (stream == null) {
+ log.warn("Unable to find resource {}", path);
+ }
+ return stream;
+ }
+
+
+ /**
+ * UI Extension Builder.
+ */
+ public static class Builder {
+ private ClassLoader classLoader;
+
+ private String resourcePath = EMPTY;
+ private List<UiView> views = new ArrayList<>();
+ private UiMessageHandlerFactory messageHandlerFactory = null;
+ private UiTopoOverlayFactory topoOverlayFactory = null;
+
+ /**
+ * Create a builder with the given class loader.
+ * Resource path defaults to "".
+ * Views defaults to an empty list.
+ * Both Message and TopoOverlay factories default to null.
+ *
+ * @param cl the class loader
+ * @param views list of views contributed by this extension
+ */
+ public Builder(ClassLoader cl, List<UiView> views) {
+ checkNotNull(cl, "Must provide a class loader");
+ checkArgument(views.size() > 0, "Must provide at least one view");
+ this.classLoader = cl;
+ this.views = views;
+ }
+
+ /**
+ * Set the resource path. That is, path to where the CSS and JS
+ * files are located. This value should
+ *
+ * @param path resource path
+ * @return self, for chaining
+ */
+ public Builder resourcePath(String path) {
+ this.resourcePath = path == null ? EMPTY : path + SLASH;
+ return this;
+ }
+
+ /**
+ * Sets the message handler factory for this extension.
+ *
+ * @param mhFactory message handler factory
+ * @return self, for chaining
+ */
+ public Builder messageHandlerFactory(UiMessageHandlerFactory mhFactory) {
+ this.messageHandlerFactory = mhFactory;
+ return this;
+ }
+
+ /**
+ * Sets the topology overlay factory for this extension.
+ *
+ * @param toFactory topology overlay factory
+ * @return self, for chaining
+ */
+ public Builder topoOverlayFactory(UiTopoOverlayFactory toFactory) {
+ this.topoOverlayFactory = toFactory;
+ return this;
+ }
+
+ /**
+ * Builds the UI extension.
+ *
+ * @return UI extension instance
+ */
+ public UiExtension build() {
+ return new UiExtension(classLoader, resourcePath, views,
+ messageHandlerFactory, topoOverlayFactory);
+ }
+
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiExtensionService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiExtensionService.java
new file mode 100644
index 00000000..330fbb7a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiExtensionService.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ui;
+
+import java.util.List;
+
+/**
+ * Service for registering user interface extensions.
+ */
+public interface UiExtensionService {
+
+ /**
+ * Registers the specified user interface extension.
+ *
+ * @param extension GUI extension to register
+ */
+ void register(UiExtension extension);
+
+ /**
+ * Unregisters the specified user interface extension.
+ *
+ * @param extension GUI extension to unregister
+ */
+ void unregister(UiExtension extension);
+
+ /**
+ * Returns the list of user interface extensions.
+ *
+ * @return list of extensions
+ */
+ List<UiExtension> getExtensions();
+
+ /**
+ * Returns the user interface extension that contributed the specified view.
+ *
+ * @param viewId view identifier
+ * @return user interface extension
+ */
+ UiExtension getViewExtension(String viewId);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiMessageHandler.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiMessageHandler.java
new file mode 100644
index 00000000..9b9a406c
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiMessageHandler.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ui;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.osgi.ServiceDirectory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of an entity capable of processing JSON messages from the user
+ * interface client.
+ * <p>
+ * The message structure is:
+ * </p>
+ * <pre>
+ * {
+ * "type": "<em>event-type</em>",
+ * "payload": {
+ * <em>arbitrary JSON object structure</em>
+ * }
+ * }
+ * </pre>
+ * On {@link #init initialization} the handler will create and cache
+ * {@link RequestHandler} instances, each of which are bound to a particular
+ * <em>event-type</em>. On {@link #process arrival} of a new message,
+ * the <em>event-type</em> is determined, and the message dispatched to the
+ * corresponding <em>RequestHandler</em>'s
+ * {@link RequestHandler#process process} method.
+ */
+public abstract class UiMessageHandler {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private final Map<String, RequestHandler> handlerMap = new HashMap<>();
+ private final ObjectMapper mapper = new ObjectMapper();
+
+ private UiConnection connection;
+ private ServiceDirectory directory;
+
+
+ /**
+ * Subclasses must create and return the collection of request handlers
+ * for the message types they handle.
+ * <p>
+ * Note that request handlers should be stateless. When we are
+ * {@link #destroy destroyed}, we will simply drop our references to them
+ * and allow them to be garbage collected.
+ *
+ * @return the message handler instances
+ */
+ protected abstract Collection<RequestHandler> createRequestHandlers();
+
+ /**
+ * Returns the set of message types which this handler is capable of
+ * processing.
+ *
+ * @return set of message types
+ */
+ public Set<String> messageTypes() {
+ return Collections.unmodifiableSet(handlerMap.keySet());
+ }
+
+ /**
+ * Processes a JSON message from the user interface client.
+ *
+ * @param message JSON message
+ */
+ public void process(ObjectNode message) {
+ String type = JsonUtils.eventType(message);
+ ObjectNode payload = JsonUtils.payload(message);
+ // TODO: remove sid
+ exec(type, 0, payload);
+ }
+
+ /**
+ * Finds the appropriate handler and executes the process method.
+ *
+ * @param eventType event type
+ * @param sid sequence identifier
+ * @param payload message payload
+ */
+ // TODO: remove sid from signature
+ void exec(String eventType, long sid, ObjectNode payload) {
+ RequestHandler requestHandler = handlerMap.get(eventType);
+ if (requestHandler != null) {
+ requestHandler.process(sid, payload);
+ } else {
+ log.warn("no request handler for event type {}", eventType);
+ }
+ }
+
+ /**
+ * Initializes the handler with the user interface connection and
+ * service directory context.
+ *
+ * @param connection user interface connection
+ * @param directory service directory
+ */
+ public void init(UiConnection connection, ServiceDirectory directory) {
+ this.connection = connection;
+ this.directory = directory;
+
+ Collection<RequestHandler> handlers = createRequestHandlers();
+ checkNotNull(handlers, "Handlers cannot be null");
+ checkArgument(!handlers.isEmpty(), "Handlers cannot be empty");
+
+ for (RequestHandler h : handlers) {
+ h.setParent(this);
+ handlerMap.put(h.eventType(), h);
+ }
+ }
+
+ /**
+ * Destroys the message handler context.
+ */
+ public void destroy() {
+ this.connection = null;
+ this.directory = null;
+ handlerMap.clear();
+ }
+
+ /**
+ * Returns the user interface connection with which this handler was primed.
+ *
+ * @return user interface connection
+ */
+ public UiConnection connection() {
+ return connection;
+ }
+
+ /**
+ * Returns the user interface connection with which this handler was primed.
+ *
+ * @return user interface connection
+ */
+ public ServiceDirectory directory() {
+ return directory;
+ }
+
+ /**
+ * Returns implementation of the specified service class.
+ *
+ * @param serviceClass service class
+ * @param <T> type of service
+ * @return implementation class
+ * @throws org.onlab.osgi.ServiceNotFoundException if no implementation found
+ */
+ protected <T> T get(Class<T> serviceClass) {
+ return directory.get(serviceClass);
+ }
+
+ /**
+ * Returns a freshly minted object node.
+ *
+ * @return new object node
+ */
+ protected ObjectNode objectNode() {
+ return mapper.createObjectNode();
+ }
+
+ /**
+ * Returns a freshly minted array node.
+ *
+ * @return new array node
+ */
+ protected ArrayNode arrayNode() {
+ return mapper.createArrayNode();
+ }
+
+ /**
+ * Sends the specified data to the client.
+ * It is expected that the data is in the prescribed JSON format for
+ * events to the client.
+ *
+ * @param data data to be sent
+ */
+ protected synchronized void sendMessage(ObjectNode data) {
+ UiConnection connection = connection();
+ if (connection != null) {
+ connection.sendMessage(data);
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiMessageHandlerFactory.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiMessageHandlerFactory.java
new file mode 100644
index 00000000..522daa8f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiMessageHandlerFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ui;
+
+import java.util.Collection;
+
+/**
+ * Abstraction of an entity capable of producing a set of message handlers
+ * specific to the given user interface connection.
+ */
+public interface UiMessageHandlerFactory {
+
+ /**
+ * Produces a collection of new message handlers.
+ *
+ * @return collection of new handlers
+ */
+ Collection<UiMessageHandler> newHandlers();
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
new file mode 100644
index 00000000..2889422a
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui;
+
+import org.onosproject.ui.topo.PropertyPanel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Represents user interface topology view overlay.
+ */
+public class UiTopoOverlay {
+
+ /**
+ * Logger for this overlay.
+ */
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final String id;
+
+ private boolean isActive = false;
+
+ /**
+ * Creates a new user interface topology view overlay descriptor.
+ *
+ * @param id overlay identifier
+ */
+ public UiTopoOverlay(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Returns the identifier for this overlay.
+ *
+ * @return the identifier
+ */
+ public String id() {
+ return id;
+ }
+
+ /**
+ * Callback invoked to initialize this overlay, soon after creation.
+ * This default implementation does nothing.
+ */
+ public void init() {
+ }
+
+ /**
+ * Callback invoked when this overlay is activated.
+ */
+ public void activate() {
+ isActive = true;
+ }
+
+ /**
+ * Callback invoked when this overlay is deactivated.
+ */
+ public void deactivate() {
+ isActive = false;
+ }
+
+ /**
+ * Returns true if this overlay is currently active.
+ *
+ * @return true if overlay active
+ */
+ public boolean isActive() {
+ return isActive;
+ }
+
+ /**
+ * Callback invoked to destroy this instance by cleaning up any
+ * internal state ready for garbage collection.
+ * This default implementation holds no state and does nothing.
+ */
+ public void destroy() {
+ }
+
+ /**
+ * Callback to modify the contents of the summary panel.
+ * This default implementation does nothing.
+ *
+ * @param pp property panel model of summary data
+ */
+ public void modifySummary(PropertyPanel pp) {
+ }
+
+ /**
+ * Callback to modify the contents of the details panel for
+ * a selected device.
+ * This default implementation does nothing.
+ *
+ * @param pp property panel model of summary data
+ */
+ public void modifyDeviceDetails(PropertyPanel pp) {
+ }
+
+ /**
+ * Callback to modify the contents of the details panel for
+ * a selected host.
+ * This default implementation does nothing.
+ *
+ * @param pp property panel model of summary data
+ */
+ public void modifyHostDetails(PropertyPanel pp) {
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlayFactory.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlayFactory.java
new file mode 100644
index 00000000..bd2f2fe6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlayFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui;
+
+import java.util.Collection;
+
+/**
+ * Abstraction of an entity capable of producing one or more topology
+ * overlay handlers specific to a given user interface connection.
+ */
+public interface UiTopoOverlayFactory {
+
+ /**
+ * Produces a collection of new overlay handlers.
+ *
+ * @return collection of new overlay handlers
+ */
+ Collection<UiTopoOverlay> newOverlays();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiView.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiView.java
new file mode 100644
index 00000000..2b8b7fa2
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiView.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ui;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Represents user interface view addition.
+ */
+public class UiView {
+
+ /**
+ * Designates navigation menu category.
+ */
+ public enum Category {
+ /**
+ * Represents platform related views.
+ */
+ PLATFORM("Platform"),
+
+ /**
+ * Represents network-control related views.
+ */
+ NETWORK("Network"),
+
+ /**
+ * Represents miscellaneous views.
+ */
+ OTHER("Other"),
+
+ /**
+ * Represents views that do not show in the navigation menu.
+ * This category should not be specified directly; rather, use
+ * the {@link UiViewHidden} constructor instead of {@link UiView}.
+ */
+ HIDDEN("(hidden)");
+
+ private final String label;
+
+ Category(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Returns display label for the category.
+ *
+ * @return display label
+ */
+ public String label() {
+ return label;
+ }
+ }
+
+ private final Category category;
+ private final String id;
+ private final String label;
+ private final String iconId;
+
+ /**
+ * Creates a new user interface view descriptor. The navigation item
+ * will appear in the navigation menu under the specified category.
+ *
+ * @param category view category
+ * @param id view identifier
+ * @param label view label
+ */
+ public UiView(Category category, String id, String label) {
+ this(category, id, label, null);
+ }
+
+ /**
+ * Creates a new user interface view descriptor. The navigation item
+ * will appear in the navigation menu under the specified category,
+ * with the specified icon adornment.
+ *
+ * @param category view category
+ * @param id view identifier
+ * @param label view label
+ * @param iconId icon id
+ */
+ public UiView(Category category, String id, String label, String iconId) {
+ this.category = category;
+ this.id = id;
+ this.label = label;
+ this.iconId = iconId;
+ }
+
+ /**
+ * Returns the navigation category.
+ *
+ * @return navigation category
+ */
+ public Category category() {
+ return category;
+ }
+
+ /**
+ * Returns the view identifier.
+ *
+ * @return view id
+ */
+ public String id() {
+ return id;
+ }
+
+ /**
+ * Returns the view label.
+ *
+ * @return view label
+ */
+ public String label() {
+ return label;
+ }
+
+ /**
+ * Returns the icon ID.
+ *
+ * @return icon ID
+ */
+ public String iconId() {
+ return iconId;
+ }
+
+ @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 UiView other = (UiView) obj;
+ return Objects.equals(this.id, other.id);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("category", category)
+ .add("id", id)
+ .add("label", label)
+ .add("iconId", iconId)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiViewHidden.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiViewHidden.java
new file mode 100644
index 00000000..b7fea8fe
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiViewHidden.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ui;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Represents user interface view addition, except that this one should not
+ * have an entry in the navigation panel.
+ */
+public class UiViewHidden extends UiView {
+
+ /**
+ * Creates a new user interface hidden view descriptor.
+ *
+ * @param id view identifier
+ */
+ public UiViewHidden(String id) {
+ super(Category.HIDDEN, id, null);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("id", id())
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/package-info.java
new file mode 100644
index 00000000..dd832a59
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Mechanism for managing dynamically registered user interface extensions.
+ */
+package org.onosproject.ui;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/CellComparator.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/CellComparator.java
new file mode 100644
index 00000000..84d11344
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/CellComparator.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table;
+
+/**
+ * Defines a comparator for cell values.
+ */
+public interface CellComparator {
+
+ /**
+ * Compares its two arguments for order. Returns a negative integer,
+ * zero, or a positive integer as the first argument is less than, equal
+ * to, or greater than the second.<p>
+ *
+ * Note that nulls are permitted, and should be sorted to the beginning
+ * of an ascending sort; i.e. null is considered to be "smaller" than
+ * non-null values.
+ *
+ * @see java.util.Comparator#compare(Object, Object)
+ *
+ * @param o1 the first object to be compared.
+ * @param o2 the second object to be compared.
+ * @return a negative integer, zero, or a positive integer as the
+ * first argument is less than, equal to, or greater than the
+ * second.
+ * @throws ClassCastException if the arguments' types prevent them from
+ * being compared by this comparator.
+ */
+ int compare(Object o1, Object o2);
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/CellFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/CellFormatter.java
new file mode 100644
index 00000000..854ac27f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/CellFormatter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table;
+
+/**
+ * Defines a formatter for cell values.
+ */
+public interface CellFormatter {
+
+ /**
+ * Formats the specified value into a string appropriate for displaying
+ * in a table cell. Note that null values are acceptable, and will result
+ * in the empty string.
+ *
+ * @param value the value
+ * @return the formatted string
+ */
+ String format(Object value);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableModel.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableModel.java
new file mode 100644
index 00000000..d0fccb65
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableModel.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.ui.table;
+
+import com.google.common.collect.Sets;
+import org.onosproject.ui.table.cell.DefaultCellComparator;
+import org.onosproject.ui.table.cell.DefaultCellFormatter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A simple model of table data.
+ * <p>
+ * Note that this is not a full MVC type model; the expected usage pattern
+ * is to create an empty table, add rows (by consulting the business model),
+ * sort rows (based on client request parameters), and finally produce the
+ * sorted list of rows.
+ * <p>
+ * The table also provides a mechanism for defining how cell values for a
+ * particular column should be formatted into strings, to help facilitate
+ * the encoding of the table data into a JSON structure.
+ * <p>
+ * Note that it is expected that all values for a particular column will
+ * be the same class.
+ */
+public class TableModel {
+
+ private static final CellComparator DEF_CMP = DefaultCellComparator.INSTANCE;
+ private static final CellFormatter DEF_FMT = DefaultCellFormatter.INSTANCE;
+
+ private final String[] columnIds;
+ private final Set<String> idSet;
+ private final Map<String, CellComparator> comparators = new HashMap<>();
+ private final Map<String, CellFormatter> formatters = new HashMap<>();
+ private final List<Row> rows = new ArrayList<>();
+
+
+ /**
+ * Constructs a table (devoid of data) with the given column IDs.
+ *
+ * @param columnIds column identifiers
+ */
+ public TableModel(String... columnIds) {
+ checkNotNull(columnIds, "columnIds cannot be null");
+ checkArgument(columnIds.length > 0, "must be at least one column");
+
+ idSet = Sets.newHashSet(columnIds);
+ if (idSet.size() != columnIds.length) {
+ throw new IllegalArgumentException("duplicate column ID(s) detected");
+ }
+
+ this.columnIds = Arrays.copyOf(columnIds, columnIds.length);
+ }
+
+ private void checkId(String id) {
+ checkNotNull(id, "must provide a column ID");
+ if (!idSet.contains(id)) {
+ throw new IllegalArgumentException("unknown column id: " + id);
+ }
+ }
+
+ /**
+ * Returns the number of rows in this table model.
+ *
+ * @return number of rows
+ */
+ public int rowCount() {
+ return rows.size();
+ }
+
+ /**
+ * Returns the number of columns in this table model.
+ *
+ * @return number of columns
+ */
+ public int columnCount() {
+ return columnIds.length;
+ }
+
+ /**
+ * Returns the array of column IDs for this table model.
+ * <p>
+ * Implementation note: we are knowingly passing you a reference to
+ * our internal array to avoid copying. Don't mess with it. It's your
+ * table you'll break if you do!
+ *
+ * @return the column identifiers
+ */
+ public String[] getColumnIds() {
+ return columnIds;
+ }
+
+ /**
+ * Returns the raw {@link Row} representation of the rows in this table.
+ *
+ * @return raw table rows
+ */
+ public Row[] getRows() {
+ return rows.toArray(new Row[rows.size()]);
+ }
+
+ /**
+ * Sets a cell comparator for the specified column.
+ *
+ * @param columnId column identifier
+ * @param comparator comparator to use
+ */
+ public void setComparator(String columnId, CellComparator comparator) {
+ checkNotNull(comparator, "must provide a comparator");
+ checkId(columnId);
+ comparators.put(columnId, comparator);
+ }
+
+ /**
+ * Returns the cell comparator to use on values in the specified column.
+ *
+ * @param columnId column identifier
+ * @return an appropriate cell comparator
+ */
+ private CellComparator getComparator(String columnId) {
+ checkId(columnId);
+ CellComparator cmp = comparators.get(columnId);
+ return cmp == null ? DEF_CMP : cmp;
+ }
+
+ /**
+ * Sets a cell formatter for the specified column.
+ *
+ * @param columnId column identifier
+ * @param formatter formatter to use
+ */
+ public void setFormatter(String columnId, CellFormatter formatter) {
+ checkNotNull(formatter, "must provide a formatter");
+ checkId(columnId);
+ formatters.put(columnId, formatter);
+ }
+
+ /**
+ * Returns the cell formatter to use on values in the specified column.
+ *
+ * @param columnId column identifier
+ * @return an appropriate cell formatter
+ */
+ public CellFormatter getFormatter(String columnId) {
+ checkId(columnId);
+ CellFormatter fmt = formatters.get(columnId);
+ return fmt == null ? DEF_FMT : fmt;
+ }
+
+ /**
+ * Adds a row to the table model.
+ *
+ * @return the row, for chaining
+ */
+ public Row addRow() {
+ Row r = new Row();
+ rows.add(r);
+ return r;
+ }
+
+ /**
+ * Sorts the table rows based on the specified column, in the
+ * specified direction.
+ *
+ * @param columnId column identifier
+ * @param dir sort direction
+ */
+ public void sort(String columnId, SortDir dir) {
+ Collections.sort(rows, new RowComparator(columnId, dir));
+ }
+
+
+ /** Designates sorting direction. */
+ public enum SortDir {
+ /** Designates an ascending sort. */
+ ASC,
+ /** Designates a descending sort. */
+ DESC
+ }
+
+ /**
+ * Row comparator.
+ */
+ private class RowComparator implements Comparator<Row> {
+ private final String columnId;
+ private final SortDir dir;
+ private final CellComparator cellComparator;
+
+ /**
+ * Constructs a row comparator based on the specified
+ * column identifier and sort direction.
+ *
+ * @param columnId column identifier
+ * @param dir sort direction
+ */
+ public RowComparator(String columnId, SortDir dir) {
+ this.columnId = columnId;
+ this.dir = dir;
+ cellComparator = getComparator(columnId);
+ }
+
+ @Override
+ public int compare(Row a, Row b) {
+ Object cellA = a.get(columnId);
+ Object cellB = b.get(columnId);
+ int result = cellComparator.compare(cellA, cellB);
+ return dir == SortDir.ASC ? result : -result;
+ }
+ }
+
+ /**
+ * Model of a row.
+ */
+ public class Row {
+ private final Map<String, Object> cells = new HashMap<>();
+
+ /**
+ * Sets the cell value for the given column of this row.
+ *
+ * @param columnId column identifier
+ * @param value value to set
+ * @return self, for chaining
+ */
+ public Row cell(String columnId, Object value) {
+ checkId(columnId);
+ cells.put(columnId, value);
+ return this;
+ }
+
+ /**
+ * Returns the value of the cell in the given column for this row.
+ *
+ * @param columnId column identifier
+ * @return cell value
+ */
+ public Object get(String columnId) {
+ return cells.get(columnId);
+ }
+
+ /**
+ * Returns the value of the cell as a string, using the
+ * formatter appropriate for the column.
+ *
+ * @param columnId column identifier
+ * @return formatted cell value
+ */
+ String getAsString(String columnId) {
+ return getFormatter(columnId).format(get(columnId));
+ }
+
+ /**
+ * Returns the row as an array of formatted strings.
+ *
+ * @return the formatted row data
+ */
+ public String[] getAsFormattedStrings() {
+ List<String> formatted = new ArrayList<>(columnCount());
+ for (String c : columnIds) {
+ formatted.add(getAsString(c));
+ }
+ return formatted.toArray(new String[formatted.size()]);
+ }
+ }
+
+ private static final String DESC = "desc";
+
+ /**
+ * Returns the appropriate sort direction for the given string.
+ * <p>
+ * The expected strings are "asc" for {@link SortDir#ASC ascending} and
+ * "desc" for {@link SortDir#DESC descending}. Any other value will
+ * default to ascending.
+ *
+ * @param s sort direction string encoding
+ * @return sort direction
+ */
+ public static SortDir sortDir(String s) {
+ return !DESC.equals(s) ? SortDir.ASC : SortDir.DESC;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableRequestHandler.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableRequestHandler.java
new file mode 100644
index 00000000..b8d48575
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableRequestHandler.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.ui.table;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.ui.JsonUtils;
+import org.onosproject.ui.RequestHandler;
+
+/**
+ * Message handler specifically for table views.
+ */
+public abstract class TableRequestHandler extends RequestHandler {
+
+ private final String respType;
+ private final String nodeName;
+
+ /**
+ * Constructs a table request handler for a specific table view. When
+ * table requests come in, the handler will generate the appropriate
+ * table rows, sort them according the the request sort parameters, and
+ * send back the response to the client.
+ *
+ * @param reqType type of the request event
+ * @param respType type of the response event
+ * @param nodeName name of JSON node holding row data
+ */
+ public TableRequestHandler(String reqType, String respType, String nodeName) {
+ super(reqType);
+ this.respType = respType;
+ this.nodeName = nodeName;
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ TableModel tm = createTableModel();
+ populateTable(tm, payload);
+
+ String sortCol = JsonUtils.string(payload, "sortCol", defaultColumnId());
+ String sortDir = JsonUtils.string(payload, "sortDir", "asc");
+ tm.sort(sortCol, TableModel.sortDir(sortDir));
+
+ ObjectNode rootNode = MAPPER.createObjectNode();
+ rootNode.set(nodeName, TableUtils.generateArrayNode(tm));
+ sendMessage(respType, 0, rootNode);
+ }
+
+ /**
+ * Creates the table model (devoid of data) using {@link #getColumnIds()}
+ * to initialize it, ready to be populated.
+ * <p>
+ * This default implementation returns a table model with default
+ * formatters and comparators for all columns.
+ *
+ * @return an empty table model
+ */
+ protected TableModel createTableModel() {
+ return new TableModel(getColumnIds());
+ }
+
+ /**
+ * Returns the default column ID to be used when one is not supplied in
+ * the payload as the column on which to sort.
+ * <p>
+ * This default implementation returns "id".
+ *
+ * @return default sort column identifier
+ */
+ protected String defaultColumnId() {
+ return "id";
+ }
+
+ /**
+ * Subclasses should return the array of column IDs with which
+ * to initialize their table model.
+ *
+ * @return the column IDs
+ */
+ protected abstract String[] getColumnIds();
+
+ /**
+ * Subclasses should populate the table model by adding
+ * {@link TableModel.Row rows}.
+ * <pre>
+ * tm.addRow()
+ * .cell(COL_ONE, ...)
+ * .cell(COL_TWO, ...)
+ * ... ;
+ * </pre>
+ * The request payload is provided in case there are request filtering
+ * parameters (other than sort column and sort direction) that are required
+ * to generate the appropriate data.
+ *
+ * @param tm the table model
+ * @param payload request payload
+ */
+ protected abstract void populateTable(TableModel tm, ObjectNode payload);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableUtils.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableUtils.java
new file mode 100644
index 00000000..eb2dff78
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/TableUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.ui.table;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Provides static utility methods for dealing with tables.
+ */
+public final class TableUtils {
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ // non-instantiable
+ private TableUtils() { }
+
+ /**
+ * Generates a JSON array node from a table model.
+ *
+ * @param tm the table model
+ * @return the array node representation
+ */
+ public static ArrayNode generateArrayNode(TableModel tm) {
+ ArrayNode array = MAPPER.createArrayNode();
+ for (TableModel.Row r : tm.getRows()) {
+ array.add(toJsonNode(r, tm));
+ }
+ return array;
+ }
+
+ private static JsonNode toJsonNode(TableModel.Row row, TableModel tm) {
+ ObjectNode result = MAPPER.createObjectNode();
+ String[] keys = tm.getColumnIds();
+ String[] cells = row.getAsFormattedStrings();
+ int n = keys.length;
+ for (int i = 0; i < n; i++) {
+ result.put(keys[i], cells[i]);
+ }
+ return result;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AbstractCellComparator.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AbstractCellComparator.java
new file mode 100644
index 00000000..6113fc3f
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AbstractCellComparator.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.onosproject.ui.table.CellComparator;
+
+/**
+ * Base implementation of a {@link CellComparator}. This class takes care
+ * of dealing with null inputs; subclasses should implement their comparison
+ * knowing that both inputs are guaranteed to be non-null.
+ */
+public abstract class AbstractCellComparator implements CellComparator {
+
+ @Override
+ public int compare(Object o1, Object o2) {
+ if (o1 == null && o2 == null) {
+ return 0; // o1 == o2
+ }
+ if (o1 == null) {
+ return -1; // o1 < o2
+ }
+ if (o2 == null) {
+ return 1; // o1 > o2
+ }
+ return nonNullCompare(o1, o2);
+ }
+
+ /**
+ * Compares its two arguments for order. Returns a negative integer,
+ * zero, or a positive integer as the first argument is less than, equal
+ * to, or greater than the second.<p>
+ *
+ * Note that both objects are guaranteed to be non-null.
+ *
+ * @see java.util.Comparator#compare(Object, Object)
+ *
+ * @param o1 the first object to be compared.
+ * @param o2 the second object to be compared.
+ * @return a negative integer, zero, or a positive integer as the
+ * first argument is less than, equal to, or greater than the
+ * second.
+ * @throws ClassCastException if the arguments' types prevent them from
+ * being compared by this comparator.
+ */
+ protected abstract int nonNullCompare(Object o1, Object o2);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AbstractCellFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AbstractCellFormatter.java
new file mode 100644
index 00000000..33ce2ab5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AbstractCellFormatter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.onosproject.ui.table.CellFormatter;
+
+/**
+ * Base implementation of a {@link CellFormatter}. This class takes care of
+ * dealing with null inputs; subclasses should implement their format method
+ * knowing that the input is guaranteed to be non-null.
+ */
+public abstract class AbstractCellFormatter implements CellFormatter {
+
+ @Override
+ public String format(Object value) {
+ return value == null ? "" : nonNullFormat(value);
+ }
+
+ /**
+ * Formats the specified value into a string appropriate for displaying
+ * in a table cell. Note that value is guaranteed to be non-null.
+ *
+ * @param value the value
+ * @return the formatted string
+ */
+ protected abstract String nonNullFormat(Object value);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java
new file mode 100644
index 00000000..42d684b6
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.ui.table.CellFormatter;
+
+/**
+ * Formats an application identifier as "(app-id) : (app-name)".
+ */
+public final class AppIdFormatter extends AbstractCellFormatter {
+
+ // non-instantiable
+ private AppIdFormatter() { }
+
+ @Override
+ protected String nonNullFormat(Object value) {
+ ApplicationId appId = (ApplicationId) value;
+ return appId.id() + " : " + appId.name();
+ }
+
+ /**
+ * An instance of this class.
+ */
+ public static final CellFormatter INSTANCE = new AppIdFormatter();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/ConnectPointFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/ConnectPointFormatter.java
new file mode 100644
index 00000000..fee26154
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/ConnectPointFormatter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.ui.table.CellFormatter;
+
+/**
+ * Formats a connect point as "(element-id)/(port)".
+ */
+public final class ConnectPointFormatter extends AbstractCellFormatter {
+
+ // non-instantiable
+ private ConnectPointFormatter() { }
+
+ @Override
+ protected String nonNullFormat(Object value) {
+ ConnectPoint cp = (ConnectPoint) value;
+ return cp.elementId() + "/" + cp.port();
+ }
+
+ /**
+ * An instance of this class.
+ */
+ public static final CellFormatter INSTANCE = new ConnectPointFormatter();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/DefaultCellComparator.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/DefaultCellComparator.java
new file mode 100644
index 00000000..093a20d3
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/DefaultCellComparator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.onosproject.ui.table.CellComparator;
+
+/**
+ * A default cell comparator.
+ * <p>
+ * Verifies that the objects being compared are the same class.
+ * Looks to see if the objects being compared implement comparable and, if so,
+ * delegates to that; otherwise, implements a lexicographical compare function
+ * (i.e. string sorting). Uses the objects' toString() method and then
+ * compares the resulting strings. Note that null values are acceptable and
+ * are considered "smaller" than any non-null value.
+ */
+public final class DefaultCellComparator extends AbstractCellComparator {
+
+ // non-instantiable
+ private DefaultCellComparator() { }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected int nonNullCompare(Object o1, Object o2) {
+ if (o1 instanceof Comparable) {
+ // if o2 is not the same class as o1, then compareTo will
+ // throw ClassCastException for us
+ return ((Comparable) o1).compareTo(o2);
+ }
+ return o1.toString().compareTo(o2.toString());
+ }
+
+ /**
+ * An instance of this class.
+ */
+ public static final CellComparator INSTANCE = new DefaultCellComparator();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/DefaultCellFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/DefaultCellFormatter.java
new file mode 100644
index 00000000..0efa2ebd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/DefaultCellFormatter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.onosproject.ui.table.CellFormatter;
+
+/**
+ * A default cell formatter. Uses the object's toString() method.
+ */
+public final class DefaultCellFormatter extends AbstractCellFormatter {
+
+ // non-instantiable
+ private DefaultCellFormatter() { }
+
+ @Override
+ public String nonNullFormat(Object value) {
+ return value.toString();
+ }
+
+ /**
+ * An instance of this class.
+ */
+ public static final CellFormatter INSTANCE = new DefaultCellFormatter();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/EnumFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/EnumFormatter.java
new file mode 100644
index 00000000..5b89a0b7
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/EnumFormatter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.onosproject.ui.table.CellFormatter;
+
+import static org.apache.commons.lang.WordUtils.capitalizeFully;
+
+/**
+ * Formats enum types to be readable strings.
+ */
+public final class EnumFormatter extends AbstractCellFormatter {
+
+ // non-instantiable
+ private EnumFormatter() { }
+
+ @Override
+ protected String nonNullFormat(Object value) {
+ return capitalizeFully(value.toString().replace("_", " "));
+ }
+
+ /**
+ * An instance of this class.
+ */
+ public static final CellFormatter INSTANCE = new EnumFormatter();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/HexFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/HexFormatter.java
new file mode 100644
index 00000000..e09982ea
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/HexFormatter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.onosproject.ui.table.CellFormatter;
+
+/**
+ * Formats integer values as hex strings with a "0x" prefix.
+ */
+public final class HexFormatter extends AbstractCellFormatter {
+
+ // non-instantiable
+ private HexFormatter() { }
+
+ @Override
+ protected String nonNullFormat(Object value) {
+ return "0x" + Integer.toHexString((Integer) value);
+ }
+
+ /**
+ * An instance of this class.
+ */
+ public static final CellFormatter INSTANCE = new HexFormatter();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/HostLocationFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/HostLocationFormatter.java
new file mode 100644
index 00000000..fe87c61b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/HostLocationFormatter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.onosproject.net.HostLocation;
+import org.onosproject.ui.table.CellFormatter;
+
+/**
+ * Formats a host location as "(device-id)/(port)".
+ */
+public final class HostLocationFormatter extends AbstractCellFormatter {
+
+ // non-instantiable
+ private HostLocationFormatter() { }
+
+ @Override
+ protected String nonNullFormat(Object value) {
+ HostLocation loc = (HostLocation) value;
+ return loc.deviceId() + "/" + loc.port();
+ }
+
+ /**
+ * An instance of this class.
+ */
+ public static final CellFormatter INSTANCE = new HostLocationFormatter();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/TimeFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/TimeFormatter.java
new file mode 100644
index 00000000..44dc1940
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/TimeFormatter.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.table.cell;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+
+import java.util.Locale;
+
+/**
+ * Formats time values using {@link DateTimeFormatter}.
+ */
+public final class TimeFormatter extends AbstractCellFormatter {
+
+ private DateTimeFormatter dtf;
+
+ // NOTE: Unlike other formatters in this package, this one is not
+ // implemented as a Singleton, because instances may be
+ // decorated with alternate locale and/or timezone.
+
+ /**
+ * Constructs a time formatter that uses the default locale and timezone.
+ */
+ public TimeFormatter() {
+ dtf = DateTimeFormat.longTime();
+ }
+
+ /**
+ * Sets the locale to use for formatting the time.
+ *
+ * @param locale locale to use for formatting
+ * @return self, for chaining
+ */
+ public TimeFormatter withLocale(Locale locale) {
+ dtf = dtf.withLocale(locale);
+ return this;
+ }
+
+ /**
+ * Sets the time zone to use for formatting the time.
+ *
+ * @param zone time zone to use
+ * @return self, for chaining
+ */
+ public TimeFormatter withZone(DateTimeZone zone) {
+ dtf = dtf.withZone(zone);
+ return this;
+ }
+
+ @Override
+ protected String nonNullFormat(Object value) {
+ return dtf.print((DateTime) value);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/package-info.java
new file mode 100644
index 00000000..c25bcb06
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Set of table cell renderers and comparators for use by GUI apps.
+ */
+package org.onosproject.ui.table.cell; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/package-info.java
new file mode 100644
index 00000000..ee975d11
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Facilities for creating tabular models of data for the GUI.
+ */
+package org.onosproject.ui.table; \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/AbstractHighlight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/AbstractHighlight.java
new file mode 100644
index 00000000..ab2ced36
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/AbstractHighlight.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Partial implementation of the highlighting to apply to topology
+ * view elements.
+ */
+public abstract class AbstractHighlight {
+ private final TopoElementType type;
+ private final String elementId;
+ private boolean keepSubdued = false;
+
+ /**
+ * Constructs the highlight.
+ *
+ * @param type highlight element type
+ * @param elementId element identifier
+ */
+ public AbstractHighlight(TopoElementType type, String elementId) {
+ this.type = checkNotNull(type);
+ this.elementId = checkNotNull(elementId);
+ }
+
+ /**
+ * Sets a flag to tell the renderer to keep this element subdued.
+ */
+ public void keepSubdued() {
+ keepSubdued = true;
+ }
+
+ /**
+ * Returns the element type.
+ *
+ * @return element type
+ */
+ public TopoElementType type() {
+ return type;
+ }
+
+ /**
+ * Returns the element identifier.
+ *
+ * @return element identifier
+ */
+ public String elementId() {
+ return elementId;
+ }
+
+ /**
+ * Returns the subdued flag.
+ *
+ * @return subdued flag
+ */
+ public boolean subdued() {
+ return keepSubdued;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BaseLink.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BaseLink.java
new file mode 100644
index 00000000..c37c129b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BaseLink.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+
+/**
+ * A simple concrete implementation of a {@link BiLink}.
+ * Note that this implementation does not generate any link highlights.
+ */
+public class BaseLink extends BiLink {
+
+ /**
+ * Constructs a base link for the given key and initial link.
+ *
+ * @param key canonical key for this base link
+ * @param link first link
+ */
+ public BaseLink(LinkKey key, Link link) {
+ super(key, link);
+ }
+
+ @Override
+ public LinkHighlight highlight(Enum<?> type) {
+ return null;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BaseLinkMap.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BaseLinkMap.java
new file mode 100644
index 00000000..720eca49
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BaseLinkMap.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+
+/**
+ * Collection of {@link BaseLink}s.
+ */
+public class BaseLinkMap extends BiLinkMap<BaseLink> {
+ @Override
+ public BaseLink create(LinkKey key, Link link) {
+ return new BaseLink(key, link);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BiLink.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BiLink.java
new file mode 100644
index 00000000..8c95e15d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BiLink.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a link and its inverse, as a partial implementation.
+ * <p>
+ * Subclasses will decide how to generate the link highlighting (coloring
+ * and labeling) for the topology view.
+ */
+public abstract class BiLink {
+
+ private final LinkKey key;
+ private final Link one;
+ private Link two;
+
+ /**
+ * Constructs a bi-link for the given key and initial link. It is expected
+ * that the caller will have used {@link TopoUtils#canonicalLinkKey(Link)}
+ * to generate the key.
+ *
+ * @param key canonical key for this bi-link
+ * @param link first link
+ */
+ public BiLink(LinkKey key, Link link) {
+ this.key = checkNotNull(key);
+ this.one = checkNotNull(link);
+ }
+
+ /**
+ * Sets the second link for this bi-link.
+ *
+ * @param link second link
+ */
+ public void setOther(Link link) {
+ this.two = checkNotNull(link);
+ }
+
+ /**
+ * Returns the link identifier in the form expected on the Topology View
+ * in the web client.
+ *
+ * @return link identifier
+ */
+ public String linkId() {
+ return TopoUtils.compactLinkString(one);
+ }
+
+ /**
+ * Returns the key for this bi-link.
+ *
+ * @return the key
+ */
+ public LinkKey key() {
+ return key;
+ }
+
+ /**
+ * Returns the first link in this bi-link.
+ *
+ * @return the first link
+ */
+ public Link one() {
+ return one;
+ }
+
+ /**
+ * Returns the second link in this bi-link.
+ *
+ * @return the second link
+ */
+ public Link two() {
+ return two;
+ }
+
+ /**
+ * Returns the link highlighting to use, based on this bi-link's current
+ * state.
+ *
+ * @param type optional highlighting type parameter
+ * @return link highlighting model
+ */
+ public abstract LinkHighlight highlight(Enum<?> type);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BiLinkMap.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BiLinkMap.java
new file mode 100644
index 00000000..7bc0e65d
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/BiLinkMap.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Represents a collection of {@link BiLink} concrete classes. These maps
+ * are used to collate a set of unidirectional {@link Link}s into a smaller
+ * set of bi-directional {@link BiLink} derivatives.
+ * <p>
+ * @param <B> the type of bi-link subclass
+ */
+public abstract class BiLinkMap<B extends BiLink> {
+
+ private final Map<LinkKey, B> map = new HashMap<>();
+
+ /**
+ * Creates a new instance of a bi-link. Concrete subclasses should
+ * instantiate and return the appropriate bi-link subclass.
+ *
+ * @param key the link key
+ * @param link the initial link
+ * @return a new instance
+ */
+ protected abstract B create(LinkKey key, Link link);
+
+ /**
+ * Adds the given link to our collection, returning the corresponding
+ * bi-link (creating one if needed necessary).
+ *
+ * @param link the link to add to the collection
+ * @return the corresponding bi-link wrapper
+ */
+ public B add(Link link) {
+ LinkKey key = TopoUtils.canonicalLinkKey(checkNotNull(link));
+ B blink = map.get(key);
+ if (blink == null) {
+ // no bi-link yet exists for this link
+ blink = create(key, link);
+ map.put(key, blink);
+ } else {
+ // we have a bi-link for this link.
+ if (!blink.one().equals(link)) {
+ blink.setOther(link);
+ }
+ }
+ return blink;
+ }
+
+ /**
+ * Returns the bi-link instances in the collection.
+ *
+ * @return the bi-links in this map
+ */
+ public Collection<B> biLinks() {
+ return map.values();
+ }
+
+ /**
+ * Returns the number of bi-links in the collection.
+ *
+ * @return number of bi-links
+ */
+ public int size() {
+ return map.size();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/ButtonId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/ButtonId.java
new file mode 100644
index 00000000..ca2ecccd
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/ButtonId.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Designates the identity of a button on the topology view panels.
+ */
+public class ButtonId {
+
+ private final String id;
+
+ /**
+ * Creates a button ID with the given identifier.
+ *
+ * @param id identifier for the button
+ */
+ public ButtonId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Returns the identifier for this button.
+ *
+ * @return identifier
+ */
+ public String id() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id()).toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ButtonId that = (ButtonId) o;
+ return id.equals(that.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/DeviceHighlight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/DeviceHighlight.java
new file mode 100644
index 00000000..2985d3d4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/DeviceHighlight.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+/**
+ * Denotes the highlighting to apply to a device.
+ */
+public class DeviceHighlight extends NodeHighlight {
+
+ public DeviceHighlight(String deviceId) {
+ super(TopoElementType.DEVICE, deviceId);
+ }
+
+ // TODO: implement device highlighting:
+ // - visual highlight
+ // - badging
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/Highlights.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/Highlights.java
new file mode 100644
index 00000000..be59c26b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/Highlights.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Encapsulates highlights to be applied to the topology view, such as
+ * highlighting links, displaying link labels, perhaps even decorating
+ * nodes with badges, etc.
+ */
+public class Highlights {
+
+ private static final String EMPTY = "";
+ private static final String MIN = "min";
+ private static final String MAX = "max";
+
+ /**
+ * A notion of amount.
+ */
+ public enum Amount {
+ ZERO(EMPTY),
+ MINIMALLY(MIN),
+ MAXIMALLY(MAX);
+
+ private final String s;
+ Amount(String str) {
+ s = str;
+ }
+
+ @Override
+ public String toString() {
+ return s;
+ }
+ }
+
+ private final Map<String, DeviceHighlight> devices = new HashMap<>();
+ private final Map<String, HostHighlight> hosts = new HashMap<>();
+ private final Map<String, LinkHighlight> links = new HashMap<>();
+
+ private Amount subdueLevel = Amount.ZERO;
+
+
+ /**
+ * Adds highlighting information for a device.
+ *
+ * @param dh device highlight
+ * @return self, for chaining
+ */
+ public Highlights add(DeviceHighlight dh) {
+ devices.put(dh.elementId(), dh);
+ return this;
+ }
+
+ /**
+ * Adds highlighting information for a host.
+ *
+ * @param hh host highlight
+ * @return self, for chaining
+ */
+ public Highlights add(HostHighlight hh) {
+ hosts.put(hh.elementId(), hh);
+ return this;
+ }
+
+ /**
+ * Adds highlighting information for a link.
+ *
+ * @param lh link highlight
+ * @return self, for chaining
+ */
+ public Highlights add(LinkHighlight lh) {
+ links.put(lh.elementId(), lh);
+ return this;
+ }
+
+ /**
+ * Marks the amount by which all other elements (devices, hosts, links)
+ * not explicitly referenced here will be "subdued" visually.
+ *
+ * @param amount amount to subdue other elements
+ * @return self, for chaining
+ */
+ public Highlights subdueAllElse(Amount amount) {
+ subdueLevel = checkNotNull(amount);
+ return this;
+ }
+
+ /**
+ * Returns the collection of device highlights.
+ *
+ * @return device highlights
+ */
+ public Collection<DeviceHighlight> devices() {
+ return Collections.unmodifiableCollection(devices.values());
+ }
+
+ /**
+ * Returns the collection of host highlights.
+ *
+ * @return host highlights
+ */
+ public Collection<HostHighlight> hosts() {
+ return Collections.unmodifiableCollection(hosts.values());
+ }
+
+ /**
+ * Returns the collection of link highlights.
+ *
+ * @return link highlights
+ */
+ public Collection<LinkHighlight> links() {
+ return Collections.unmodifiableCollection(links.values());
+ }
+
+ /**
+ * Returns the amount by which all other elements not explicitly
+ * referenced here should be "subdued".
+ *
+ * @return amount to subdue other elements
+ */
+ public Amount subdueLevel() {
+ return subdueLevel;
+ }
+
+ /**
+ * Returns the node highlight (device or host) for the given element
+ * identifier, or null if no match.
+ *
+ * @param id element identifier
+ * @return corresponding node highlight
+ */
+ public NodeHighlight getNode(String id) {
+ NodeHighlight nh = devices.get(id);
+ return nh != null ? nh : hosts.get(id);
+ }
+
+ /**
+ * Returns the device highlight for the given device identifier,
+ * or null if no match.
+ *
+ * @param id device identifier
+ * @return corresponding device highlight
+ */
+ public DeviceHighlight getDevice(String id) {
+ return devices.get(id);
+ }
+
+ /**
+ * Returns the host highlight for the given host identifier,
+ * or null if no match.
+ *
+ * @param id host identifier
+ * @return corresponding host highlight
+ */
+ public HostHighlight getHost(String id) {
+ return hosts.get(id);
+ }
+
+ /**
+ * Returns the link highlight for the given link identifier,
+ * or null if no match.
+ *
+ * @param id link identifier
+ * @return corresponding link highlight
+ */
+ public LinkHighlight getLink(String id) {
+ return links.get(id);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/HostHighlight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/HostHighlight.java
new file mode 100644
index 00000000..76669a84
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/HostHighlight.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+/**
+ * Denotes the highlighting to apply to a host.
+ */
+public class HostHighlight extends NodeHighlight {
+
+ public HostHighlight(String hostId) {
+ super(TopoElementType.HOST, hostId);
+ }
+
+ // TODO: implement host highlighting:
+ // - visual highlight
+ // - badging
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/LinkHighlight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/LinkHighlight.java
new file mode 100644
index 00000000..b4e43304
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/LinkHighlight.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Denotes the highlighting to be applied to a link.
+ * {@link Flavor} is a closed set of NO-, PRIMARY-, or SECONDARY- highlighting.
+ * {@link Mod} is an open ended set of additional modifications (CSS classes)
+ * that may also be applied.
+ * Note that {@link #MOD_OPTICAL} and {@link #MOD_ANIMATED} are pre-defined mods.
+ * Label text may be set, which will also be displayed on the link.
+ */
+public class LinkHighlight extends AbstractHighlight {
+
+ private static final String PLAIN = "plain";
+ private static final String PRIMARY = "primary";
+ private static final String SECONDARY = "secondary";
+ private static final String EMPTY = "";
+ private static final String SPACE = " ";
+
+ private final Flavor flavor;
+ private final Set<Mod> mods = new TreeSet<>();
+ private String label = EMPTY;
+
+ /**
+ * Constructs a link highlight entity.
+ *
+ * @param linkId the link identifier
+ * @param flavor the highlight flavor
+ */
+ public LinkHighlight(String linkId, Flavor flavor) {
+ super(TopoElementType.LINK, linkId);
+ this.flavor = checkNotNull(flavor);
+ }
+
+ /**
+ * Adds a highlighting modification to this link highlight.
+ *
+ * @param mod mod to be added
+ * @return self, for chaining
+ */
+ public LinkHighlight addMod(Mod mod) {
+ mods.add(checkNotNull(mod));
+ return this;
+ }
+
+ /**
+ * Adds a label to be displayed on the link.
+ *
+ * @param label the label text
+ * @return self, for chaining
+ */
+ public LinkHighlight setLabel(String label) {
+ this.label = label == null ? EMPTY : label;
+ return this;
+ }
+
+ /**
+ * Returns the highlight flavor.
+ *
+ * @return highlight flavor
+ */
+ public Flavor flavor() {
+ return flavor;
+ }
+
+ /**
+ * Returns the highlight modifications.
+ *
+ * @return highlight modifications
+ */
+ public Set<Mod> mods() {
+ return Collections.unmodifiableSet(mods);
+ }
+
+ /**
+ * Generates the CSS classes string from the {@link #flavor} and
+ * any optional {@link #mods}.
+ *
+ * @return CSS classes string
+ */
+ public String cssClasses() {
+ StringBuilder sb = new StringBuilder(flavor.toString());
+ mods.forEach(m -> sb.append(SPACE).append(m));
+ return sb.toString();
+ }
+
+ /**
+ * Returns the label text.
+ *
+ * @return label text
+ */
+ public String label() {
+ return label;
+ }
+
+ /**
+ * Link highlighting flavor.
+ */
+ public enum Flavor {
+ NO_HIGHLIGHT(PLAIN),
+ PRIMARY_HIGHLIGHT(PRIMARY),
+ SECONDARY_HIGHLIGHT(SECONDARY);
+
+ private String cssName;
+
+ Flavor(String s) {
+ cssName = s;
+ }
+
+ @Override
+ public String toString() {
+ return cssName;
+ }
+ }
+
+ /**
+ * Denotes a link to be tagged as an optical link.
+ */
+ public static final Mod MOD_OPTICAL = new Mod("optical");
+
+ /**
+ * Denotes a link to be tagged with animated traffic ("marching ants").
+ */
+ public static final Mod MOD_ANIMATED = new Mod("animated");
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/Mod.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/Mod.java
new file mode 100644
index 00000000..d21a8724
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/Mod.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Highlighting modification.
+ * <p>
+ * Note that (for link highlights) this translates to a CSS class name
+ * that is applied to the link in the Topology UI.
+ */
+public final class Mod implements Comparable<Mod> {
+ private final String modId;
+
+ /**
+ * Constructs a mod with the given identifier.
+ *
+ * @param modId modification identifier
+ */
+ public Mod(String modId) {
+ this.modId = checkNotNull(modId);
+ }
+
+ @Override
+ public String toString() {
+ return modId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Mod mod = (Mod) o;
+ return modId.equals(mod.modId);
+ }
+
+ @Override
+ public int hashCode() {
+ return modId.hashCode();
+ }
+
+ @Override
+ public int compareTo(Mod o) {
+ return this.modId.compareTo(o.modId);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeHighlight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeHighlight.java
new file mode 100644
index 00000000..735f8166
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeHighlight.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+/**
+ * Parent class of {@link DeviceHighlight} and {@link HostHighlight}.
+ */
+public abstract class NodeHighlight extends AbstractHighlight {
+ public NodeHighlight(TopoElementType type, String elementId) {
+ super(type, elementId);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeSelection.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeSelection.java
new file mode 100644
index 00000000..b284de1b
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeSelection.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.net.Device;
+import org.onosproject.net.Element;
+import org.onosproject.net.Host;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.ui.JsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.HostId.hostId;
+
+/**
+ * Encapsulates a selection of devices and/or hosts from the topology view.
+ */
+public class NodeSelection {
+
+ private static final Logger log =
+ LoggerFactory.getLogger(NodeSelection.class);
+
+ private static final String IDS = "ids";
+ private static final String HOVER = "hover";
+
+ private final DeviceService deviceService;
+ private final HostService hostService;
+
+ private final Set<String> ids;
+ private final String hover;
+
+ private final Set<Device> devices = new HashSet<>();
+ private final Set<Host> hosts = new HashSet<>();
+ private Element hovered;
+
+ /**
+ * Creates a node selection entity, from the given payload, using the
+ * supplied device and host services. Note that if a device or host was
+ * hovered over by the mouse, it is available via {@link #hovered()}.
+ *
+ * @param payload message payload
+ * @param deviceService device service
+ * @param hostService host service
+ */
+ public NodeSelection(ObjectNode payload,
+ DeviceService deviceService,
+ HostService hostService) {
+ this.deviceService = deviceService;
+ this.hostService = hostService;
+
+ ids = extractIds(payload);
+ hover = extractHover(payload);
+
+ // start by extracting the hovered element if any
+ if (isNullOrEmpty(hover)) {
+ hovered = null;
+ } else {
+ setHoveredElement();
+ }
+
+ // now go find the devices and hosts that are in the selection list
+ Set<String> unmatched = findDevices(ids);
+ unmatched = findHosts(unmatched);
+ if (unmatched.size() > 0) {
+ log.debug("Skipping unmatched IDs {}", unmatched);
+ }
+
+ }
+
+ /**
+ * Returns a view of the selected devices (hover not included).
+ *
+ * @return selected devices
+ */
+ public Set<Device> devices() {
+ return Collections.unmodifiableSet(devices);
+ }
+
+ /**
+ * Returns a view of the selected devices, including the hovered device
+ * if there was one.
+ *
+ * @return selected (plus hovered) devices
+ */
+ public Set<Device> devicesWithHover() {
+ Set<Device> withHover;
+ if (hovered != null && hovered instanceof Device) {
+ withHover = new HashSet<>(devices);
+ withHover.add((Device) hovered);
+ } else {
+ withHover = devices;
+ }
+ return Collections.unmodifiableSet(withHover);
+ }
+
+ /**
+ * Returns a view of the selected hosts (hover not included).
+ *
+ * @return selected hosts
+ */
+ public Set<Host> hosts() {
+ return Collections.unmodifiableSet(hosts);
+ }
+
+ /**
+ * Returns a view of the selected hosts, including the hovered host
+ * if thee was one.
+ *
+ * @return selected (plus hovered) hosts
+ */
+ public Set<Host> hostsWithHover() {
+ Set<Host> withHover;
+ if (hovered != null && hovered instanceof Host) {
+ withHover = new HashSet<>(hosts);
+ withHover.add((Host) hovered);
+ } else {
+ withHover = hosts;
+ }
+ return Collections.unmodifiableSet(withHover);
+ }
+
+ /**
+ * Returns the element (host or device) over which the mouse was hovering,
+ * or null.
+ *
+ * @return element hovered over
+ */
+ public Element hovered() {
+ return hovered;
+ }
+
+ /**
+ * Returns true if nothing is selected.
+ *
+ * @return true if nothing selected
+ */
+ public boolean none() {
+ return devices().size() == 0 && hosts().size() == 0;
+ }
+
+ @Override
+ public String toString() {
+ return "NodeSelection{" +
+ "ids=" + ids +
+ ", hover='" + hover + '\'' +
+ ", #devices=" + devices.size() +
+ ", #hosts=" + hosts.size() +
+ '}';
+ }
+
+ // == helper methods
+
+ private Set<String> extractIds(ObjectNode payload) {
+ ArrayNode array = (ArrayNode) payload.path(IDS);
+ if (array == null || array.size() == 0) {
+ return Collections.emptySet();
+ }
+
+ Set<String> ids = new HashSet<>();
+ for (JsonNode node : array) {
+ ids.add(node.asText());
+ }
+ return ids;
+ }
+
+ private String extractHover(ObjectNode payload) {
+ return JsonUtils.string(payload, HOVER);
+ }
+
+ private void setHoveredElement() {
+ Set<String> unmatched;
+ unmatched = new HashSet<>();
+ unmatched.add(hover);
+ unmatched = findDevices(unmatched);
+ if (devices.size() == 1) {
+ hovered = devices.iterator().next();
+ devices.clear();
+ } else {
+ unmatched = findHosts(unmatched);
+ if (hosts.size() == 1) {
+ hovered = hosts.iterator().next();
+ hosts.clear();
+ } else {
+ hovered = null;
+ log.debug("Skipping unmatched HOVER {}", unmatched);
+ }
+ }
+ }
+
+ private Set<String> findDevices(Set<String> ids) {
+ Set<String> unmatched = new HashSet<>();
+ Device device;
+
+ for (String id : ids) {
+ try {
+ device = deviceService.getDevice(deviceId(id));
+ if (device != null) {
+ devices.add(device);
+ } else {
+ unmatched.add(id);
+ }
+ } catch (Exception e) {
+ unmatched.add(id);
+ }
+ }
+ return unmatched;
+ }
+
+ private Set<String> findHosts(Set<String> ids) {
+ Set<String> unmatched = new HashSet<>();
+ Host host;
+
+ for (String id : ids) {
+ try {
+ host = hostService.getHost(hostId(id));
+ if (host != null) {
+ hosts.add(host);
+ } else {
+ unmatched.add(id);
+ }
+ } catch (Exception e) {
+ unmatched.add(id);
+ }
+ }
+ return unmatched;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/PropertyPanel.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/PropertyPanel.java
new file mode 100644
index 00000000..121e0834
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/PropertyPanel.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import com.google.common.collect.Sets;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Models a panel displayed on the Topology View.
+ */
+public class PropertyPanel {
+
+ private static final DecimalFormat DF0 = new DecimalFormat("#,###");
+
+ private String title;
+ private String typeId;
+ private String id;
+ private List<Prop> properties = new ArrayList<>();
+ private List<ButtonId> buttons = new ArrayList<>();
+
+ /**
+ * Constructs a property panel model with the given title and
+ * type identifier (icon to display).
+ *
+ * @param title title text
+ * @param typeId type (icon) ID
+ */
+ public PropertyPanel(String title, String typeId) {
+ this.title = title;
+ this.typeId = typeId;
+ }
+
+ /**
+ * Adds an ID field to the panel data, to be included in
+ * the returned JSON data to the client.
+ *
+ * @param id the identifier
+ * @return self, for chaining
+ */
+ public PropertyPanel id(String id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * Adds a property to the panel data.
+ *
+ * @param key property key
+ * @param value property value
+ * @return self, for chaining
+ */
+ public PropertyPanel addProp(String key, String value) {
+ properties.add(new Prop(key, value));
+ return this;
+ }
+
+ /**
+ * Adds a property to the panel data, using a decimal formatter.
+ *
+ * @param key property key
+ * @param value property value
+ * @return self, for chaining
+ */
+ public PropertyPanel addProp(String key, int value) {
+ properties.add(new Prop(key, DF0.format(value)));
+ return this;
+ }
+
+ /**
+ * Adds a property to the panel data, using a decimal formatter.
+ *
+ * @param key property key
+ * @param value property value
+ * @return self, for chaining
+ */
+ public PropertyPanel addProp(String key, long value) {
+ properties.add(new Prop(key, DF0.format(value)));
+ return this;
+ }
+
+ /**
+ * Adds a property to the panel data. Note that the value's
+ * {@link Object#toString toString()} method is used to convert the
+ * value to a string.
+ *
+ * @param key property key
+ * @param value property value
+ * @return self, for chaining
+ */
+ public PropertyPanel addProp(String key, Object value) {
+ properties.add(new Prop(key, value.toString()));
+ return this;
+ }
+
+ /**
+ * Adds a property to the panel data. Note that the value's
+ * {@link Object#toString toString()} method is used to convert the
+ * value to a string, from which the characters defined in the given
+ * regular expression string are stripped.
+ *
+ * @param key property key
+ * @param value property value
+ * @param reStrip regexp characters to strip from value string
+ * @return self, for chaining
+ */
+ public PropertyPanel addProp(String key, Object value, String reStrip) {
+ String val = value.toString().replaceAll(reStrip, "");
+ properties.add(new Prop(key, val));
+ return this;
+ }
+
+ /**
+ * Adds a separator to the panel data.
+ *
+ * @return self, for chaining
+ */
+ public PropertyPanel addSeparator() {
+ properties.add(new Separator());
+ return this;
+ }
+
+ /**
+ * Returns the title text.
+ *
+ * @return title text
+ */
+ public String title() {
+ return title;
+ }
+
+ /**
+ * Returns the type identifier.
+ *
+ * @return type identifier
+ */
+ public String typeId() {
+ return typeId;
+ }
+
+ /**
+ * Returns the internal ID.
+ *
+ * @return the ID
+ */
+ public String id() {
+ return id;
+ }
+
+ /**
+ * Returns the list of properties to be displayed.
+ *
+ * @return the property list
+ */
+ // TODO: consider protecting this?
+ public List<Prop> properties() {
+ return properties;
+ }
+
+ /**
+ * Returns the list of button descriptors.
+ *
+ * @return the button list
+ */
+ // TODO: consider protecting this?
+ public List<ButtonId> buttons() {
+ return buttons;
+ }
+
+ // == MUTATORS
+
+ /**
+ * Sets the title text.
+ *
+ * @param title title text
+ * @return self, for chaining
+ */
+ public PropertyPanel title(String title) {
+ this.title = title;
+ return this;
+ }
+
+ /**
+ * Sets the type identifier (icon ID).
+ *
+ * @param typeId type identifier
+ * @return self, for chaining
+ */
+ public PropertyPanel typeId(String typeId) {
+ this.typeId = typeId;
+ return this;
+ }
+
+ /**
+ * Removes properties with the given keys from the list.
+ *
+ * @param keys keys of properties to remove
+ * @return self, for chaining
+ */
+ public PropertyPanel removeProps(String... keys) {
+ Set<String> forRemoval = Sets.newHashSet(keys);
+ List<Prop> toKeep = new ArrayList<>();
+ for (Prop p: properties) {
+ if (!forRemoval.contains(p.key())) {
+ toKeep.add(p);
+ }
+ }
+ properties = toKeep;
+ return this;
+ }
+
+ /**
+ * Removes all currently defined properties.
+ *
+ * @return self, for chaining
+ */
+ public PropertyPanel removeAllProps() {
+ properties.clear();
+ return this;
+ }
+
+ /**
+ * Adds the given button descriptor to the panel data.
+ *
+ * @param button button descriptor
+ * @return self, for chaining
+ */
+ public PropertyPanel addButton(ButtonId button) {
+ buttons.add(button);
+ return this;
+ }
+
+ /**
+ * Removes buttons with the given descriptors from the list.
+ *
+ * @param descriptors descriptors to remove
+ * @return self, for chaining
+ */
+ public PropertyPanel removeButtons(ButtonId... descriptors) {
+ Set<ButtonId> forRemoval = Sets.newHashSet(descriptors);
+ List<ButtonId> toKeep = new ArrayList<>();
+ for (ButtonId bd: buttons) {
+ if (!forRemoval.contains(bd)) {
+ toKeep.add(bd);
+ }
+ }
+ buttons = toKeep;
+ return this;
+ }
+
+ /**
+ * Removes all currently defined buttons.
+ *
+ * @return self, for chaining
+ */
+ public PropertyPanel removeAllButtons() {
+ buttons.clear();
+ return this;
+ }
+
+ // ====================
+
+
+ /**
+ * Simple data carrier for a property, composed of a key/value pair.
+ */
+ public static class Prop {
+ private final String key;
+ private final String value;
+
+ /**
+ * Constructs a property data value.
+ *
+ * @param key property key
+ * @param value property value
+ */
+ public Prop(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ /**
+ * Returns the property's key.
+ *
+ * @return the key
+ */
+ public String key() {
+ return key;
+ }
+
+ /**
+ * Returns the property's value.
+ *
+ * @return the value
+ */
+ public String value() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Prop prop = (Prop) o;
+ return key.equals(prop.key) && value.equals(prop.value);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = key.hashCode();
+ result = 31 * result + value.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "{" + key + " -> " + value + "}";
+ }
+ }
+
+ /**
+ * Auxiliary class representing a separator property.
+ */
+ public static class Separator extends Prop {
+ public Separator() {
+ super("-", "");
+ }
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoConstants.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoConstants.java
new file mode 100644
index 00000000..38a8f036
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoConstants.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+/**
+ * Defines string constants used in the Topology View of the ONOS GUI.
+ * <p>
+ * See also:
+ * <ul>
+ * <li> https://wiki.onosproject.org/display/ONOS/UI+Service+-+GlyphService </li>
+ * </ul>
+ */
+public final class TopoConstants {
+
+ /**
+ * Defines constants for standard glyph identifiers.
+ */
+ public static final class Glyphs {
+ public static final String UNKNOWN = "unknown";
+ public static final String BIRD = "bird";
+ public static final String NODE = "node";
+ public static final String SWITCH = "switch";
+ public static final String ROADM = "roadm";
+ public static final String ENDSTATION = "endstation";
+ public static final String ROUTER = "router";
+ public static final String BGP_SPEAKER = "bgpSpeaker";
+ public static final String CHAIN = "chain";
+ public static final String CROWN = "crown";
+ public static final String TOPO = "topo";
+ public static final String REFRESH = "refresh";
+ public static final String GARBAGE = "garbage";
+ public static final String FLOW_TABLE = "flowTable";
+ public static final String PORT_TABLE = "portTable";
+ public static final String GROUP_TABLE = "groupTable";
+ public static final String SUMMARY = "summary";
+ public static final String DETAILS = "details";
+ public static final String PORTS = "ports";
+ public static final String MAP = "map";
+ public static final String CYCLE_LABELS = "cycleLabels";
+ public static final String OBLIQUE = "oblique";
+ public static final String FILTERS = "filters";
+ public static final String RESET_ZOOM = "resetZoom";
+ public static final String RELATED_INTENTS = "relatedIntents";
+ public static final String NEXT_INTENT = "nextIntent";
+ public static final String PREV_INTENT = "prevIntent";
+ public static final String INTENT_TRAFFIC = "intentTraffic";
+ public static final String ALL_TRAFFIC = "allTraffic";
+ public static final String FLOWS = "flows";
+ public static final String EQ_MASTER = "eqMaster";
+ public static final String UI_ATTACHED = "uiAttached";
+ public static final String CHECK_MARK = "checkMark";
+ public static final String X_MARK = "xMark";
+ public static final String TRIANGLE_UP = "triangleUp";
+ public static final String TRIANGLE_DOWN = "triangleDown";
+ public static final String PLUS = "plus";
+ public static final String MINUS = "minus";
+ public static final String PLAY = "play";
+ public static final String STOP = "stop";
+ public static final String CLOUD = "cloud";
+ }
+
+ /**
+ * Defines constants for property names on the default summary and
+ * details panels.
+ */
+ public static final class Properties {
+ public static final String SEPARATOR = "-";
+
+ // summary panel
+ public static final String DEVICES = "Devices";
+ public static final String LINKS = "Links";
+ public static final String HOSTS = "Hosts";
+ public static final String TOPOLOGY_SSCS = "Topology SCCs";
+ public static final String INTENTS = "Intents";
+ public static final String TUNNELS = "Tunnels";
+ public static final String FLOWS = "Flows";
+ public static final String VERSION = "Version";
+
+ // device details
+ public static final String URI = "URI";
+ public static final String VENDOR = "Vendor";
+ public static final String HW_VERSION = "H/W Version";
+ public static final String SW_VERSION = "S/W Version";
+ public static final String SERIAL_NUMBER = "Serial Number";
+ public static final String PROTOCOL = "Protocol";
+ public static final String LATITUDE = "Latitude";
+ public static final String LONGITUDE = "Longitude";
+ public static final String PORTS = "Ports";
+
+ // host details
+ public static final String MAC = "MAC";
+ public static final String IP = "IP";
+ public static final String VLAN = "VLAN";
+ }
+
+ /**
+ * Defines identities of core buttons that appear on the topology
+ * details panel.
+ */
+ public static final class CoreButtons {
+ public static final ButtonId SHOW_DEVICE_VIEW =
+ new ButtonId("showDeviceView");
+
+ public static final ButtonId SHOW_FLOW_VIEW =
+ new ButtonId("showFlowView");
+
+ public static final ButtonId SHOW_PORT_VIEW =
+ new ButtonId("showPortView");
+
+ public static final ButtonId SHOW_GROUP_VIEW =
+ new ButtonId("showGroupView");
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoElementType.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoElementType.java
new file mode 100644
index 00000000..dc327464
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoElementType.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+/**
+ * The topology element types to which a highlight can be applied.
+ */
+public enum TopoElementType {
+ DEVICE, HOST, LINK
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java
new file mode 100644
index 00000000..a94068ee
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.onosproject.ui.JsonUtils.envelope;
+
+/**
+ * JSON utilities for the Topology View.
+ */
+public final class TopoJson {
+ // package-private for unit test access
+ static final String SHOW_HIGHLIGHTS = "showHighlights";
+
+ static final String DEVICES = "devices";
+ static final String HOSTS = "hosts";
+ static final String LINKS = "links";
+ static final String SUBDUE = "subdue";
+
+ static final String ID = "id";
+ static final String LABEL = "label";
+ static final String CSS = "css";
+
+ static final String TITLE = "title";
+ static final String TYPE = "type";
+ static final String PROP_ORDER = "propOrder";
+ static final String PROPS = "props";
+ static final String BUTTONS = "buttons";
+
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private static ObjectNode objectNode() {
+ return MAPPER.createObjectNode();
+ }
+
+ private static ArrayNode arrayNode() {
+ return MAPPER.createArrayNode();
+ }
+
+ // non-instantiable
+ private TopoJson() { }
+
+ /**
+ * Returns a formatted message ready to send to the topology view
+ * to render highlights.
+ *
+ * @param highlights highlights model to transform
+ * @return fully formatted "show highlights" message
+ */
+ public static ObjectNode highlightsMessage(Highlights highlights) {
+ return envelope(SHOW_HIGHLIGHTS, json(highlights));
+ }
+
+ /**
+ * Transforms the given highlights model into a JSON message payload.
+ *
+ * @param highlights the model to transform
+ * @return JSON payload
+ */
+ public static ObjectNode json(Highlights highlights) {
+ ObjectNode payload = objectNode();
+
+ ArrayNode devices = arrayNode();
+ ArrayNode hosts = arrayNode();
+ ArrayNode links = arrayNode();
+
+ payload.set(DEVICES, devices);
+ payload.set(HOSTS, hosts);
+ payload.set(LINKS, links);
+
+ highlights.devices().forEach(dh -> devices.add(json(dh)));
+ highlights.hosts().forEach(hh -> hosts.add(json(hh)));
+ highlights.links().forEach(lh -> links.add(json(lh)));
+
+ Highlights.Amount toSubdue = highlights.subdueLevel();
+ if (!toSubdue.equals(Highlights.Amount.ZERO)) {
+ payload.put(SUBDUE, toSubdue.toString());
+ }
+ return payload;
+ }
+
+ private static ObjectNode json(DeviceHighlight dh) {
+ ObjectNode n = objectNode()
+ .put(ID, dh.elementId());
+ if (dh.subdued()) {
+ n.put(SUBDUE, true);
+ }
+ return n;
+ }
+
+ private static ObjectNode json(HostHighlight hh) {
+ ObjectNode n = objectNode()
+ .put(ID, hh.elementId());
+ if (hh.subdued()) {
+ n.put(SUBDUE, true);
+ }
+ return n;
+ }
+
+ private static ObjectNode json(LinkHighlight lh) {
+ ObjectNode n = objectNode()
+ .put(ID, lh.elementId())
+ .put(LABEL, lh.label())
+ .put(CSS, lh.cssClasses());
+ if (lh.subdued()) {
+ n.put(SUBDUE, true);
+ }
+ return n;
+ }
+
+ /**
+ * Translates the given property panel into JSON, for returning
+ * to the client.
+ *
+ * @param pp the property panel model
+ * @return JSON payload
+ */
+ public static ObjectNode json(PropertyPanel pp) {
+ ObjectNode result = objectNode()
+ .put(TITLE, pp.title())
+ .put(TYPE, pp.typeId())
+ .put(ID, pp.id());
+
+ ObjectNode pnode = objectNode();
+ ArrayNode porder = arrayNode();
+ for (PropertyPanel.Prop p : pp.properties()) {
+ porder.add(p.key());
+ pnode.put(p.key(), p.value());
+ }
+ result.set(PROP_ORDER, porder);
+ result.set(PROPS, pnode);
+
+ ArrayNode buttons = arrayNode();
+ for (ButtonId b : pp.buttons()) {
+ buttons.add(b.id());
+ }
+ result.set(BUTTONS, buttons);
+ return result;
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoUtils.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoUtils.java
new file mode 100644
index 00000000..f92d5798
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoUtils.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onosproject.ui.topo;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+
+import java.text.DecimalFormat;
+
+import static org.onosproject.net.LinkKey.linkKey;
+
+/**
+ * Utility methods for helping out with formatting data for the Topology View
+ * in the web client.
+ */
+public final class TopoUtils {
+
+ // explicit decision made to not 'javadoc' these self explanatory constants
+ public static final double KILO = 1024;
+ public static final double MEGA = 1024 * KILO;
+ public static final double GIGA = 1024 * MEGA;
+
+ public static final String GBITS_UNIT = "Gb";
+ public static final String MBITS_UNIT = "Mb";
+ public static final String KBITS_UNIT = "Kb";
+ public static final String BITS_UNIT = "b";
+ public static final String GBYTES_UNIT = "GB";
+ public static final String MBYTES_UNIT = "MB";
+ public static final String KBYTES_UNIT = "KB";
+ public static final String BYTES_UNIT = "B";
+
+
+ private static final DecimalFormat DF2 = new DecimalFormat("#,###.##");
+
+ private static final String COMPACT = "%s/%s-%s/%s";
+ private static final String EMPTY = "";
+ private static final String SPACE = " ";
+ private static final String PER_SEC = "ps";
+ private static final String FLOW = "flow";
+ private static final String FLOWS = "flows";
+
+ // non-instantiable
+ private TopoUtils() { }
+
+ /**
+ * Returns a compact identity for the given link, in the form
+ * used to identify links in the Topology View on the client.
+ *
+ * @param link link
+ * @return compact link identity
+ */
+ public static String compactLinkString(Link link) {
+ return String.format(COMPACT, link.src().elementId(), link.src().port(),
+ link.dst().elementId(), link.dst().port());
+ }
+
+ /**
+ * Produces a canonical link key, that is, one that will match both a link
+ * and its inverse.
+ *
+ * @param link the link
+ * @return canonical key
+ */
+ public static LinkKey canonicalLinkKey(Link link) {
+ String sn = link.src().elementId().toString();
+ String dn = link.dst().elementId().toString();
+ return sn.compareTo(dn) < 0 ?
+ linkKey(link.src(), link.dst()) : linkKey(link.dst(), link.src());
+ }
+
+ /**
+ * Returns human readable count of bytes, to be displayed as a label.
+ *
+ * @param bytes number of bytes
+ * @return formatted byte count
+ */
+ public static String formatBytes(long bytes) {
+ String unit;
+ double value;
+ if (bytes > GIGA) {
+ value = bytes / GIGA;
+ unit = GBYTES_UNIT;
+ } else if (bytes > MEGA) {
+ value = bytes / MEGA;
+ unit = MBYTES_UNIT;
+ } else if (bytes > KILO) {
+ value = bytes / KILO;
+ unit = KBYTES_UNIT;
+ } else {
+ value = bytes;
+ unit = BYTES_UNIT;
+ }
+ return DF2.format(value) + SPACE + unit;
+ }
+
+ /**
+ * Returns human readable bit rate, to be displayed as a label.
+ *
+ * @param bytes bytes per second
+ * @return formatted bits per second
+ */
+ public static String formatBitRate(long bytes) {
+ String unit;
+ double value;
+
+ //Convert to bits
+ long bits = bytes * 8;
+ if (bits > GIGA) {
+ value = bits / GIGA;
+ unit = GBITS_UNIT;
+
+ // NOTE: temporary hack to clip rate at 10.0 Gbps
+ // Added for the CORD Fabric demo at ONS 2015
+ // TODO: provide a more elegant solution to this issue
+ if (value > 10.0) {
+ value = 10.0;
+ }
+
+ } else if (bits > MEGA) {
+ value = bits / MEGA;
+ unit = MBITS_UNIT;
+ } else if (bits > KILO) {
+ value = bits / KILO;
+ unit = KBITS_UNIT;
+ } else {
+ value = bits;
+ unit = BITS_UNIT;
+ }
+ return DF2.format(value) + SPACE + unit + PER_SEC;
+ }
+
+ /**
+ * Returns human readable flow count, to be displayed as a label.
+ *
+ * @param flows number of flows
+ * @return formatted flow count
+ */
+ public static String formatFlows(long flows) {
+ if (flows < 1) {
+ return EMPTY;
+ }
+ return String.valueOf(flows) + SPACE + (flows > 1 ? FLOWS : FLOW);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/package-info.java
new file mode 100644
index 00000000..85ac7fea
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Mechanism for dynamically extending topology view with information and
+ * behaviour overlays.
+ */
+package org.onosproject.ui.topo; \ No newline at end of file