alshabib

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

Showing 96 changed files with 3271 additions and 780 deletions
...@@ -184,13 +184,13 @@ public class ReactiveForwarding { ...@@ -184,13 +184,13 @@ public class ReactiveForwarding {
184 184
185 // Install the flow rule to handle this type of message from now on. 185 // Install the flow rule to handle this type of message from now on.
186 Ethernet inPkt = context.inPacket().parsed(); 186 Ethernet inPkt = context.inPacket().parsed();
187 - TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder(); 187 + TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
188 builder.matchEthType(inPkt.getEtherType()) 188 builder.matchEthType(inPkt.getEtherType())
189 .matchEthSrc(inPkt.getSourceMAC()) 189 .matchEthSrc(inPkt.getSourceMAC())
190 .matchEthDst(inPkt.getDestinationMAC()) 190 .matchEthDst(inPkt.getDestinationMAC())
191 .matchInport(context.inPacket().receivedFrom().port()); 191 .matchInport(context.inPacket().receivedFrom().port());
192 192
193 - TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder(); 193 + TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
194 treat.setOutput(portNumber); 194 treat.setOutput(portNumber);
195 195
196 FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(), 196 FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(),
......
1 +package org.onlab.onos.cli.net;
2 +
3 +import org.apache.karaf.shell.commands.Argument;
4 +import org.apache.karaf.shell.commands.Command;
5 +import org.onlab.onos.cli.AbstractShellCommand;
6 +import org.onlab.onos.net.HostId;
7 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
8 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
9 +import org.onlab.onos.net.flow.TrafficSelector;
10 +import org.onlab.onos.net.flow.TrafficTreatment;
11 +import org.onlab.onos.net.host.HostService;
12 +import org.onlab.onos.net.intent.HostToHostIntent;
13 +import org.onlab.onos.net.intent.IntentId;
14 +import org.onlab.onos.net.intent.IntentService;
15 +
16 +/**
17 + * Lists all shortest-paths paths between the specified source and
18 + * destination devices.
19 + */
20 +@Command(scope = "onos", name = "add-intent",
21 + description = "Installs HostToHostIntent between the specified source and destination devices")
22 +public class IntentInstallCommand extends AbstractShellCommand {
23 +
24 + @Argument(index = 0, name = "src", description = "Source device ID",
25 + required = true, multiValued = false)
26 + String src = null;
27 +
28 + @Argument(index = 1, name = "dst", description = "Destination device ID",
29 + required = true, multiValued = false)
30 + String dst = null;
31 +
32 + private static long id = 1;
33 +
34 + @Override
35 + protected void execute() {
36 + IntentService service = get(IntentService.class);
37 + HostService hosts = get(HostService.class);
38 +
39 + HostId srcId = HostId.hostId(src);
40 + HostId dstId = HostId.hostId(dst);
41 +
42 + TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
43 + builder.matchEthSrc(hosts.getHost(srcId).mac())
44 + .matchEthDst(hosts.getHost(dstId).mac());
45 +
46 + TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
47 +
48 + HostToHostIntent intent =
49 + new HostToHostIntent(new IntentId(id++), srcId, dstId,
50 + builder.build(), treat.build());
51 +
52 + log.info("Adding intent {}", intent);
53 +
54 + service.submit(intent);
55 + }
56 +
57 +}
...@@ -57,6 +57,13 @@ ...@@ -57,6 +57,13 @@
57 </completers> 57 </completers>
58 </command> 58 </command>
59 <command> 59 <command>
60 + <action class="org.onlab.onos.cli.net.IntentInstallCommand"/>
61 + <completers>
62 + <ref component-id="hostIdCompleter"/>
63 + </completers>
64 + </command>
65 +
66 + <command>
60 <action class="org.onlab.onos.cli.net.ClustersListCommand"/> 67 <action class="org.onlab.onos.cli.net.ClustersListCommand"/>
61 </command> 68 </command>
62 <command> 69 <command>
......
...@@ -18,9 +18,9 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink { ...@@ -18,9 +18,9 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink {
18 * @param providerId provider identity 18 * @param providerId provider identity
19 * @param hostPoint host-side connection point 19 * @param hostPoint host-side connection point
20 * @param hostLocation location where host attaches to the network 20 * @param hostLocation location where host attaches to the network
21 - * @param isIngress true to indicated host-to-network direction; false 21 + * @param isIngress true to indicate host-to-network direction; false
22 * for network-to-host direction 22 * for network-to-host direction
23 - * @param annotations optional key/value annotations 23 + * @param annotations optional key/value annotations
24 */ 24 */
25 public DefaultEdgeLink(ProviderId providerId, ConnectPoint hostPoint, 25 public DefaultEdgeLink(ProviderId providerId, ConnectPoint hostPoint,
26 HostLocation hostLocation, boolean isIngress, 26 HostLocation hostLocation, boolean isIngress,
...@@ -42,4 +42,20 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink { ...@@ -42,4 +42,20 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink {
42 public HostLocation hostLocation() { 42 public HostLocation hostLocation() {
43 return hostLocation; 43 return hostLocation;
44 } 44 }
45 +
46 + /**
47 + * Creates a phantom edge link, to an unspecified end-station. This link
48 + * does not represent any actually discovered link stored in the system.
49 + *
50 + * @param edgePort network edge port
51 + * @param isIngress true to indicate host-to-network direction; false
52 + * for network-to-host direction
53 + * @return new phantom edge link
54 + */
55 + public static DefaultEdgeLink createEdgeLink(HostLocation edgePort,
56 + boolean isIngress) {
57 + return new DefaultEdgeLink(ProviderId.NONE,
58 + new ConnectPoint(HostId.NONE, PortNumber.P0),
59 + edgePort, isIngress);
60 + }
45 } 61 }
......
...@@ -10,6 +10,14 @@ import java.net.URI; ...@@ -10,6 +10,14 @@ import java.net.URI;
10 */ 10 */
11 public final class HostId extends ElementId { 11 public final class HostId extends ElementId {
12 12
13 + private static final String NIC = "nic";
14 +
15 + /**
16 + * Represents either no host, or an unspecified host; used for creating
17 + * open ingress/egress edge links.
18 + */
19 + public static final HostId NONE = hostId(NIC + ":none-0");
20 +
13 // Public construction is prohibited 21 // Public construction is prohibited
14 private HostId(URI uri) { 22 private HostId(URI uri) {
15 super(uri); 23 super(uri);
...@@ -43,8 +51,7 @@ public final class HostId extends ElementId { ...@@ -43,8 +51,7 @@ public final class HostId extends ElementId {
43 * @return host identifier 51 * @return host identifier
44 */ 52 */
45 public static HostId hostId(MacAddress mac, VlanId vlanId) { 53 public static HostId hostId(MacAddress mac, VlanId vlanId) {
46 - // FIXME: use more efficient means of encoding 54 + return hostId(NIC + ":" + mac + "-" + vlanId);
47 - return hostId("nic" + ":" + mac + "-" + vlanId);
48 } 55 }
49 56
50 /** 57 /**
......
...@@ -9,6 +9,8 @@ import com.google.common.primitives.UnsignedLongs; ...@@ -9,6 +9,8 @@ import com.google.common.primitives.UnsignedLongs;
9 */ 9 */
10 public final class PortNumber { 10 public final class PortNumber {
11 11
12 + public static final PortNumber P0 = portNumber(0);
13 +
12 // TODO: revisit the max and the logical port value assignments 14 // TODO: revisit the max and the logical port value assignments
13 15
14 private static final long MAX_NUMBER = (2L * Integer.MAX_VALUE) + 1; 16 private static final long MAX_NUMBER = (2L * Integer.MAX_VALUE) + 1;
......
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 -import static org.slf4j.LoggerFactory.getLogger; 3 +import com.google.common.collect.ImmutableSet;
4 -
5 -import java.util.Collections;
6 -import java.util.HashSet;
7 -import java.util.Objects;
8 -import java.util.Set;
9 -
10 import org.onlab.onos.net.PortNumber; 4 import org.onlab.onos.net.PortNumber;
11 import org.onlab.onos.net.flow.criteria.Criteria; 5 import org.onlab.onos.net.flow.criteria.Criteria;
12 import org.onlab.onos.net.flow.criteria.Criterion; 6 import org.onlab.onos.net.flow.criteria.Criterion;
13 import org.onlab.packet.IpPrefix; 7 import org.onlab.packet.IpPrefix;
14 import org.onlab.packet.MacAddress; 8 import org.onlab.packet.MacAddress;
15 import org.onlab.packet.VlanId; 9 import org.onlab.packet.VlanId;
16 -import org.slf4j.Logger;
17 10
11 +import java.util.Collections;
12 +import java.util.HashMap;
13 +import java.util.Map;
14 +import java.util.Objects;
15 +import java.util.Set;
16 +
17 +/**
18 + * Default traffic selector implementation.
19 + */
18 public final class DefaultTrafficSelector implements TrafficSelector { 20 public final class DefaultTrafficSelector implements TrafficSelector {
19 21
20 - private final Set<Criterion> selector; 22 + private final Set<Criterion> criteria;
21 23
22 - private DefaultTrafficSelector(Set<Criterion> selector) { 24 + /**
23 - this.selector = Collections.unmodifiableSet(selector); 25 + * Creates a new traffic selector with the specified criteria.
26 + *
27 + * @param criteria criteria
28 + */
29 + private DefaultTrafficSelector(Set<Criterion> criteria) {
30 + this.criteria = Collections.unmodifiableSet(criteria);
24 } 31 }
25 32
26 @Override 33 @Override
27 public Set<Criterion> criteria() { 34 public Set<Criterion> criteria() {
28 - return selector; 35 + return criteria;
29 } 36 }
30 37
31 @Override 38 @Override
32 public int hashCode() { 39 public int hashCode() {
33 - return Objects.hash(selector); 40 + return Objects.hash(criteria);
34 } 41 }
35 42
36 @Override 43 @Override
...@@ -40,23 +47,50 @@ public final class DefaultTrafficSelector implements TrafficSelector { ...@@ -40,23 +47,50 @@ public final class DefaultTrafficSelector implements TrafficSelector {
40 } 47 }
41 if (obj instanceof DefaultTrafficSelector) { 48 if (obj instanceof DefaultTrafficSelector) {
42 DefaultTrafficSelector that = (DefaultTrafficSelector) obj; 49 DefaultTrafficSelector that = (DefaultTrafficSelector) obj;
43 - return Objects.equals(selector, that.selector); 50 + return Objects.equals(criteria, that.criteria);
44 51
45 } 52 }
46 return false; 53 return false;
47 } 54 }
48 55
56 + /**
57 + * Returns a new traffic selector builder.
58 + *
59 + * @return traffic selector builder
60 + */
61 + public static TrafficSelector.Builder builder() {
62 + return new Builder();
63 + }
49 64
65 + /**
66 + * Returns a new traffic selector builder primed to produce entities
67 + * patterned after the supplied selector.
68 + *
69 + * @return traffic selector builder
70 + */
71 + public static TrafficSelector.Builder builder(TrafficSelector selector) {
72 + return new Builder(selector);
73 + }
50 74
51 - public static class Builder implements TrafficSelector.Builder { 75 + /**
76 + * Builder of traffic selector entities.
77 + */
78 + public static final class Builder implements TrafficSelector.Builder {
52 79
53 - private final Logger log = getLogger(getClass()); 80 + private final Map<Criterion.Type, Criterion> selector = new HashMap<>();
54 81
55 - private final Set<Criterion> selector = new HashSet<>(); 82 + private Builder() {
83 + }
84 +
85 + private Builder(TrafficSelector selector) {
86 + for (Criterion c : selector.criteria()) {
87 + add(c);
88 + }
89 + }
56 90
57 @Override 91 @Override
58 public Builder add(Criterion criterion) { 92 public Builder add(Criterion criterion) {
59 - selector.add(criterion); 93 + selector.put(criterion.type(), criterion);
60 return this; 94 return this;
61 } 95 }
62 96
...@@ -107,7 +141,7 @@ public final class DefaultTrafficSelector implements TrafficSelector { ...@@ -107,7 +141,7 @@ public final class DefaultTrafficSelector implements TrafficSelector {
107 141
108 @Override 142 @Override
109 public TrafficSelector build() { 143 public TrafficSelector build() {
110 - return new DefaultTrafficSelector(selector); 144 + return new DefaultTrafficSelector(ImmutableSet.copyOf(selector.values()));
111 } 145 }
112 146
113 } 147 }
......
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 -import static org.slf4j.LoggerFactory.getLogger;
4 -
5 -import java.util.Collections;
6 -import java.util.LinkedList;
7 -import java.util.List;
8 -
9 import org.onlab.onos.net.PortNumber; 3 import org.onlab.onos.net.PortNumber;
10 import org.onlab.onos.net.flow.instructions.Instruction; 4 import org.onlab.onos.net.flow.instructions.Instruction;
11 import org.onlab.onos.net.flow.instructions.Instructions; 5 import org.onlab.onos.net.flow.instructions.Instructions;
...@@ -14,10 +8,24 @@ import org.onlab.packet.MacAddress; ...@@ -14,10 +8,24 @@ import org.onlab.packet.MacAddress;
14 import org.onlab.packet.VlanId; 8 import org.onlab.packet.VlanId;
15 import org.slf4j.Logger; 9 import org.slf4j.Logger;
16 10
11 +import java.util.Collections;
12 +import java.util.LinkedList;
13 +import java.util.List;
14 +
15 +import static org.slf4j.LoggerFactory.getLogger;
16 +
17 +/**
18 + * Default traffic treatment implementation.
19 + */
17 public final class DefaultTrafficTreatment implements TrafficTreatment { 20 public final class DefaultTrafficTreatment implements TrafficTreatment {
18 21
19 private final List<Instruction> instructions; 22 private final List<Instruction> instructions;
20 23
24 + /**
25 + * Creates a new traffic treatment from the specified list of instructions.
26 + *
27 + * @param instructions treatment instructions
28 + */
21 private DefaultTrafficTreatment(List<Instruction> instructions) { 29 private DefaultTrafficTreatment(List<Instruction> instructions) {
22 this.instructions = Collections.unmodifiableList(instructions); 30 this.instructions = Collections.unmodifiableList(instructions);
23 } 31 }
...@@ -28,12 +36,19 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -28,12 +36,19 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
28 } 36 }
29 37
30 /** 38 /**
31 - * Builds a list of treatments following the following order. 39 + * Returns a new traffic treatment builder.
32 - * Modifications -> Group -> Output (including drop)
33 * 40 *
41 + * @return traffic treatment builder
34 */ 42 */
43 + public static TrafficTreatment.Builder builder() {
44 + return new Builder();
45 + }
35 46
36 - public static class Builder implements TrafficTreatment.Builder { 47 + /**
48 + * Builds a list of treatments following the following order.
49 + * Modifications -> Group -> Output (including drop)
50 + */
51 + public static final class Builder implements TrafficTreatment.Builder {
37 52
38 private final Logger log = getLogger(getClass()); 53 private final Logger log = getLogger(getClass());
39 54
...@@ -47,27 +62,31 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -47,27 +62,31 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
47 // TODO: should be a list of instructions based on modification objects 62 // TODO: should be a list of instructions based on modification objects
48 List<Instruction> modifications = new LinkedList<>(); 63 List<Instruction> modifications = new LinkedList<>();
49 64
65 + // Creates a new builder
66 + private Builder() {
67 + }
68 +
50 public Builder add(Instruction instruction) { 69 public Builder add(Instruction instruction) {
51 if (drop) { 70 if (drop) {
52 return this; 71 return this;
53 } 72 }
54 switch (instruction.type()) { 73 switch (instruction.type()) {
55 - case DROP: 74 + case DROP:
56 - drop = true; 75 + drop = true;
57 - break; 76 + break;
58 - case OUTPUT: 77 + case OUTPUT:
59 - outputs.add(instruction); 78 + outputs.add(instruction);
60 - break; 79 + break;
61 - case L2MODIFICATION: 80 + case L2MODIFICATION:
62 - case L3MODIFICATION: 81 + case L3MODIFICATION:
63 - // TODO: enforce modification order if any 82 + // TODO: enforce modification order if any
64 - modifications.add(instruction); 83 + modifications.add(instruction);
65 - break; 84 + break;
66 - case GROUP: 85 + case GROUP:
67 - groups.add(instruction); 86 + groups.add(instruction);
68 - break; 87 + break;
69 - default: 88 + default:
70 - log.warn("Unknown instruction type {}", instruction.type()); 89 + log.warn("Unknown instruction type {}", instruction.type());
71 } 90 }
72 return this; 91 return this;
73 } 92 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 //TODO is this the right package? 2 //TODO is this the right package?
3 3
4 -import static com.google.common.base.Preconditions.checkNotNull;
5 -
6 import java.util.Collections; 4 import java.util.Collections;
7 import java.util.LinkedList; 5 import java.util.LinkedList;
8 import java.util.List; 6 import java.util.List;
9 7
8 +import static com.google.common.base.Preconditions.checkNotNull;
9 +
10 /** 10 /**
11 * A list of BatchOperationEntry. 11 * A list of BatchOperationEntry.
12 * 12 *
13 * @param <T> the enum of operators <br> 13 * @param <T> the enum of operators <br>
14 - * This enum must be defined in each sub-classes. 14 + * This enum must be defined in each sub-classes.
15 - *
16 */ 15 */
17 public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> { 16 public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> {
17 +
18 private List<T> ops; 18 private List<T> ops;
19 19
20 /** 20 /**
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import static com.google.common.base.Preconditions.checkNotNull; 3 +import com.google.common.base.Objects;
4 -
5 import org.onlab.onos.net.flow.TrafficSelector; 4 import org.onlab.onos.net.flow.TrafficSelector;
6 import org.onlab.onos.net.flow.TrafficTreatment; 5 import org.onlab.onos.net.flow.TrafficTreatment;
7 6
8 -import com.google.common.base.Objects; 7 +import static com.google.common.base.Preconditions.checkNotNull;
9 8
10 /** 9 /**
11 * Abstraction of connectivity intent for traffic matching some criteria. 10 * Abstraction of connectivity intent for traffic matching some criteria.
...@@ -26,17 +25,18 @@ public abstract class ConnectivityIntent extends AbstractIntent { ...@@ -26,17 +25,18 @@ public abstract class ConnectivityIntent extends AbstractIntent {
26 25
27 /** 26 /**
28 * Creates a connectivity intent that matches on the specified intent 27 * Creates a connectivity intent that matches on the specified intent
29 - * and applies the specified action. 28 + * and applies the specified treatement.
30 * 29 *
31 - * @param id intent identifier 30 + * @param intentId intent identifier
32 - * @param match traffic match 31 + * @param selector traffic selector
33 - * @param action action 32 + * @param treatement treatement
34 - * @throws NullPointerException if the match or action is null 33 + * @throws NullPointerException if the selector or treatement is null
35 */ 34 */
36 - protected ConnectivityIntent(IntentId id, TrafficSelector match, TrafficTreatment action) { 35 + protected ConnectivityIntent(IntentId intentId, TrafficSelector selector,
37 - super(id); 36 + TrafficTreatment treatement) {
38 - this.selector = checkNotNull(match); 37 + super(intentId);
39 - this.treatment = checkNotNull(action); 38 + this.selector = checkNotNull(selector);
39 + this.treatment = checkNotNull(treatement);
40 } 40 }
41 41
42 /** 42 /**
......
1 +package org.onlab.onos.net.intent;
2 +
3 +import com.google.common.base.MoreObjects;
4 +import org.onlab.onos.net.HostId;
5 +import org.onlab.onos.net.flow.TrafficSelector;
6 +import org.onlab.onos.net.flow.TrafficTreatment;
7 +
8 +import java.util.Objects;
9 +
10 +import static com.google.common.base.Preconditions.checkNotNull;
11 +
12 +/**
13 + * Abstraction of end-station to end-station connectivity.
14 + */
15 +public class HostToHostIntent extends ConnectivityIntent {
16 +
17 + private final HostId src;
18 + private final HostId dst;
19 +
20 + /**
21 + * Creates a new point-to-point intent with the supplied ingress/egress
22 + * ports.
23 + *
24 + * @param intentId intent identifier
25 + * @param selector action
26 + * @param treatment ingress port
27 + * @throws NullPointerException if {@code ingressPort} or {@code egressPort}
28 + * is null.
29 + */
30 + public HostToHostIntent(IntentId intentId, HostId src, HostId dst,
31 + TrafficSelector selector, TrafficTreatment treatment) {
32 + super(intentId, selector, treatment);
33 + this.src = checkNotNull(src);
34 + this.dst = checkNotNull(dst);
35 + }
36 +
37 + /**
38 + * Returns the port on which the ingress traffic should be connected to the
39 + * egress.
40 + *
41 + * @return ingress port
42 + */
43 + public HostId getSrc() {
44 + return src;
45 + }
46 +
47 + /**
48 + * Returns the port on which the traffic should egress.
49 + *
50 + * @return egress port
51 + */
52 + public HostId getDst() {
53 + return dst;
54 + }
55 +
56 + @Override
57 + public boolean equals(Object o) {
58 + if (this == o) {
59 + return true;
60 + }
61 + if (o == null || getClass() != o.getClass()) {
62 + return false;
63 + }
64 + if (!super.equals(o)) {
65 + return false;
66 + }
67 +
68 + HostToHostIntent that = (HostToHostIntent) o;
69 + return Objects.equals(this.src, that.src)
70 + && Objects.equals(this.dst, that.dst);
71 + }
72 +
73 + @Override
74 + public int hashCode() {
75 + return Objects.hash(super.hashCode(), src, dst);
76 + }
77 +
78 + @Override
79 + public String toString() {
80 + return MoreObjects.toStringHelper(getClass())
81 + .add("id", getId())
82 + .add("selector", getTrafficSelector())
83 + .add("treatmetn", getTrafficTreatment())
84 + .add("src", src)
85 + .add("dst", dst)
86 + .toString();
87 + }
88 +
89 +}
...@@ -2,7 +2,7 @@ package org.onlab.onos.net.intent; ...@@ -2,7 +2,7 @@ package org.onlab.onos.net.intent;
2 2
3 /** 3 /**
4 * Abstraction of an application level intent. 4 * Abstraction of an application level intent.
5 - * 5 + * <p/>
6 * Make sure that an Intent should be immutable when a new type is defined. 6 * Make sure that an Intent should be immutable when a new type is defined.
7 */ 7 */
8 public interface Intent extends BatchOperationTarget { 8 public interface Intent extends BatchOperationTarget {
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import static com.google.common.base.Preconditions.checkNotNull; 3 +import com.google.common.base.MoreObjects;
4 +import org.onlab.onos.event.AbstractEvent;
4 5
5 import java.util.Objects; 6 import java.util.Objects;
6 7
7 -import com.google.common.base.MoreObjects; 8 +import static com.google.common.base.Preconditions.checkNotNull;
8 9
9 /** 10 /**
10 * A class to represent an intent related event. 11 * A class to represent an intent related event.
11 */ 12 */
12 -public class IntentEvent { 13 +public class IntentEvent extends AbstractEvent<IntentState, Intent> {
13 14
14 - // TODO: determine a suitable parent class; if one does not exist, consider introducing one 15 + // TODO: determine a suitable parent class; if one does not exist, consider
16 + // introducing one
15 17
16 private final long time; 18 private final long time;
17 private final Intent intent; 19 private final Intent intent;
...@@ -21,13 +23,14 @@ public class IntentEvent { ...@@ -21,13 +23,14 @@ public class IntentEvent {
21 /** 23 /**
22 * Creates an event describing a state change of an intent. 24 * Creates an event describing a state change of an intent.
23 * 25 *
24 - * @param intent subject intent 26 + * @param intent subject intent
25 - * @param state new intent state 27 + * @param state new intent state
26 * @param previous previous intent state 28 * @param previous previous intent state
27 - * @param time time the event created in milliseconds since start of epoch 29 + * @param time time the event created in milliseconds since start of epoch
28 * @throws NullPointerException if the intent or state is null 30 * @throws NullPointerException if the intent or state is null
29 */ 31 */
30 public IntentEvent(Intent intent, IntentState state, IntentState previous, long time) { 32 public IntentEvent(Intent intent, IntentState state, IntentState previous, long time) {
33 + super(state, intent);
31 this.intent = checkNotNull(intent); 34 this.intent = checkNotNull(intent);
32 this.state = checkNotNull(state); 35 this.state = checkNotNull(state);
33 this.previous = previous; 36 this.previous = previous;
...@@ -35,16 +38,6 @@ public class IntentEvent { ...@@ -35,16 +38,6 @@ public class IntentEvent {
35 } 38 }
36 39
37 /** 40 /**
38 - * Constructor for serializer.
39 - */
40 - protected IntentEvent() {
41 - this.intent = null;
42 - this.state = null;
43 - this.previous = null;
44 - this.time = 0;
45 - }
46 -
47 - /**
48 * Returns the state of the intent which caused the event. 41 * Returns the state of the intent which caused the event.
49 * 42 *
50 * @return the state of the intent 43 * @return the state of the intent
......
...@@ -26,7 +26,7 @@ public class IntentException extends RuntimeException { ...@@ -26,7 +26,7 @@ public class IntentException extends RuntimeException {
26 * Constructs an exception with the specified message and the underlying cause. 26 * Constructs an exception with the specified message and the underlying cause.
27 * 27 *
28 * @param message the message describing the specific nature of the error 28 * @param message the message describing the specific nature of the error
29 - * @param cause the underlying cause of this error 29 + * @param cause the underlying cause of this error
30 */ 30 */
31 public IntentException(String message, Throwable cause) { 31 public IntentException(String message, Throwable cause) {
32 super(message, cause); 32 super(message, cause);
......
...@@ -10,9 +10,9 @@ public interface IntentExtensionService { ...@@ -10,9 +10,9 @@ public interface IntentExtensionService {
10 /** 10 /**
11 * Registers the specified compiler for the given intent class. 11 * Registers the specified compiler for the given intent class.
12 * 12 *
13 - * @param cls intent class 13 + * @param cls intent class
14 * @param compiler intent compiler 14 * @param compiler intent compiler
15 - * @param <T> the type of intent 15 + * @param <T> the type of intent
16 */ 16 */
17 <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler); 17 <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler);
18 18
...@@ -34,9 +34,9 @@ public interface IntentExtensionService { ...@@ -34,9 +34,9 @@ public interface IntentExtensionService {
34 /** 34 /**
35 * Registers the specified installer for the given installable intent class. 35 * Registers the specified installer for the given installable intent class.
36 * 36 *
37 - * @param cls installable intent class 37 + * @param cls installable intent class
38 * @param installer intent installer 38 * @param installer intent installer
39 - * @param <T> the type of installable intent 39 + * @param <T> the type of installable intent
40 */ 40 */
41 <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer); 41 <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer);
42 42
......
...@@ -2,7 +2,7 @@ package org.onlab.onos.net.intent; ...@@ -2,7 +2,7 @@ package org.onlab.onos.net.intent;
2 2
3 /** 3 /**
4 * Intent identifier suitable as an external key. 4 * Intent identifier suitable as an external key.
5 - * 5 + * <p/>
6 * This class is immutable. 6 * This class is immutable.
7 */ 7 */
8 public final class IntentId implements BatchOperationTarget { 8 public final class IntentId implements BatchOperationTarget {
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 +import org.onlab.onos.event.EventListener;
4 +
3 /** 5 /**
4 * Listener for {@link IntentEvent intent events}. 6 * Listener for {@link IntentEvent intent events}.
5 */ 7 */
6 -public interface IntentEventListener { 8 +public interface IntentListener extends EventListener<IntentEvent> {
7 - /**
8 - * Processes the specified intent event.
9 - *
10 - * @param event the event to process
11 - */
12 - void event(IntentEvent event);
13 } 9 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import java.util.Set;
4 3
5 /** 4 /**
6 * Service for application submitting or withdrawing their intents. 5 * Service for application submitting or withdrawing their intents.
...@@ -8,9 +7,9 @@ import java.util.Set; ...@@ -8,9 +7,9 @@ import java.util.Set;
8 public interface IntentService { 7 public interface IntentService {
9 /** 8 /**
10 * Submits an intent into the system. 9 * Submits an intent into the system.
11 - * 10 + * <p/>
12 - * This is an asynchronous request meaning that any compiling 11 + * This is an asynchronous request meaning that any compiling or
13 - * or installation activities may be done at later time. 12 + * installation activities may be done at later time.
14 * 13 *
15 * @param intent intent to be submitted 14 * @param intent intent to be submitted
16 */ 15 */
...@@ -18,9 +17,9 @@ public interface IntentService { ...@@ -18,9 +17,9 @@ public interface IntentService {
18 17
19 /** 18 /**
20 * Withdraws an intent from the system. 19 * Withdraws an intent from the system.
21 - * 20 + * <p/>
22 - * This is an asynchronous request meaning that the environment 21 + * This is an asynchronous request meaning that the environment may be
23 - * may be affected at later time. 22 + * affected at later time.
24 * 23 *
25 * @param intent intent to be withdrawn 24 * @param intent intent to be withdrawn
26 */ 25 */
...@@ -29,20 +28,27 @@ public interface IntentService { ...@@ -29,20 +28,27 @@ public interface IntentService {
29 /** 28 /**
30 * Submits a batch of submit &amp; withdraw operations. Such a batch is 29 * Submits a batch of submit &amp; withdraw operations. Such a batch is
31 * assumed to be processed together. 30 * assumed to be processed together.
32 - * 31 + * <p/>
33 - * This is an asynchronous request meaning that the environment 32 + * This is an asynchronous request meaning that the environment may be
34 - * may be affected at later time. 33 + * affected at later time.
35 * 34 *
36 * @param operations batch of intent operations 35 * @param operations batch of intent operations
37 */ 36 */
38 void execute(IntentOperations operations); 37 void execute(IntentOperations operations);
39 38
40 /** 39 /**
41 - * Returns immutable set of intents currently in the system. 40 + * Returns an iterable of intents currently in the system.
42 * 41 *
43 * @return set of intents 42 * @return set of intents
44 */ 43 */
45 - Set<Intent> getIntents(); 44 + Iterable<Intent> getIntents();
45 +
46 + /**
47 + * Returns the number of intents currently in the system.
48 + *
49 + * @return number of intents
50 + */
51 + long getIntentCount();
46 52
47 /** 53 /**
48 * Retrieves the intent specified by its identifier. 54 * Retrieves the intent specified by its identifier.
...@@ -56,7 +62,8 @@ public interface IntentService { ...@@ -56,7 +62,8 @@ public interface IntentService {
56 * Retrieves the state of an intent by its identifier. 62 * Retrieves the state of an intent by its identifier.
57 * 63 *
58 * @param id intent identifier 64 * @param id intent identifier
59 - * @return the intent state or null if one with the given identifier is not found 65 + * @return the intent state or null if one with the given identifier is not
66 + * found
60 */ 67 */
61 IntentState getIntentState(IntentId id); 68 IntentState getIntentState(IntentId id);
62 69
...@@ -65,12 +72,12 @@ public interface IntentService { ...@@ -65,12 +72,12 @@ public interface IntentService {
65 * 72 *
66 * @param listener listener to be added 73 * @param listener listener to be added
67 */ 74 */
68 - void addListener(IntentEventListener listener); 75 + void addListener(IntentListener listener);
69 76
70 /** 77 /**
71 * Removes the specified listener for intent events. 78 * Removes the specified listener for intent events.
72 * 79 *
73 * @param listener listener to be removed 80 * @param listener listener to be removed
74 */ 81 */
75 - void removeListener(IntentEventListener listener); 82 + void removeListener(IntentListener listener);
76 } 83 }
......
1 +package org.onlab.onos.net.intent;
2 +
3 +import org.onlab.onos.store.Store;
4 +
5 +import java.util.List;
6 +
7 +/**
8 + * Manages inventory of end-station intents; not intended for direct use.
9 + */
10 +public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> {
11 +
12 + /**
13 + * Creates a new intent.
14 + *
15 + * @param intent intent
16 + * @return appropriate event or null if no change resulted
17 + */
18 + IntentEvent createIntent(Intent intent);
19 +
20 + /**
21 + * Removes the specified intent from the inventory.
22 + *
23 + * @param intentId intent identification
24 + * @return removed state transition event or null if intent was not found
25 + */
26 + IntentEvent removeIntent(IntentId intentId);
27 +
28 + /**
29 + * Returns the number of intents in the store.
30 + */
31 + long getIntentCount();
32 +
33 + /**
34 + * Returns a collection of all intents in the store.
35 + *
36 + * @return iterable collection of all intents
37 + */
38 + Iterable<Intent> getIntents();
39 +
40 + /**
41 + * Returns the intent with the specified identifer.
42 + *
43 + * @param intentId intent identification
44 + * @return intent or null if not found
45 + */
46 + Intent getIntent(IntentId intentId);
47 +
48 + /**
49 + * Returns the state of the specified intent.
50 + *
51 + * @param intentId intent identification
52 + * @return current intent state
53 + */
54 + IntentState getIntentState(IntentId intentId);
55 +
56 + /**
57 + * Sets the state of the specified intent to the new state.
58 + *
59 + * @param intent intent whose state is to be changed
60 + * @param newState new state
61 + * @return state transition event
62 + */
63 + IntentEvent setState(Intent intent, IntentState newState);
64 +
65 + /**
66 + * Adds the installable intents which resulted from compilation of the
67 + * specified original intent.
68 + *
69 + * @param intentId original intent identifier
70 + * @param installableIntents compiled installable intents
71 + * @return compiled state transition event
72 + */
73 + IntentEvent addInstallableIntents(IntentId intentId,
74 + List<InstallableIntent> installableIntents);
75 +
76 + /**
77 + * Returns the list of the installable events associated with the specified
78 + * original intent.
79 + *
80 + * @param intentId original intent identifier
81 + * @return compiled installable intents
82 + */
83 + List<InstallableIntent> getInstallableIntents(IntentId intentId);
84 +
85 + // TODO: this should be triggered from with the store as a result of removeIntent call
86 +
87 + /**
88 + * Removes any installable intents which resulted from compilation of the
89 + * specified original intent.
90 + *
91 + * @param intentId original intent identifier
92 + * @return compiled state transition event
93 + */
94 + void removeInstalledIntents(IntentId intentId);
95 +
96 +}
1 +package org.onlab.onos.net.intent;
2 +
3 +import org.onlab.onos.store.StoreDelegate;
4 +
5 +/**
6 + * Intent store delegate abstraction.
7 + */
8 +public interface IntentStoreDelegate extends StoreDelegate<IntentEvent> {
9 +}
...@@ -30,18 +30,20 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent { ...@@ -30,18 +30,20 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent {
30 * @param action action 30 * @param action action
31 * @param ingressPorts set of ports from which ingress traffic originates 31 * @param ingressPorts set of ports from which ingress traffic originates
32 * @param egressPort port to which traffic will egress 32 * @param egressPort port to which traffic will egress
33 - * @throws NullPointerException if {@code ingressPorts} or 33 + * @throws NullPointerException if {@code ingressPorts} or
34 - * {@code egressPort} is null. 34 + * {@code egressPort} is null.
35 * @throws IllegalArgumentException if the size of {@code ingressPorts} is 35 * @throws IllegalArgumentException if the size of {@code ingressPorts} is
36 - * not more than 1 36 + * not more than 1
37 */ 37 */
38 - public MultiPointToSinglePointIntent(IntentId id, TrafficSelector match, TrafficTreatment action, 38 + public MultiPointToSinglePointIntent(IntentId id, TrafficSelector match,
39 - Set<ConnectPoint> ingressPorts, ConnectPoint egressPort) { 39 + TrafficTreatment action,
40 + Set<ConnectPoint> ingressPorts,
41 + ConnectPoint egressPort) {
40 super(id, match, action); 42 super(id, match, action);
41 43
42 checkNotNull(ingressPorts); 44 checkNotNull(ingressPorts);
43 checkArgument(!ingressPorts.isEmpty(), 45 checkArgument(!ingressPorts.isEmpty(),
44 - "there should be at least one ingress port"); 46 + "there should be at least one ingress port");
45 47
46 this.ingressPorts = Sets.newHashSet(ingressPorts); 48 this.ingressPorts = Sets.newHashSet(ingressPorts);
47 this.egressPort = checkNotNull(egressPort); 49 this.egressPort = checkNotNull(egressPort);
......
...@@ -3,30 +3,30 @@ package org.onlab.onos.net.intent; ...@@ -3,30 +3,30 @@ package org.onlab.onos.net.intent;
3 import org.onlab.onos.net.ConnectPoint; 3 import org.onlab.onos.net.ConnectPoint;
4 4
5 // TODO: consider if this intent should be sub-class of ConnectivityIntent 5 // TODO: consider if this intent should be sub-class of ConnectivityIntent
6 +
6 /** 7 /**
7 * An optical layer Intent for a connectivity from a transponder port to another 8 * An optical layer Intent for a connectivity from a transponder port to another
8 * transponder port. 9 * transponder port.
9 - * <p> 10 + * <p/>
10 * This class doesn't accepts lambda specifier. This class computes path between 11 * This class doesn't accepts lambda specifier. This class computes path between
11 * ports and assign lambda automatically. The lambda can be specified using 12 * ports and assign lambda automatically. The lambda can be specified using
12 * OpticalPathFlow class. 13 * OpticalPathFlow class.
13 */ 14 */
14 public class OpticalConnectivityIntent extends AbstractIntent { 15 public class OpticalConnectivityIntent extends AbstractIntent {
15 - protected ConnectPoint srcConnectPoint; 16 + protected ConnectPoint src;
16 - protected ConnectPoint dstConnectPoint; 17 + protected ConnectPoint dst;
17 18
18 /** 19 /**
19 * Constructor. 20 * Constructor.
20 * 21 *
21 - * @param id ID for this new Intent object. 22 + * @param id ID for this new Intent object.
22 - * @param srcConnectPoint The source transponder port. 23 + * @param src The source transponder port.
23 - * @param dstConnectPoint The destination transponder port. 24 + * @param dst The destination transponder port.
24 */ 25 */
25 - public OpticalConnectivityIntent(IntentId id, 26 + public OpticalConnectivityIntent(IntentId id, ConnectPoint src, ConnectPoint dst) {
26 - ConnectPoint srcConnectPoint, ConnectPoint dstConnectPoint) {
27 super(id); 27 super(id);
28 - this.srcConnectPoint = srcConnectPoint; 28 + this.src = src;
29 - this.dstConnectPoint = dstConnectPoint; 29 + this.dst = dst;
30 } 30 }
31 31
32 /** 32 /**
...@@ -34,8 +34,8 @@ public class OpticalConnectivityIntent extends AbstractIntent { ...@@ -34,8 +34,8 @@ public class OpticalConnectivityIntent extends AbstractIntent {
34 */ 34 */
35 protected OpticalConnectivityIntent() { 35 protected OpticalConnectivityIntent() {
36 super(); 36 super();
37 - this.srcConnectPoint = null; 37 + this.src = null;
38 - this.dstConnectPoint = null; 38 + this.dst = null;
39 } 39 }
40 40
41 /** 41 /**
...@@ -44,7 +44,7 @@ public class OpticalConnectivityIntent extends AbstractIntent { ...@@ -44,7 +44,7 @@ public class OpticalConnectivityIntent extends AbstractIntent {
44 * @return The source transponder port. 44 * @return The source transponder port.
45 */ 45 */
46 public ConnectPoint getSrcConnectPoint() { 46 public ConnectPoint getSrcConnectPoint() {
47 - return srcConnectPoint; 47 + return src;
48 } 48 }
49 49
50 /** 50 /**
...@@ -52,7 +52,7 @@ public class OpticalConnectivityIntent extends AbstractIntent { ...@@ -52,7 +52,7 @@ public class OpticalConnectivityIntent extends AbstractIntent {
52 * 52 *
53 * @return The source transponder port. 53 * @return The source transponder port.
54 */ 54 */
55 - public ConnectPoint getDstConnectPoint() { 55 + public ConnectPoint getDst() {
56 - return dstConnectPoint; 56 + return dst;
57 } 57 }
58 } 58 }
......
...@@ -12,7 +12,7 @@ import com.google.common.base.MoreObjects; ...@@ -12,7 +12,7 @@ import com.google.common.base.MoreObjects;
12 /** 12 /**
13 * Abstraction of explicitly path specified connectivity intent. 13 * Abstraction of explicitly path specified connectivity intent.
14 */ 14 */
15 -public class PathIntent extends PointToPointIntent { 15 +public class PathIntent extends PointToPointIntent implements InstallableIntent {
16 16
17 private final Path path; 17 private final Path path;
18 18
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import static com.google.common.base.Preconditions.checkNotNull; 3 +import com.google.common.base.MoreObjects;
4 -
5 -import java.util.Objects;
6 -
7 import org.onlab.onos.net.ConnectPoint; 4 import org.onlab.onos.net.ConnectPoint;
8 import org.onlab.onos.net.flow.TrafficSelector; 5 import org.onlab.onos.net.flow.TrafficSelector;
9 import org.onlab.onos.net.flow.TrafficTreatment; 6 import org.onlab.onos.net.flow.TrafficTreatment;
10 7
11 -import com.google.common.base.MoreObjects; 8 +import java.util.Objects;
9 +
10 +import static com.google.common.base.Preconditions.checkNotNull;
12 11
13 /** 12 /**
14 * Abstraction of point-to-point connectivity. 13 * Abstraction of point-to-point connectivity.
...@@ -23,15 +22,17 @@ public class PointToPointIntent extends ConnectivityIntent { ...@@ -23,15 +22,17 @@ public class PointToPointIntent extends ConnectivityIntent {
23 * ports. 22 * ports.
24 * 23 *
25 * @param id intent identifier 24 * @param id intent identifier
26 - * @param match traffic match 25 + * @param selector traffic selector
27 - * @param action action 26 + * @param treatment treatment
28 * @param ingressPort ingress port 27 * @param ingressPort ingress port
29 * @param egressPort egress port 28 * @param egressPort egress port
30 * @throws NullPointerException if {@code ingressPort} or {@code egressPort} is null. 29 * @throws NullPointerException if {@code ingressPort} or {@code egressPort} is null.
31 */ 30 */
32 - public PointToPointIntent(IntentId id, TrafficSelector match, TrafficTreatment action, 31 + public PointToPointIntent(IntentId id, TrafficSelector selector,
33 - ConnectPoint ingressPort, ConnectPoint egressPort) { 32 + TrafficTreatment treatment,
34 - super(id, match, action); 33 + ConnectPoint ingressPort,
34 + ConnectPoint egressPort) {
35 + super(id, selector, treatment);
35 this.ingressPort = checkNotNull(ingressPort); 36 this.ingressPort = checkNotNull(ingressPort);
36 this.egressPort = checkNotNull(egressPort); 37 this.egressPort = checkNotNull(egressPort);
37 } 38 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import static com.google.common.base.Preconditions.checkArgument; 3 +import com.google.common.base.MoreObjects;
4 -import static com.google.common.base.Preconditions.checkNotNull; 4 +import com.google.common.collect.Sets;
5 -
6 -import java.util.Objects;
7 -import java.util.Set;
8 -
9 import org.onlab.onos.net.ConnectPoint; 5 import org.onlab.onos.net.ConnectPoint;
10 import org.onlab.onos.net.flow.TrafficSelector; 6 import org.onlab.onos.net.flow.TrafficSelector;
11 import org.onlab.onos.net.flow.TrafficTreatment; 7 import org.onlab.onos.net.flow.TrafficTreatment;
12 8
13 -import com.google.common.base.MoreObjects; 9 +import java.util.Objects;
14 -import com.google.common.collect.Sets; 10 +import java.util.Set;
11 +
12 +import static com.google.common.base.Preconditions.checkArgument;
13 +import static com.google.common.base.Preconditions.checkNotNull;
15 14
16 /** 15 /**
17 * Abstraction of single source, multiple destination connectivity intent. 16 * Abstraction of single source, multiple destination connectivity intent.
...@@ -25,23 +24,24 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { ...@@ -25,23 +24,24 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent {
25 * Creates a new single-to-multi point connectivity intent. 24 * Creates a new single-to-multi point connectivity intent.
26 * 25 *
27 * @param id intent identifier 26 * @param id intent identifier
28 - * @param match traffic match 27 + * @param selector traffic selector
29 - * @param action action 28 + * @param treatment treatment
30 * @param ingressPort port on which traffic will ingress 29 * @param ingressPort port on which traffic will ingress
31 * @param egressPorts set of ports on which traffic will egress 30 * @param egressPorts set of ports on which traffic will egress
32 - * @throws NullPointerException if {@code ingressPort} or 31 + * @throws NullPointerException if {@code ingressPort} or
33 - * {@code egressPorts} is null 32 + * {@code egressPorts} is null
34 * @throws IllegalArgumentException if the size of {@code egressPorts} is 33 * @throws IllegalArgumentException if the size of {@code egressPorts} is
35 - * not more than 1 34 + * not more than 1
36 */ 35 */
37 - public SinglePointToMultiPointIntent(IntentId id, TrafficSelector match, TrafficTreatment action, 36 + public SinglePointToMultiPointIntent(IntentId id, TrafficSelector selector,
37 + TrafficTreatment treatment,
38 ConnectPoint ingressPort, 38 ConnectPoint ingressPort,
39 Set<ConnectPoint> egressPorts) { 39 Set<ConnectPoint> egressPorts) {
40 - super(id, match, action); 40 + super(id, selector, treatment);
41 41
42 checkNotNull(egressPorts); 42 checkNotNull(egressPorts);
43 checkArgument(!egressPorts.isEmpty(), 43 checkArgument(!egressPorts.isEmpty(),
44 - "there should be at least one egress port"); 44 + "there should be at least one egress port");
45 45
46 this.ingressPort = checkNotNull(ingressPort); 46 this.ingressPort = checkNotNull(ingressPort);
47 this.egressPorts = Sets.newHashSet(egressPorts); 47 this.egressPorts = Sets.newHashSet(egressPorts);
......
1 /** 1 /**
2 - * Intent Package. TODO 2 + * Set of abstractions for conveying high-level intents for treatment of
3 + * selected network traffic by allowing applications to express the
4 + * <em>what</em> rather than the <em>how</em>. This makes such instructions
5 + * largely independent of topology and device specifics, thus allowing them to
6 + * survive topology mutations.
3 */ 7 */
4 -
5 package org.onlab.onos.net.intent; 8 package org.onlab.onos.net.intent;
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -24,7 +24,7 @@ public abstract class DefaultPacketContext implements PacketContext { ...@@ -24,7 +24,7 @@ public abstract class DefaultPacketContext implements PacketContext {
24 this.inPkt = inPkt; 24 this.inPkt = inPkt;
25 this.outPkt = outPkt; 25 this.outPkt = outPkt;
26 this.block = new AtomicBoolean(block); 26 this.block = new AtomicBoolean(block);
27 - this.builder = new DefaultTrafficTreatment.Builder(); 27 + this.builder = DefaultTrafficTreatment.builder();
28 } 28 }
29 29
30 @Override 30 @Override
......
...@@ -3,6 +3,7 @@ package org.onlab.onos.net.provider; ...@@ -3,6 +3,7 @@ package org.onlab.onos.net.provider;
3 import java.util.Objects; 3 import java.util.Objects;
4 4
5 import static com.google.common.base.MoreObjects.toStringHelper; 5 import static com.google.common.base.MoreObjects.toStringHelper;
6 +import static com.google.common.base.Preconditions.checkNotNull;
6 7
7 /** 8 /**
8 * External identity of a {@link org.onlab.onos.net.provider.Provider} family. 9 * External identity of a {@link org.onlab.onos.net.provider.Provider} family.
...@@ -19,10 +20,22 @@ import static com.google.common.base.MoreObjects.toStringHelper; ...@@ -19,10 +20,22 @@ import static com.google.common.base.MoreObjects.toStringHelper;
19 */ 20 */
20 public class ProviderId { 21 public class ProviderId {
21 22
23 + /**
24 + * Represents no provider ID.
25 + */
26 + public static final ProviderId NONE = new ProviderId();
27 +
22 private final String scheme; 28 private final String scheme;
23 private final String id; 29 private final String id;
24 private final boolean ancillary; 30 private final boolean ancillary;
25 31
32 + // For serialization
33 + private ProviderId() {
34 + scheme = null;
35 + id = null;
36 + ancillary = false;
37 + }
38 +
26 /** 39 /**
27 * Creates a new primary provider identifier from the specified string. 40 * Creates a new primary provider identifier from the specified string.
28 * The providers are expected to follow the reverse DNS convention, e.g. 41 * The providers are expected to follow the reverse DNS convention, e.g.
...@@ -45,8 +58,8 @@ public class ProviderId { ...@@ -45,8 +58,8 @@ public class ProviderId {
45 * @param ancillary ancillary provider indicator 58 * @param ancillary ancillary provider indicator
46 */ 59 */
47 public ProviderId(String scheme, String id, boolean ancillary) { 60 public ProviderId(String scheme, String id, boolean ancillary) {
48 - this.scheme = scheme; 61 + this.scheme = checkNotNull(scheme, "Scheme cannot be null");
49 - this.id = id; 62 + this.id = checkNotNull(id, "ID cannot be null");
50 this.ancillary = ancillary; 63 this.ancillary = ancillary;
51 } 64 }
52 65
......
1 +package org.onlab.onos.store;
2 +
3 +import org.onlab.onos.cluster.MastershipTerm;
4 +import org.onlab.onos.net.DeviceId;
5 +
6 +//TODO: Consider renaming to DeviceClockProviderService?
7 +/**
8 +* Interface for feeding term information to a logical clock service
9 +* that vends per device timestamps.
10 +*/
11 +public interface ClockProviderService {
12 +
13 + /**
14 + * Updates the mastership term for the specified deviceId.
15 + * @param deviceId device identifier.
16 + * @param term mastership term.
17 + */
18 + public void setMastershipTerm(DeviceId deviceId, MastershipTerm term);
19 +}
1 package org.onlab.onos.store; 1 package org.onlab.onos.store;
2 2
3 -import org.onlab.onos.cluster.MastershipTerm;
4 import org.onlab.onos.net.DeviceId; 3 import org.onlab.onos.net.DeviceId;
5 4
6 // TODO: Consider renaming to DeviceClockService? 5 // TODO: Consider renaming to DeviceClockService?
...@@ -15,12 +14,4 @@ public interface ClockService { ...@@ -15,12 +14,4 @@ public interface ClockService {
15 * @return timestamp. 14 * @return timestamp.
16 */ 15 */
17 public Timestamp getTimestamp(DeviceId deviceId); 16 public Timestamp getTimestamp(DeviceId deviceId);
18 -
19 - // TODO: Should this be here or separate as Admin service, etc.?
20 - /**
21 - * Updates the mastership term for the specified deviceId.
22 - * @param deviceId device identifier.
23 - * @param term mastership term.
24 - */
25 - public void setMastershipTerm(DeviceId deviceId, MastershipTerm term);
26 } 17 }
......
...@@ -2,7 +2,15 @@ package org.onlab.onos.store; ...@@ -2,7 +2,15 @@ package org.onlab.onos.store;
2 2
3 /** 3 /**
4 * Opaque version structure. 4 * Opaque version structure.
5 + * <p>
6 + * Classes implementing this interface must also implement
7 + * {@link #hashCode()} and {@link #equals(Object)}.
5 */ 8 */
6 public interface Timestamp extends Comparable<Timestamp> { 9 public interface Timestamp extends Comparable<Timestamp> {
7 10
11 + @Override
12 + public abstract int hashCode();
13 +
14 + @Override
15 + public abstract boolean equals(Object obj);
8 } 16 }
......
...@@ -16,8 +16,8 @@ import org.onlab.onos.net.flow.TrafficTreatment; ...@@ -16,8 +16,8 @@ import org.onlab.onos.net.flow.TrafficTreatment;
16 public abstract class ConnectivityIntentTest extends IntentTest { 16 public abstract class ConnectivityIntentTest extends IntentTest {
17 17
18 public static final IntentId IID = new IntentId(123); 18 public static final IntentId IID = new IntentId(123);
19 - public static final TrafficSelector MATCH = (new DefaultTrafficSelector.Builder()).build(); 19 + public static final TrafficSelector MATCH = DefaultTrafficSelector.builder().build();
20 - public static final TrafficTreatment NOP = (new DefaultTrafficTreatment.Builder()).build(); 20 + public static final TrafficTreatment NOP = DefaultTrafficTreatment.builder().build();
21 21
22 public static final ConnectPoint P1 = new ConnectPoint(DeviceId.deviceId("111"), PortNumber.portNumber(0x1)); 22 public static final ConnectPoint P1 = new ConnectPoint(DeviceId.deviceId("111"), PortNumber.portNumber(0x1));
23 public static final ConnectPoint P2 = new ConnectPoint(DeviceId.deviceId("222"), PortNumber.portNumber(0x2)); 23 public static final ConnectPoint P2 = new ConnectPoint(DeviceId.deviceId("222"), PortNumber.portNumber(0x2));
......
...@@ -11,19 +11,19 @@ import java.util.concurrent.ExecutorService; ...@@ -11,19 +11,19 @@ import java.util.concurrent.ExecutorService;
11 import java.util.concurrent.Executors; 11 import java.util.concurrent.Executors;
12 12
13 /** 13 /**
14 - * Fake implementation of the intent service to assist in developing tests 14 + * Fake implementation of the intent service to assist in developing tests of
15 - * of the interface contract. 15 + * the interface contract.
16 */ 16 */
17 public class FakeIntentManager implements TestableIntentService { 17 public class FakeIntentManager implements TestableIntentService {
18 18
19 private final Map<IntentId, Intent> intents = new HashMap<>(); 19 private final Map<IntentId, Intent> intents = new HashMap<>();
20 private final Map<IntentId, IntentState> intentStates = new HashMap<>(); 20 private final Map<IntentId, IntentState> intentStates = new HashMap<>();
21 private final Map<IntentId, List<InstallableIntent>> installables = new HashMap<>(); 21 private final Map<IntentId, List<InstallableIntent>> installables = new HashMap<>();
22 - private final Set<IntentEventListener> listeners = new HashSet<>(); 22 + private final Set<IntentListener> listeners = new HashSet<>();
23 23
24 private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>(); 24 private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>();
25 - private final Map<Class<? extends InstallableIntent>, 25 + private final Map<Class<? extends InstallableIntent>, IntentInstaller<? extends InstallableIntent>> installers
26 - IntentInstaller<? extends InstallableIntent>> installers = new HashMap<>(); 26 + = new HashMap<>();
27 27
28 private final ExecutorService executor = Executors.newSingleThreadExecutor(); 28 private final ExecutorService executor = Executors.newSingleThreadExecutor();
29 private final List<IntentException> exceptions = new ArrayList<>(); 29 private final List<IntentException> exceptions = new ArrayList<>();
...@@ -76,7 +76,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -76,7 +76,8 @@ public class FakeIntentManager implements TestableIntentService {
76 76
77 private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) { 77 private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) {
78 @SuppressWarnings("unchecked") 78 @SuppressWarnings("unchecked")
79 - IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass()); 79 + IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent
80 + .getClass());
80 if (installer == null) { 81 if (installer == null) {
81 throw new IntentException("no installer for class " + intent.getClass()); 82 throw new IntentException("no installer for class " + intent.getClass());
82 } 83 }
...@@ -125,7 +126,6 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -125,7 +126,6 @@ public class FakeIntentManager implements TestableIntentService {
125 } 126 }
126 } 127 }
127 128
128 -
129 // Sets the internal state for the given intent and dispatches an event 129 // Sets the internal state for the given intent and dispatches an event
130 private void setState(Intent intent, IntentState state) { 130 private void setState(Intent intent, IntentState state) {
131 IntentState previous = intentStates.get(intent.getId()); 131 IntentState previous = intentStates.get(intent.getId());
...@@ -175,6 +175,11 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -175,6 +175,11 @@ public class FakeIntentManager implements TestableIntentService {
175 } 175 }
176 176
177 @Override 177 @Override
178 + public long getIntentCount() {
179 + return intents.size();
180 + }
181 +
182 + @Override
178 public Intent getIntent(IntentId id) { 183 public Intent getIntent(IntentId id) {
179 return intents.get(id); 184 return intents.get(id);
180 } 185 }
...@@ -185,23 +190,24 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -185,23 +190,24 @@ public class FakeIntentManager implements TestableIntentService {
185 } 190 }
186 191
187 @Override 192 @Override
188 - public void addListener(IntentEventListener listener) { 193 + public void addListener(IntentListener listener) {
189 listeners.add(listener); 194 listeners.add(listener);
190 } 195 }
191 196
192 @Override 197 @Override
193 - public void removeListener(IntentEventListener listener) { 198 + public void removeListener(IntentListener listener) {
194 listeners.remove(listener); 199 listeners.remove(listener);
195 } 200 }
196 201
197 private void dispatch(IntentEvent event) { 202 private void dispatch(IntentEvent event) {
198 - for (IntentEventListener listener : listeners) { 203 + for (IntentListener listener : listeners) {
199 listener.event(event); 204 listener.event(event);
200 } 205 }
201 } 206 }
202 207
203 @Override 208 @Override
204 - public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) { 209 + public <T extends Intent> void registerCompiler(Class<T> cls,
210 + IntentCompiler<T> compiler) {
205 compilers.put(cls, compiler); 211 compilers.put(cls, compiler);
206 } 212 }
207 213
...@@ -216,7 +222,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -216,7 +222,8 @@ public class FakeIntentManager implements TestableIntentService {
216 } 222 }
217 223
218 @Override 224 @Override
219 - public <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) { 225 + public <T extends InstallableIntent> void registerInstaller(Class<T> cls,
226 + IntentInstaller<T> installer) {
220 installers.put(cls, installer); 227 installers.put(cls, installer);
221 } 228 }
222 229
...@@ -227,7 +234,7 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -227,7 +234,7 @@ public class FakeIntentManager implements TestableIntentService {
227 234
228 @Override 235 @Override
229 public Map<Class<? extends InstallableIntent>, 236 public Map<Class<? extends InstallableIntent>,
230 - IntentInstaller<? extends InstallableIntent>> getInstallers() { 237 + IntentInstaller<? extends InstallableIntent>> getInstallers() {
231 return Collections.unmodifiableMap(installers); 238 return Collections.unmodifiableMap(installers);
232 } 239 }
233 240
...@@ -252,7 +259,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -252,7 +259,8 @@ public class FakeIntentManager implements TestableIntentService {
252 if (!installers.containsKey(intent.getClass())) { 259 if (!installers.containsKey(intent.getClass())) {
253 Class<?> cls = intent.getClass(); 260 Class<?> cls = intent.getClass();
254 while (cls != Object.class) { 261 while (cls != Object.class) {
255 - // As long as we're within the InstallableIntent class descendants 262 + // As long as we're within the InstallableIntent class
263 + // descendants
256 if (InstallableIntent.class.isAssignableFrom(cls)) { 264 if (InstallableIntent.class.isAssignableFrom(cls)) {
257 IntentInstaller<?> installer = installers.get(cls); 265 IntentInstaller<?> installer = installers.get(cls);
258 if (installer != null) { 266 if (installer != null) {
......
...@@ -51,7 +51,7 @@ public class IntentServiceTest { ...@@ -51,7 +51,7 @@ public class IntentServiceTest {
51 @Test 51 @Test
52 public void basics() { 52 public void basics() {
53 // Make sure there are no intents 53 // Make sure there are no intents
54 - assertEquals("incorrect intent count", 0, service.getIntents().size()); 54 + assertEquals("incorrect intent count", 0, service.getIntentCount());
55 55
56 // Register a compiler and an installer both setup for success. 56 // Register a compiler and an installer both setup for success.
57 service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID))); 57 service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID)));
...@@ -73,8 +73,7 @@ public class IntentServiceTest { ...@@ -73,8 +73,7 @@ public class IntentServiceTest {
73 validateEvents(intent, SUBMITTED, COMPILED, INSTALLED); 73 validateEvents(intent, SUBMITTED, COMPILED, INSTALLED);
74 74
75 // Make sure there is just one intent (and is ours) 75 // Make sure there is just one intent (and is ours)
76 - assertEquals("incorrect intent count", 1, service.getIntents().size()); 76 + assertEquals("incorrect intent count", 1, service.getIntentCount());
77 - assertEquals("incorrect intent", intent, service.getIntent(intent.getId()));
78 77
79 // Reset the listener events 78 // Reset the listener events
80 listener.events.clear(); 79 listener.events.clear();
...@@ -250,7 +249,7 @@ public class IntentServiceTest { ...@@ -250,7 +249,7 @@ public class IntentServiceTest {
250 249
251 250
252 // Fixture to track emitted intent events 251 // Fixture to track emitted intent events
253 - protected class TestListener implements IntentEventListener { 252 + protected class TestListener implements IntentListener {
254 final List<IntentEvent> events = new ArrayList<>(); 253 final List<IntentEvent> events = new ArrayList<>();
255 254
256 @Override 255 @Override
......
...@@ -38,7 +38,7 @@ import org.onlab.onos.net.device.DeviceStoreDelegate; ...@@ -38,7 +38,7 @@ import org.onlab.onos.net.device.DeviceStoreDelegate;
38 import org.onlab.onos.net.device.PortDescription; 38 import org.onlab.onos.net.device.PortDescription;
39 import org.onlab.onos.net.provider.AbstractProviderRegistry; 39 import org.onlab.onos.net.provider.AbstractProviderRegistry;
40 import org.onlab.onos.net.provider.AbstractProviderService; 40 import org.onlab.onos.net.provider.AbstractProviderService;
41 -import org.onlab.onos.store.ClockService; 41 +import org.onlab.onos.store.ClockProviderService;
42 import org.slf4j.Logger; 42 import org.slf4j.Logger;
43 43
44 /** 44 /**
...@@ -80,7 +80,7 @@ public class DeviceManager ...@@ -80,7 +80,7 @@ public class DeviceManager
80 protected MastershipTermService termService; 80 protected MastershipTermService termService;
81 81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 - protected ClockService clockService; 83 + protected ClockProviderService clockProviderService;
84 84
85 @Activate 85 @Activate
86 public void activate() { 86 public void activate() {
...@@ -274,7 +274,7 @@ public class DeviceManager ...@@ -274,7 +274,7 @@ public class DeviceManager
274 if (event.master().equals(clusterService.getLocalNode().id())) { 274 if (event.master().equals(clusterService.getLocalNode().id())) {
275 MastershipTerm term = mastershipService.requestTermService() 275 MastershipTerm term = mastershipService.requestTermService()
276 .getMastershipTerm(event.subject()); 276 .getMastershipTerm(event.subject());
277 - clockService.setMastershipTerm(event.subject(), term); 277 + clockProviderService.setMastershipTerm(event.subject(), term);
278 applyRole(event.subject(), MastershipRole.MASTER); 278 applyRole(event.subject(), MastershipRole.MASTER);
279 } else { 279 } else {
280 applyRole(event.subject(), MastershipRole.STANDBY); 280 applyRole(event.subject(), MastershipRole.STANDBY);
......
...@@ -242,15 +242,16 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -242,15 +242,16 @@ implements FlowRuleService, FlowRuleProviderRegistry {
242 } 242 }
243 243
244 private boolean checkRuleLiveness(FlowRule swRule, FlowRule storedRule) { 244 private boolean checkRuleLiveness(FlowRule swRule, FlowRule storedRule) {
245 - int timeout = storedRule.timeout(); 245 + return true;
246 - if (storedRule.packets() != swRule.packets()) { 246 +// int timeout = storedRule.timeout();
247 - deadRounds.get(swRule).set(0); 247 +// if (storedRule.packets() != swRule.packets()) {
248 - return true; 248 +// deadRounds.get(swRule).set(0);
249 - } 249 +// return true;
250 - 250 +// }
251 - return (deadRounds.get(swRule).getAndIncrement() * 251 +//
252 - FlowRuleProvider.POLL_INTERVAL) <= timeout; 252 +// return (deadRounds.get(swRule).getAndIncrement() *
253 - 253 +// FlowRuleProvider.POLL_INTERVAL) <= timeout;
254 +//
254 } 255 }
255 256
256 // Posts the specified event to the local event dispatcher. 257 // Posts the specified event to the local event dispatcher.
......
...@@ -4,9 +4,9 @@ import java.nio.ByteBuffer; ...@@ -4,9 +4,9 @@ import java.nio.ByteBuffer;
4 import java.util.ArrayList; 4 import java.util.ArrayList;
5 import java.util.HashSet; 5 import java.util.HashSet;
6 import java.util.List; 6 import java.util.List;
7 -import java.util.Map;
8 import java.util.Set; 7 import java.util.Set;
9 import java.util.concurrent.ConcurrentHashMap; 8 import java.util.concurrent.ConcurrentHashMap;
9 +import java.util.concurrent.ConcurrentMap;
10 import java.util.concurrent.TimeUnit; 10 import java.util.concurrent.TimeUnit;
11 11
12 import org.jboss.netty.util.Timeout; 12 import org.jboss.netty.util.Timeout;
...@@ -59,15 +59,14 @@ public class HostMonitor implements TimerTask { ...@@ -59,15 +59,14 @@ public class HostMonitor implements TimerTask {
59 59
60 private final Set<IpAddress> monitoredAddresses; 60 private final Set<IpAddress> monitoredAddresses;
61 61
62 - private final Map<ProviderId, HostProvider> hostProviders; 62 + private final ConcurrentMap<ProviderId, HostProvider> hostProviders;
63 63
64 - private final long probeRate; 64 + private static final long DEFAULT_PROBE_RATE = 30000; // milliseconds
65 + private long probeRate = DEFAULT_PROBE_RATE;
65 66
66 private final Timeout timeout; 67 private final Timeout timeout;
67 68
68 - public HostMonitor( 69 + public HostMonitor(DeviceService deviceService, PacketService packetService,
69 - DeviceService deviceService,
70 - PacketService packetService,
71 HostManager hostService) { 70 HostManager hostService) {
72 71
73 this.deviceService = deviceService; 72 this.deviceService = deviceService;
...@@ -77,15 +76,7 @@ public class HostMonitor implements TimerTask { ...@@ -77,15 +76,7 @@ public class HostMonitor implements TimerTask {
77 monitoredAddresses = new HashSet<>(); 76 monitoredAddresses = new HashSet<>();
78 hostProviders = new ConcurrentHashMap<>(); 77 hostProviders = new ConcurrentHashMap<>();
79 78
80 - probeRate = 30000; // milliseconds
81 -
82 timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS); 79 timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS);
83 -
84 - addDefaultAddresses();
85 - }
86 -
87 - private void addDefaultAddresses() {
88 - //monitoredAddresses.add(IpAddress.valueOf("10.0.0.1"));
89 } 80 }
90 81
91 void addMonitoringFor(IpAddress ip) { 82 void addMonitoringFor(IpAddress ip) {
...@@ -104,10 +95,6 @@ public class HostMonitor implements TimerTask { ...@@ -104,10 +95,6 @@ public class HostMonitor implements TimerTask {
104 hostProviders.put(provider.id(), provider); 95 hostProviders.put(provider.id(), provider);
105 } 96 }
106 97
107 - void unregisterHostProvider(HostProvider provider) {
108 - // TODO find out how to call this
109 - }
110 -
111 @Override 98 @Override
112 public void run(Timeout timeout) throws Exception { 99 public void run(Timeout timeout) throws Exception {
113 for (IpAddress ip : monitoredAddresses) { 100 for (IpAddress ip : monitoredAddresses) {
...@@ -121,7 +108,9 @@ public class HostMonitor implements TimerTask { ...@@ -121,7 +108,9 @@ public class HostMonitor implements TimerTask {
121 } else { 108 } else {
122 for (Host host : hosts) { 109 for (Host host : hosts) {
123 HostProvider provider = hostProviders.get(host.providerId()); 110 HostProvider provider = hostProviders.get(host.providerId());
124 - if (provider != null) { 111 + if (provider == null) {
112 + hostProviders.remove(host.providerId(), null);
113 + } else {
125 provider.triggerProbe(host); 114 provider.triggerProbe(host);
126 } 115 }
127 } 116 }
...@@ -161,7 +150,7 @@ public class HostMonitor implements TimerTask { ...@@ -161,7 +150,7 @@ public class HostMonitor implements TimerTask {
161 List<Instruction> instructions = new ArrayList<>(); 150 List<Instruction> instructions = new ArrayList<>();
162 instructions.add(Instructions.createOutput(port.number())); 151 instructions.add(Instructions.createOutput(port.number()));
163 152
164 - TrafficTreatment treatment = new DefaultTrafficTreatment.Builder() 153 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
165 .setOutput(port.number()) 154 .setOutput(port.number())
166 .build(); 155 .build();
167 156
......
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IdGenerator;
4 +
5 +/**
6 + * Base class of {@link IdGenerator} implementations which use {@link IdBlockAllocator} as
7 + * backend.
8 + *
9 + * @param <T> the type of ID
10 + */
11 +public abstract class AbstractBlockAllocatorBasedIdGenerator<T> implements IdGenerator<T> {
12 + protected final IdBlockAllocator allocator;
13 + protected IdBlock idBlock;
14 +
15 + /**
16 + * Constructs an ID generator which use {@link IdBlockAllocator} as backend.
17 + *
18 + * @param allocator
19 + */
20 + protected AbstractBlockAllocatorBasedIdGenerator(IdBlockAllocator allocator) {
21 + this.allocator = allocator;
22 + this.idBlock = allocator.allocateUniqueIdBlock();
23 + }
24 +
25 + @Override
26 + public synchronized T getNewId() {
27 + try {
28 + return convertFrom(idBlock.getNextId());
29 + } catch (UnavailableIdException e) {
30 + idBlock = allocator.allocateUniqueIdBlock();
31 + return convertFrom(idBlock.getNextId());
32 + }
33 + }
34 +
35 + /**
36 + * Returns an ID instance of {@code T} type from the long value.
37 + *
38 + * @param value original long value
39 + * @return ID instance
40 + */
41 + protected abstract T convertFrom(long value);
42 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +public class DummyIdBlockAllocator implements IdBlockAllocator {
4 + private long blockTop;
5 + private static final long BLOCK_SIZE = 0x1000000L;
6 +
7 + /**
8 + * Returns a block of IDs which are unique and unused.
9 + * Range of IDs is fixed size and is assigned incrementally as this method
10 + * called.
11 + *
12 + * @return an IdBlock containing a set of unique IDs
13 + */
14 + @Override
15 + public IdBlock allocateUniqueIdBlock() {
16 + synchronized (this) {
17 + long blockHead = blockTop;
18 + long blockTail = blockTop + BLOCK_SIZE;
19 +
20 + IdBlock block = new IdBlock(blockHead, BLOCK_SIZE);
21 + blockTop = blockTail;
22 +
23 + return block;
24 + }
25 + }
26 +
27 + @Override
28 + public IdBlock allocateUniqueIdBlock(long range) {
29 + throw new UnsupportedOperationException("Not supported yet");
30 + }
31 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import java.util.Arrays;
4 +import java.util.List;
5 +import java.util.Set;
6 +
7 +import org.apache.felix.scr.annotations.Activate;
8 +import org.apache.felix.scr.annotations.Component;
9 +import org.apache.felix.scr.annotations.Deactivate;
10 +import org.apache.felix.scr.annotations.Reference;
11 +import org.apache.felix.scr.annotations.ReferenceCardinality;
12 +import org.onlab.onos.net.ConnectPoint;
13 +import org.onlab.onos.net.Path;
14 +import org.onlab.onos.net.PortNumber;
15 +import org.onlab.onos.net.intent.HostToHostIntent;
16 +import org.onlab.onos.net.intent.IdGenerator;
17 +import org.onlab.onos.net.intent.Intent;
18 +import org.onlab.onos.net.intent.IntentCompiler;
19 +import org.onlab.onos.net.intent.IntentExtensionService;
20 +import org.onlab.onos.net.intent.IntentId;
21 +import org.onlab.onos.net.intent.PathIntent;
22 +import org.onlab.onos.net.topology.PathService;
23 +
24 +/**
25 + * A intent compiler for {@link HostToHostIntent}.
26 + */
27 +@Component(immediate = true)
28 +public class HostToHostIntentCompiler
29 + implements IntentCompiler<HostToHostIntent> {
30 +
31 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
32 + protected IntentExtensionService intentManager;
33 +
34 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
35 + protected PathService pathService;
36 +
37 + private IdGenerator<IntentId> intentIdGenerator;
38 +
39 + @Activate
40 + public void activate() {
41 + IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
42 + intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
43 + intentManager.registerCompiler(HostToHostIntent.class, this);
44 + }
45 +
46 + @Deactivate
47 + public void deactivate() {
48 + intentManager.unregisterCompiler(HostToHostIntent.class);
49 + }
50 +
51 + @Override
52 + public List<Intent> compile(HostToHostIntent intent) {
53 + Set<Path> paths = pathService.getPaths(intent.getSrc(), intent.getDst());
54 + if (paths.isEmpty()) {
55 + throw new PathNotFoundException();
56 + }
57 + Path path = paths.iterator().next();
58 +
59 + return Arrays.asList((Intent) new PathIntent(
60 + intentIdGenerator.getNewId(),
61 + intent.getTrafficSelector(),
62 + intent.getTrafficTreatment(),
63 + new ConnectPoint(intent.getSrc(), PortNumber.ALL),
64 + new ConnectPoint(intent.getDst(), PortNumber.ALL),
65 + path));
66 + }
67 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import static com.google.common.base.Preconditions.checkArgument;
4 +
5 +import java.util.Objects;
6 +import java.util.concurrent.atomic.AtomicLong;
7 +
8 +import com.google.common.base.MoreObjects;
9 +
10 +/**
11 + * A class representing an ID space.
12 + */
13 +public final class IdBlock {
14 + private final long start;
15 + private final long size;
16 +
17 + private final AtomicLong currentId;
18 +
19 + /**
20 + * Constructs a new ID block with the specified size and initial value.
21 + *
22 + * @param start initial value of the block
23 + * @param size size of the block
24 + * @throws IllegalArgumentException if the size is less than or equal to 0
25 + */
26 + public IdBlock(long start, long size) {
27 + checkArgument(size > 0, "size should be more than 0, but %s", size);
28 +
29 + this.start = start;
30 + this.size = size;
31 +
32 + this.currentId = new AtomicLong(start);
33 + }
34 +
35 + // TODO: consider if this method is needed or not
36 + /**
37 + * Returns the initial value.
38 + *
39 + * @return initial value
40 + */
41 + public long getStart() {
42 + return start;
43 + }
44 +
45 + // TODO: consider if this method is needed or not
46 + /**
47 + * Returns the last value.
48 + *
49 + * @return last value
50 + */
51 + public long getEnd() {
52 + return start + size - 1;
53 + }
54 +
55 + /**
56 + * Returns the block size.
57 + *
58 + * @return block size
59 + */
60 + public long getSize() {
61 + return size;
62 + }
63 +
64 + /**
65 + * Returns the next ID in the block.
66 + *
67 + * @return next ID
68 + * @throws UnavailableIdException if there is no available ID in the block.
69 + */
70 + public long getNextId() {
71 + final long id = currentId.getAndIncrement();
72 + if (id > getEnd()) {
73 + throw new UnavailableIdException(String.format(
74 + "used all IDs in allocated space (size: %d, end: %d, current: %d)",
75 + size, getEnd(), id
76 + ));
77 + }
78 +
79 + return id;
80 + }
81 +
82 + // TODO: Do we really need equals and hashCode? Should it contain currentId?
83 + @Override
84 + public boolean equals(Object o) {
85 + if (this == o) {
86 + return true;
87 + }
88 + if (o == null || getClass() != o.getClass()) {
89 + return false;
90 + }
91 +
92 + IdBlock that = (IdBlock) o;
93 + return Objects.equals(this.start, that.start)
94 + && Objects.equals(this.size, that.size)
95 + && Objects.equals(this.currentId.get(), that.currentId.get());
96 + }
97 +
98 + @Override
99 + public int hashCode() {
100 + return Objects.hash(start, size, currentId);
101 + }
102 +
103 + @Override
104 + public String toString() {
105 + return MoreObjects.toStringHelper(getClass())
106 + .add("start", start)
107 + .add("size", size)
108 + .add("currentId", currentId)
109 + .toString();
110 + }
111 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +/**
4 + * An interface that gives unique ID spaces.
5 + */
6 +public interface IdBlockAllocator {
7 + /**
8 + * Allocates a unique Id Block.
9 + *
10 + * @return Id Block.
11 + */
12 + IdBlock allocateUniqueIdBlock();
13 +
14 + /**
15 + * Allocates next unique id and retrieve a new range of ids if needed.
16 + *
17 + * @param range range to use for the identifier
18 + * @return Id Block.
19 + */
20 + IdBlock allocateUniqueIdBlock(long range);
21 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentId;
4 +
5 +/**
6 + * An implementation of {@link org.onlab.onos.net.intent.IdGenerator} of intent ID,
7 + * which uses {@link IdBlockAllocator}.
8 + */
9 +public class IdBlockAllocatorBasedIntentIdGenerator extends AbstractBlockAllocatorBasedIdGenerator<IntentId> {
10 +
11 + /**
12 + * Constructs an intent ID generator, which uses the specified ID block allocator
13 + * to generate a global unique intent ID.
14 + *
15 + * @param allocator the ID block allocator to use for generating intent IDs
16 + */
17 + public IdBlockAllocatorBasedIntentIdGenerator(IdBlockAllocator allocator) {
18 + super(allocator);
19 + }
20 +
21 + @Override
22 + protected IntentId convertFrom(long value) {
23 + return new IntentId(value);
24 + }
25 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentException;
4 +
5 +/**
6 + * An exception thrown when a intent compilation fails.
7 + */
8 +public class IntentCompilationException extends IntentException {
9 + private static final long serialVersionUID = 235237603018210810L;
10 +
11 + public IntentCompilationException() {
12 + super();
13 + }
14 +
15 + public IntentCompilationException(String message) {
16 + super(message);
17 + }
18 +
19 + public IntentCompilationException(String message, Throwable cause) {
20 + super(message, cause);
21 + }
22 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentException;
4 +
5 +/**
6 + * An exception thrown when intent installation fails.
7 + */
8 +public class IntentInstallationException extends IntentException {
9 + private static final long serialVersionUID = 3720268258616014168L;
10 +
11 + public IntentInstallationException() {
12 + super();
13 + }
14 +
15 + public IntentInstallationException(String message) {
16 + super(message);
17 + }
18 +
19 + public IntentInstallationException(String message, Throwable cause) {
20 + super(message, cause);
21 + }
22 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +import static org.onlab.onos.net.intent.IntentState.FAILED;
5 +import static org.onlab.onos.net.intent.IntentState.INSTALLED;
6 +import static org.onlab.onos.net.intent.IntentState.WITHDRAWING;
7 +import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
8 +import static org.slf4j.LoggerFactory.getLogger;
9 +
10 +import java.util.ArrayList;
11 +import java.util.List;
12 +import java.util.Map;
13 +import java.util.concurrent.ConcurrentHashMap;
14 +import java.util.concurrent.ConcurrentMap;
15 +import java.util.concurrent.CopyOnWriteArrayList;
16 +
17 +import org.apache.felix.scr.annotations.Activate;
18 +import org.apache.felix.scr.annotations.Component;
19 +import org.apache.felix.scr.annotations.Deactivate;
20 +import org.apache.felix.scr.annotations.Reference;
21 +import org.apache.felix.scr.annotations.ReferenceCardinality;
22 +import org.apache.felix.scr.annotations.Service;
23 +import org.onlab.onos.event.AbstractListenerRegistry;
24 +import org.onlab.onos.event.EventDeliveryService;
25 +import org.onlab.onos.net.intent.InstallableIntent;
26 +import org.onlab.onos.net.intent.Intent;
27 +import org.onlab.onos.net.intent.IntentCompiler;
28 +import org.onlab.onos.net.intent.IntentEvent;
29 +import org.onlab.onos.net.intent.IntentException;
30 +import org.onlab.onos.net.intent.IntentExtensionService;
31 +import org.onlab.onos.net.intent.IntentId;
32 +import org.onlab.onos.net.intent.IntentInstaller;
33 +import org.onlab.onos.net.intent.IntentListener;
34 +import org.onlab.onos.net.intent.IntentOperations;
35 +import org.onlab.onos.net.intent.IntentService;
36 +import org.onlab.onos.net.intent.IntentState;
37 +import org.onlab.onos.net.intent.IntentStore;
38 +import org.onlab.onos.net.intent.IntentStoreDelegate;
39 +import org.slf4j.Logger;
40 +
41 +import com.google.common.collect.ImmutableMap;
42 +
43 +/**
44 + * An implementation of Intent Manager.
45 + */
46 +@Component(immediate = true)
47 +@Service
48 +public class IntentManager
49 + implements IntentService, IntentExtensionService {
50 + private final Logger log = getLogger(getClass());
51 +
52 + public static final String INTENT_NULL = "Intent cannot be null";
53 + public static final String INTENT_ID_NULL = "Intent ID cannot be null";
54 +
55 + // Collections for compiler, installer, and listener are ONOS instance local
56 + private final ConcurrentMap<Class<? extends Intent>,
57 + IntentCompiler<? extends Intent>> compilers = new ConcurrentHashMap<>();
58 + private final ConcurrentMap<Class<? extends InstallableIntent>,
59 + IntentInstaller<? extends InstallableIntent>> installers = new ConcurrentHashMap<>();
60 + private final CopyOnWriteArrayList<IntentListener> listeners = new CopyOnWriteArrayList<>();
61 +
62 + private final AbstractListenerRegistry<IntentEvent, IntentListener>
63 + listenerRegistry = new AbstractListenerRegistry<>();
64 +
65 + private final IntentStoreDelegate delegate = new InternalStoreDelegate();
66 +
67 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 + protected IntentStore store;
69 +
70 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 + protected EventDeliveryService eventDispatcher;
72 +
73 + @Activate
74 + public void activate() {
75 + store.setDelegate(delegate);
76 + eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
77 +
78 +// this.intentEvents = new IntentMap<>("intentState", IntentEvent.class, collectionsService);
79 +// this.installableIntents =
80 +// new IntentMap<>("installableIntents", IntentCompilationResult.class, collectionsService);
81 +//
82 +//
83 +// this.intentEvents.addListener(new InternalEntryListener(new InternalIntentEventListener()));
84 +
85 + log.info("Started");
86 + }
87 +
88 + @Deactivate
89 + public void deactivate() {
90 + store.unsetDelegate(delegate);
91 + eventDispatcher.removeSink(IntentEvent.class);
92 + log.info("Stopped");
93 + }
94 +
95 + @Override
96 + public void submit(Intent intent) {
97 + checkNotNull(intent, INTENT_NULL);
98 + registerSubclassCompilerIfNeeded(intent);
99 + IntentEvent event = store.createIntent(intent);
100 + eventDispatcher.post(event);
101 + processStoreEvent(event);
102 + }
103 +
104 + @Override
105 + public void withdraw(Intent intent) {
106 + checkNotNull(intent, INTENT_NULL);
107 + IntentEvent event = store.setState(intent, WITHDRAWING);
108 + eventDispatcher.post(event);
109 + processStoreEvent(event);
110 + }
111 +
112 + // FIXME: implement this method
113 + @Override
114 + public void execute(IntentOperations operations) {
115 + throw new UnsupportedOperationException("execute() is not implemented yet");
116 + }
117 +
118 + @Override
119 + public Iterable<Intent> getIntents() {
120 + return store.getIntents();
121 + }
122 +
123 + @Override
124 + public long getIntentCount() {
125 + return store.getIntentCount();
126 + }
127 +
128 + @Override
129 + public Intent getIntent(IntentId id) {
130 + checkNotNull(id, INTENT_ID_NULL);
131 + return store.getIntent(id);
132 + }
133 +
134 + @Override
135 + public IntentState getIntentState(IntentId id) {
136 + checkNotNull(id, INTENT_ID_NULL);
137 + return store.getIntentState(id);
138 + }
139 +
140 + @Override
141 + public void addListener(IntentListener listener) {
142 + listenerRegistry.addListener(listener);
143 + }
144 +
145 + @Override
146 + public void removeListener(IntentListener listener) {
147 + listenerRegistry.removeListener(listener);
148 + }
149 +
150 + @Override
151 + public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
152 + compilers.put(cls, compiler);
153 + }
154 +
155 + @Override
156 + public <T extends Intent> void unregisterCompiler(Class<T> cls) {
157 + compilers.remove(cls);
158 + }
159 +
160 + @Override
161 + public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
162 + return ImmutableMap.copyOf(compilers);
163 + }
164 +
165 + @Override
166 + public <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
167 + installers.put(cls, installer);
168 + }
169 +
170 + @Override
171 + public <T extends InstallableIntent> void unregisterInstaller(Class<T> cls) {
172 + installers.remove(cls);
173 + }
174 +
175 + @Override
176 + public Map<Class<? extends InstallableIntent>, IntentInstaller<? extends InstallableIntent>> getInstallers() {
177 + return ImmutableMap.copyOf(installers);
178 + }
179 +
180 + /**
181 + * Invokes all of registered intent event listener.
182 + *
183 + * @param event event supplied to a listener as an argument
184 + */
185 + private void invokeListeners(IntentEvent event) {
186 + for (IntentListener listener : listeners) {
187 + listener.event(event);
188 + }
189 + }
190 +
191 + /**
192 + * Returns the corresponding intent compiler to the specified intent.
193 + *
194 + * @param intent intent
195 + * @param <T> the type of intent
196 + * @return intent compiler corresponding to the specified intent
197 + */
198 + private <T extends Intent> IntentCompiler<T> getCompiler(T intent) {
199 + @SuppressWarnings("unchecked")
200 + IntentCompiler<T> compiler = (IntentCompiler<T>) compilers.get(intent.getClass());
201 + if (compiler == null) {
202 + throw new IntentException("no compiler for class " + intent.getClass());
203 + }
204 + return compiler;
205 + }
206 +
207 + /**
208 + * Returns the corresponding intent installer to the specified installable intent.
209 + * @param intent intent
210 + * @param <T> the type of installable intent
211 + * @return intent installer corresponding to the specified installable intent
212 + */
213 + private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) {
214 + @SuppressWarnings("unchecked")
215 + IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass());
216 + if (installer == null) {
217 + throw new IntentException("no installer for class " + intent.getClass());
218 + }
219 + return installer;
220 + }
221 +
222 + /**
223 + * Compiles an intent.
224 + *
225 + * @param intent intent
226 + */
227 + private void compileIntent(Intent intent) {
228 + // FIXME: To make SDN-IP workable ASAP, only single level compilation is implemented
229 + // TODO: implement compilation traversing tree structure
230 + List<InstallableIntent> installable = new ArrayList<>();
231 + for (Intent compiled : getCompiler(intent).compile(intent)) {
232 + installable.add((InstallableIntent) compiled);
233 + }
234 + IntentEvent event = store.addInstallableIntents(intent.getId(), installable);
235 + eventDispatcher.post(event);
236 + processStoreEvent(event);
237 + }
238 +
239 + /**
240 + * Installs an intent.
241 + *
242 + * @param intent intent
243 + */
244 + private void installIntent(Intent intent) {
245 + for (InstallableIntent installable : store.getInstallableIntents(intent.getId())) {
246 + registerSubclassInstallerIfNeeded(installable);
247 + getInstaller(installable).install(installable);
248 + }
249 +
250 + IntentEvent event = store.setState(intent, INSTALLED);
251 + eventDispatcher.post(event);
252 + processStoreEvent(event);
253 +
254 + }
255 +
256 + /**
257 + * Uninstalls an intent.
258 + *
259 + * @param intent intent
260 + */
261 + private void uninstallIntent(Intent intent) {
262 + for (InstallableIntent installable : store.getInstallableIntents(intent.getId())) {
263 + getInstaller(installable).uninstall(installable);
264 + }
265 +
266 + store.removeInstalledIntents(intent.getId());
267 + store.setState(intent, WITHDRAWN);
268 + }
269 +
270 + /**
271 + * Registers an intent compiler of the specified intent if an intent compiler
272 + * for the intent is not registered. This method traverses the class hierarchy of
273 + * the intent. Once an intent compiler for a parent type is found, this method
274 + * registers the found intent compiler.
275 + *
276 + * @param intent intent
277 + */
278 + private void registerSubclassCompilerIfNeeded(Intent intent) {
279 + if (!compilers.containsKey(intent.getClass())) {
280 + Class<?> cls = intent.getClass();
281 + while (cls != Object.class) {
282 + // As long as we're within the Intent class descendants
283 + if (Intent.class.isAssignableFrom(cls)) {
284 + IntentCompiler<?> compiler = compilers.get(cls);
285 + if (compiler != null) {
286 + compilers.put(intent.getClass(), compiler);
287 + return;
288 + }
289 + }
290 + cls = cls.getSuperclass();
291 + }
292 + }
293 + }
294 +
295 + /**
296 + * Registers an intent installer of the specified intent if an intent installer
297 + * for the intent is not registered. This method traverses the class hierarchy of
298 + * the intent. Once an intent installer for a parent type is found, this method
299 + * registers the found intent installer.
300 + *
301 + * @param intent intent
302 + */
303 + private void registerSubclassInstallerIfNeeded(InstallableIntent intent) {
304 + if (!installers.containsKey(intent.getClass())) {
305 + Class<?> cls = intent.getClass();
306 + while (cls != Object.class) {
307 + // As long as we're within the InstallableIntent class descendants
308 + if (InstallableIntent.class.isAssignableFrom(cls)) {
309 + IntentInstaller<?> installer = installers.get(cls);
310 + if (installer != null) {
311 + installers.put(intent.getClass(), installer);
312 + return;
313 + }
314 + }
315 + cls = cls.getSuperclass();
316 + }
317 + }
318 + }
319 +
320 + /**
321 + * Handles state transition of submitted intents.
322 + */
323 + private void processStoreEvent(IntentEvent event) {
324 + invokeListeners(event);
325 + Intent intent = event.getIntent();
326 +
327 + try {
328 + switch (event.getState()) {
329 + case SUBMITTED:
330 + compileIntent(intent);
331 + break;
332 + case COMPILED:
333 + installIntent(intent);
334 + break;
335 + case INSTALLED:
336 + break;
337 + case WITHDRAWING:
338 + uninstallIntent(intent);
339 + break;
340 + case WITHDRAWN:
341 + break;
342 + case FAILED:
343 + break;
344 + default:
345 + throw new IllegalStateException(
346 + "the state of IntentEvent is illegal: " + event.getState());
347 + }
348 + } catch (IntentException e) {
349 + store.setState(intent, FAILED);
350 + }
351 +
352 + }
353 +
354 + // Store delegate to re-post events emitted from the store.
355 + private class InternalStoreDelegate implements IntentStoreDelegate {
356 + @Override
357 + public void notify(IntentEvent event) {
358 + processStoreEvent(event);
359 + eventDispatcher.post(event);
360 + }
361 + }
362 +
363 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentException;
4 +
5 +/**
6 + * An exception thrown when intent removal failed.
7 + */
8 +public class IntentRemovalException extends IntentException {
9 + private static final long serialVersionUID = -5259226322037891951L;
10 +
11 + public IntentRemovalException() {
12 + super();
13 + }
14 +
15 + public IntentRemovalException(String message) {
16 + super(message);
17 + }
18 +
19 + public IntentRemovalException(String message, Throwable cause) {
20 + super(message, cause);
21 + }
22 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.apache.felix.scr.annotations.Activate;
4 +import org.apache.felix.scr.annotations.Component;
5 +import org.apache.felix.scr.annotations.Deactivate;
6 +import org.apache.felix.scr.annotations.Reference;
7 +import org.apache.felix.scr.annotations.ReferenceCardinality;
8 +import org.onlab.onos.ApplicationId;
9 +import org.onlab.onos.net.ConnectPoint;
10 +import org.onlab.onos.net.Link;
11 +import org.onlab.onos.net.flow.DefaultFlowRule;
12 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
13 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
14 +import org.onlab.onos.net.flow.FlowRule;
15 +import org.onlab.onos.net.flow.FlowRuleService;
16 +import org.onlab.onos.net.flow.TrafficSelector;
17 +import org.onlab.onos.net.flow.TrafficTreatment;
18 +import org.onlab.onos.net.intent.IntentExtensionService;
19 +import org.onlab.onos.net.intent.IntentInstaller;
20 +import org.onlab.onos.net.intent.PathIntent;
21 +
22 +import java.util.Iterator;
23 +
24 +/**
25 + * Installer for {@link PathIntent path connectivity intents}.
26 + */
27 +@Component(immediate = true)
28 +public class PathIntentInstaller implements IntentInstaller<PathIntent> {
29 +
30 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
31 + protected IntentExtensionService intentManager;
32 +
33 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
34 + protected FlowRuleService flowRuleService;
35 +
36 + private final ApplicationId appId = ApplicationId.getAppId();
37 +
38 + @Activate
39 + public void activate() {
40 + intentManager.registerInstaller(PathIntent.class, this);
41 + }
42 +
43 + @Deactivate
44 + public void deactivate() {
45 + intentManager.unregisterInstaller(PathIntent.class);
46 + }
47 +
48 + @Override
49 + public void install(PathIntent intent) {
50 + TrafficSelector.Builder builder =
51 + DefaultTrafficSelector.builder(intent.getTrafficSelector());
52 + Iterator<Link> links = intent.getPath().links().iterator();
53 + ConnectPoint prev = links.next().dst();
54 + while (links.hasNext()) {
55 + builder.matchInport(prev.port());
56 + Link link = links.next();
57 +
58 + TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
59 + treat.setOutput(link.src().port());
60 +
61 + FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
62 + builder.build(), treat.build(),
63 + 0, appId, 30);
64 + flowRuleService.applyFlowRules(rule);
65 +
66 + prev = link.dst();
67 + }
68 +
69 + }
70 +
71 + @Override
72 + public void uninstall(PathIntent intent) {
73 + //TODO
74 + }
75 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentException;
4 +
5 +/**
6 + * An exception thrown when a path is not found.
7 + */
8 +public class PathNotFoundException extends IntentException {
9 + private static final long serialVersionUID = -2087045731049914733L;
10 +
11 + public PathNotFoundException() {
12 + super();
13 + }
14 +
15 + public PathNotFoundException(String message) {
16 + super(message);
17 + }
18 +
19 + public PathNotFoundException(String message, Throwable cause) {
20 + super(message, cause);
21 + }
22 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +/**
4 + * Represents that there is no available IDs.
5 + */
6 +public class UnavailableIdException extends RuntimeException {
7 +
8 + private static final long serialVersionUID = -2287403908433720122L;
9 +
10 + /**
11 + * Constructs an exception with no message and no underlying cause.
12 + */
13 + public UnavailableIdException() {
14 + }
15 +
16 + /**
17 + * Constructs an exception with the specified message.
18 + *
19 + * @param message the message describing the specific nature of the error
20 + */
21 + public UnavailableIdException(String message) {
22 + super(message);
23 + }
24 +
25 + /**
26 + * Constructs an exception with the specified message and the underlying cause.
27 + *
28 + * @param message the message describing the specific nature of the error
29 + * @param cause the underlying cause of this error
30 + */
31 + public UnavailableIdException(String message, Throwable cause) {
32 + super(message, cause);
33 + }
34 +}
1 +/**
2 + * Core subsystem for tracking high-level intents for treatment of selected
3 + * network traffic.
4 + */
5 +package org.onlab.onos.net.intent.impl;
...\ No newline at end of file ...\ No newline at end of file
...@@ -43,7 +43,6 @@ import com.google.common.collect.HashMultimap; ...@@ -43,7 +43,6 @@ import com.google.common.collect.HashMultimap;
43 import com.google.common.collect.Lists; 43 import com.google.common.collect.Lists;
44 import com.google.common.collect.Multimap; 44 import com.google.common.collect.Multimap;
45 45
46 -
47 @Component(immediate = true) 46 @Component(immediate = true)
48 @Service 47 @Service
49 public class ProxyArpManager implements ProxyArpService { 48 public class ProxyArpManager implements ProxyArpService {
...@@ -128,7 +127,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -128,7 +127,7 @@ public class ProxyArpManager implements ProxyArpService {
128 127
129 Ethernet arpReply = buildArpReply(dst, eth); 128 Ethernet arpReply = buildArpReply(dst, eth);
130 // TODO: check send status with host service. 129 // TODO: check send status with host service.
131 - TrafficTreatment.Builder builder = new DefaultTrafficTreatment.Builder(); 130 + TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
132 builder.setOutput(src.location().port()); 131 builder.setOutput(src.location().port());
133 packetService.emit(new DefaultOutboundPacket(src.location().deviceId(), 132 packetService.emit(new DefaultOutboundPacket(src.location().deviceId(),
134 builder.build(), ByteBuffer.wrap(arpReply.serialize()))); 133 builder.build(), ByteBuffer.wrap(arpReply.serialize())));
...@@ -148,7 +147,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -148,7 +147,7 @@ public class ProxyArpManager implements ProxyArpService {
148 if (h == null) { 147 if (h == null) {
149 flood(eth); 148 flood(eth);
150 } else { 149 } else {
151 - TrafficTreatment.Builder builder = new DefaultTrafficTreatment.Builder(); 150 + TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
152 builder.setOutput(h.location().port()); 151 builder.setOutput(h.location().port());
153 packetService.emit(new DefaultOutboundPacket(h.location().deviceId(), 152 packetService.emit(new DefaultOutboundPacket(h.location().deviceId(),
154 builder.build(), ByteBuffer.wrap(eth.serialize()))); 153 builder.build(), ByteBuffer.wrap(eth.serialize())));
...@@ -166,7 +165,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -166,7 +165,7 @@ public class ProxyArpManager implements ProxyArpService {
166 165
167 synchronized (externalPorts) { 166 synchronized (externalPorts) {
168 for (Entry<Device, PortNumber> entry : externalPorts.entries()) { 167 for (Entry<Device, PortNumber> entry : externalPorts.entries()) {
169 - builder = new DefaultTrafficTreatment.Builder(); 168 + builder = DefaultTrafficTreatment.builder();
170 builder.setOutput(entry.getValue()); 169 builder.setOutput(entry.getValue());
171 packetService.emit(new DefaultOutboundPacket(entry.getKey().id(), 170 packetService.emit(new DefaultOutboundPacket(entry.getKey().id(),
172 builder.build(), buf)); 171 builder.build(), buf));
......
1 package org.onlab.onos.store.cluster.impl; 1 package org.onlab.onos.store.cluster.impl;
2 2
3 -import de.javakaffee.kryoserializers.URISerializer;
4 import org.apache.felix.scr.annotations.Activate; 3 import org.apache.felix.scr.annotations.Activate;
5 import org.apache.felix.scr.annotations.Component; 4 import org.apache.felix.scr.annotations.Component;
6 import org.apache.felix.scr.annotations.Deactivate; 5 import org.apache.felix.scr.annotations.Deactivate;
7 import org.apache.felix.scr.annotations.Service; 6 import org.apache.felix.scr.annotations.Service;
8 -import org.onlab.onos.cluster.ControllerNode;
9 -import org.onlab.onos.cluster.DefaultControllerNode;
10 -import org.onlab.onos.cluster.NodeId;
11 -import org.onlab.onos.net.ConnectPoint;
12 -import org.onlab.onos.net.DefaultDevice;
13 -import org.onlab.onos.net.DefaultLink;
14 -import org.onlab.onos.net.DefaultPort;
15 -import org.onlab.onos.net.Device;
16 -import org.onlab.onos.net.DeviceId;
17 -import org.onlab.onos.net.Element;
18 -import org.onlab.onos.net.Link;
19 -import org.onlab.onos.net.LinkKey;
20 -import org.onlab.onos.net.MastershipRole;
21 -import org.onlab.onos.net.Port;
22 -import org.onlab.onos.net.PortNumber;
23 -import org.onlab.onos.net.provider.ProviderId;
24 import org.onlab.onos.store.cluster.messaging.MessageSubject; 7 import org.onlab.onos.store.cluster.messaging.MessageSubject;
25 import org.onlab.onos.store.cluster.messaging.SerializationService; 8 import org.onlab.onos.store.cluster.messaging.SerializationService;
26 -import org.onlab.onos.store.serializers.ConnectPointSerializer; 9 +import org.onlab.onos.store.serializers.KryoPoolUtil;
27 -import org.onlab.onos.store.serializers.DefaultLinkSerializer;
28 -import org.onlab.onos.store.serializers.DefaultPortSerializer;
29 -import org.onlab.onos.store.serializers.DeviceIdSerializer;
30 -import org.onlab.onos.store.serializers.IpPrefixSerializer;
31 -import org.onlab.onos.store.serializers.LinkKeySerializer;
32 -import org.onlab.onos.store.serializers.NodeIdSerializer;
33 -import org.onlab.onos.store.serializers.PortNumberSerializer;
34 -import org.onlab.onos.store.serializers.ProviderIdSerializer;
35 -import org.onlab.packet.IpPrefix;
36 import org.onlab.util.KryoPool; 10 import org.onlab.util.KryoPool;
37 import org.slf4j.Logger; 11 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory; 12 import org.slf4j.LoggerFactory;
39 13
40 -import java.net.URI;
41 -import java.util.ArrayList;
42 -import java.util.HashMap;
43 -
44 /** 14 /**
45 * Factory for parsing messages sent between cluster members. 15 * Factory for parsing messages sent between cluster members.
46 */ 16 */
...@@ -72,34 +42,10 @@ public class MessageSerializer implements SerializationService { ...@@ -72,34 +42,10 @@ public class MessageSerializer implements SerializationService {
72 * Sets up the common serialzers pool. 42 * Sets up the common serialzers pool.
73 */ 43 */
74 protected void setupKryoPool() { 44 protected void setupKryoPool() {
75 - // FIXME Slice out types used in common to separate pool/namespace.
76 serializerPool = KryoPool.newBuilder() 45 serializerPool = KryoPool.newBuilder()
77 - .register(ArrayList.class, 46 + .register(KryoPoolUtil.API)
78 - HashMap.class, 47 + // TODO: Should MessageSubject be in API bundle?
79 - 48 + .register(MessageSubject.class)
80 - ControllerNode.State.class,
81 - Device.Type.class,
82 -
83 - DefaultControllerNode.class,
84 - DefaultDevice.class,
85 - MastershipRole.class,
86 - Port.class,
87 - Element.class,
88 -
89 - Link.Type.class,
90 -
91 - MessageSubject.class
92 - )
93 - .register(IpPrefix.class, new IpPrefixSerializer())
94 - .register(URI.class, new URISerializer())
95 - .register(NodeId.class, new NodeIdSerializer())
96 - .register(ProviderId.class, new ProviderIdSerializer())
97 - .register(DeviceId.class, new DeviceIdSerializer())
98 - .register(PortNumber.class, new PortNumberSerializer())
99 - .register(DefaultPort.class, new DefaultPortSerializer())
100 - .register(LinkKey.class, new LinkKeySerializer())
101 - .register(ConnectPoint.class, new ConnectPointSerializer())
102 - .register(DefaultLink.class, new DefaultLinkSerializer())
103 .build() 49 .build()
104 .populate(1); 50 .populate(1);
105 } 51 }
...@@ -114,4 +60,4 @@ public class MessageSerializer implements SerializationService { ...@@ -114,4 +60,4 @@ public class MessageSerializer implements SerializationService {
114 public byte[] encode(Object payload) { 60 public byte[] encode(Object payload) {
115 return serializerPool.serialize(payload); 61 return serializerPool.serialize(payload);
116 } 62 }
117 -}
...\ No newline at end of file ...\ No newline at end of file
63 +}
......
1 +/**
2 + * Implementation of the cluster messaging mechanism.
3 + */
4 +package org.onlab.onos.store.cluster.messaging.impl;
...\ No newline at end of file ...\ No newline at end of file
1 -package org.onlab.onos.store.impl; 1 +package org.onlab.onos.store.common.impl;
2 2
3 import static com.google.common.base.Preconditions.checkArgument; 3 import static com.google.common.base.Preconditions.checkArgument;
4 4
...@@ -9,12 +9,11 @@ import org.onlab.onos.store.Timestamp; ...@@ -9,12 +9,11 @@ import org.onlab.onos.store.Timestamp;
9 import com.google.common.base.MoreObjects; 9 import com.google.common.base.MoreObjects;
10 import com.google.common.collect.ComparisonChain; 10 import com.google.common.collect.ComparisonChain;
11 11
12 -// If it is store specific, implement serializable interfaces?
13 /** 12 /**
14 * Default implementation of Timestamp. 13 * Default implementation of Timestamp.
15 * TODO: Better documentation. 14 * TODO: Better documentation.
16 */ 15 */
17 -public final class OnosTimestamp implements Timestamp { 16 +public final class MastershipBasedTimestamp implements Timestamp {
18 17
19 private final int termNumber; 18 private final int termNumber;
20 private final int sequenceNumber; 19 private final int sequenceNumber;
...@@ -25,15 +24,16 @@ public final class OnosTimestamp implements Timestamp { ...@@ -25,15 +24,16 @@ public final class OnosTimestamp implements Timestamp {
25 * @param termNumber the mastership termNumber 24 * @param termNumber the mastership termNumber
26 * @param sequenceNumber the sequenceNumber number within the termNumber 25 * @param sequenceNumber the sequenceNumber number within the termNumber
27 */ 26 */
28 - public OnosTimestamp(int termNumber, int sequenceNumber) { 27 + public MastershipBasedTimestamp(int termNumber, int sequenceNumber) {
29 this.termNumber = termNumber; 28 this.termNumber = termNumber;
30 this.sequenceNumber = sequenceNumber; 29 this.sequenceNumber = sequenceNumber;
31 } 30 }
32 31
33 @Override 32 @Override
34 public int compareTo(Timestamp o) { 33 public int compareTo(Timestamp o) {
35 - checkArgument(o instanceof OnosTimestamp, "Must be OnosTimestamp", o); 34 + checkArgument(o instanceof MastershipBasedTimestamp,
36 - OnosTimestamp that = (OnosTimestamp) o; 35 + "Must be MastershipBasedTimestamp", o);
36 + MastershipBasedTimestamp that = (MastershipBasedTimestamp) o;
37 37
38 return ComparisonChain.start() 38 return ComparisonChain.start()
39 .compare(this.termNumber, that.termNumber) 39 .compare(this.termNumber, that.termNumber)
...@@ -51,10 +51,10 @@ public final class OnosTimestamp implements Timestamp { ...@@ -51,10 +51,10 @@ public final class OnosTimestamp implements Timestamp {
51 if (this == obj) { 51 if (this == obj) {
52 return true; 52 return true;
53 } 53 }
54 - if (!(obj instanceof OnosTimestamp)) { 54 + if (!(obj instanceof MastershipBasedTimestamp)) {
55 return false; 55 return false;
56 } 56 }
57 - OnosTimestamp that = (OnosTimestamp) obj; 57 + MastershipBasedTimestamp that = (MastershipBasedTimestamp) obj;
58 return Objects.equals(this.termNumber, that.termNumber) && 58 return Objects.equals(this.termNumber, that.termNumber) &&
59 Objects.equals(this.sequenceNumber, that.sequenceNumber); 59 Objects.equals(this.sequenceNumber, that.sequenceNumber);
60 } 60 }
...@@ -84,4 +84,11 @@ public final class OnosTimestamp implements Timestamp { ...@@ -84,4 +84,11 @@ public final class OnosTimestamp implements Timestamp {
84 public int sequenceNumber() { 84 public int sequenceNumber() {
85 return sequenceNumber; 85 return sequenceNumber;
86 } 86 }
87 +
88 + // Default constructor for serialization
89 + @Deprecated
90 + protected MastershipBasedTimestamp() {
91 + this.termNumber = -1;
92 + this.sequenceNumber = -1;
93 + }
87 } 94 }
......
1 +package org.onlab.onos.store.common.impl;
2 +
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +
5 +import java.util.Objects;
6 +
7 +import org.onlab.onos.store.Timestamp;
8 +
9 +/**
10 + * Wrapper class to store Timestamped value.
11 + * @param <T>
12 + */
13 +public final class Timestamped<T> {
14 +
15 + private final Timestamp timestamp;
16 + private final T value;
17 +
18 + /**
19 + * Creates a time stamped value.
20 + *
21 + * @param value to be timestamp
22 + * @param timestamp the timestamp
23 + */
24 + public Timestamped(T value, Timestamp timestamp) {
25 + this.value = checkNotNull(value);
26 + this.timestamp = checkNotNull(timestamp);
27 + }
28 +
29 + /**
30 + * Returns the value.
31 + * @return value
32 + */
33 + public T value() {
34 + return value;
35 + }
36 +
37 + /**
38 + * Returns the time stamp.
39 + * @return time stamp
40 + */
41 + public Timestamp timestamp() {
42 + return timestamp;
43 + }
44 +
45 + /**
46 + * Tests if this timestamped value is newer than the other.
47 + *
48 + * @param other timestamped value
49 + * @return true if this instance is newer.
50 + */
51 + public boolean isNewer(Timestamped<T> other) {
52 + return this.timestamp.compareTo(checkNotNull(other).timestamp()) > 0;
53 + }
54 +
55 + @Override
56 + public int hashCode() {
57 + return timestamp.hashCode();
58 + }
59 +
60 + @Override
61 + public boolean equals(Object obj) {
62 + if (this == obj) {
63 + return true;
64 + }
65 + if (!(obj instanceof Timestamped)) {
66 + return false;
67 + }
68 + @SuppressWarnings("unchecked")
69 + Timestamped<T> that = (Timestamped<T>) obj;
70 + return Objects.equals(this.timestamp, that.timestamp);
71 + }
72 +
73 + // Default constructor for serialization
74 + @Deprecated
75 + protected Timestamped() {
76 + this.value = null;
77 + this.timestamp = null;
78 + }
79 +}
1 +/**
2 + * Common abstractions and facilities for implementing distributed store
3 + * using gossip protocol.
4 + */
5 +package org.onlab.onos.store.common.impl;
...@@ -12,14 +12,18 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -12,14 +12,18 @@ import org.apache.felix.scr.annotations.Deactivate;
12 import org.apache.felix.scr.annotations.Service; 12 import org.apache.felix.scr.annotations.Service;
13 import org.onlab.onos.cluster.MastershipTerm; 13 import org.onlab.onos.cluster.MastershipTerm;
14 import org.onlab.onos.net.DeviceId; 14 import org.onlab.onos.net.DeviceId;
15 +import org.onlab.onos.store.ClockProviderService;
15 import org.onlab.onos.store.ClockService; 16 import org.onlab.onos.store.ClockService;
16 import org.onlab.onos.store.Timestamp; 17 import org.onlab.onos.store.Timestamp;
17 -import org.onlab.onos.store.impl.OnosTimestamp; 18 +import org.onlab.onos.store.common.impl.MastershipBasedTimestamp;
18 import org.slf4j.Logger; 19 import org.slf4j.Logger;
19 20
21 +/**
22 + * Clock service to issue Timestamp based on Device Mastership.
23 + */
20 @Component(immediate = true) 24 @Component(immediate = true)
21 @Service 25 @Service
22 -public class OnosClockService implements ClockService { 26 +public class DeviceClockManager implements ClockService, ClockProviderService {
23 27
24 private final Logger log = getLogger(getClass()); 28 private final Logger log = getLogger(getClass());
25 29
...@@ -43,7 +47,7 @@ public class OnosClockService implements ClockService { ...@@ -43,7 +47,7 @@ public class OnosClockService implements ClockService {
43 if (term == null) { 47 if (term == null) {
44 throw new IllegalStateException("Requesting timestamp for a deviceId without mastership"); 48 throw new IllegalStateException("Requesting timestamp for a deviceId without mastership");
45 } 49 }
46 - return new OnosTimestamp(term.termNumber(), ticker.incrementAndGet()); 50 + return new MastershipBasedTimestamp(term.termNumber(), ticker.incrementAndGet());
47 } 51 }
48 52
49 @Override 53 @Override
......
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import com.google.common.collect.FluentIterable;
4 +import com.google.common.collect.ImmutableList;
5 +
6 +import org.apache.commons.lang3.concurrent.ConcurrentException;
7 +import org.apache.commons.lang3.concurrent.ConcurrentInitializer;
8 +import org.apache.felix.scr.annotations.Activate;
9 +import org.apache.felix.scr.annotations.Component;
10 +import org.apache.felix.scr.annotations.Deactivate;
11 +import org.apache.felix.scr.annotations.Reference;
12 +import org.apache.felix.scr.annotations.ReferenceCardinality;
13 +import org.apache.felix.scr.annotations.Service;
14 +import org.onlab.onos.net.Annotations;
15 +import org.onlab.onos.net.DefaultAnnotations;
16 +import org.onlab.onos.net.DefaultDevice;
17 +import org.onlab.onos.net.DefaultPort;
18 +import org.onlab.onos.net.Device;
19 +import org.onlab.onos.net.Device.Type;
20 +import org.onlab.onos.net.DeviceId;
21 +import org.onlab.onos.net.Port;
22 +import org.onlab.onos.net.PortNumber;
23 +import org.onlab.onos.net.SparseAnnotations;
24 +import org.onlab.onos.net.device.DefaultDeviceDescription;
25 +import org.onlab.onos.net.device.DefaultPortDescription;
26 +import org.onlab.onos.net.device.DeviceDescription;
27 +import org.onlab.onos.net.device.DeviceEvent;
28 +import org.onlab.onos.net.device.DeviceStore;
29 +import org.onlab.onos.net.device.DeviceStoreDelegate;
30 +import org.onlab.onos.net.device.PortDescription;
31 +import org.onlab.onos.net.provider.ProviderId;
32 +import org.onlab.onos.store.AbstractStore;
33 +import org.onlab.onos.store.ClockService;
34 +import org.onlab.onos.store.Timestamp;
35 +import org.onlab.onos.store.common.impl.Timestamped;
36 +import org.slf4j.Logger;
37 +
38 +import java.util.ArrayList;
39 +import java.util.Collections;
40 +import java.util.HashSet;
41 +import java.util.Iterator;
42 +import java.util.List;
43 +import java.util.Map;
44 +import java.util.Map.Entry;
45 +import java.util.Objects;
46 +import java.util.Set;
47 +import java.util.concurrent.ConcurrentHashMap;
48 +import java.util.concurrent.ConcurrentMap;
49 +import java.util.concurrent.atomic.AtomicReference;
50 +
51 +import static com.google.common.base.Preconditions.checkArgument;
52 +import static com.google.common.base.Preconditions.checkNotNull;
53 +import static com.google.common.base.Predicates.notNull;
54 +import static org.onlab.onos.net.device.DeviceEvent.Type.*;
55 +import static org.slf4j.LoggerFactory.getLogger;
56 +import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked;
57 +import static org.onlab.onos.net.DefaultAnnotations.merge;
58 +import static com.google.common.base.Verify.verify;
59 +
60 +// TODO: implement remove event handling and call *Internal
61 +/**
62 + * Manages inventory of infrastructure devices using gossip protocol to distribute
63 + * information.
64 + */
65 +@Component(immediate = true)
66 +@Service
67 +public class GossipDeviceStore
68 + extends AbstractStore<DeviceEvent, DeviceStoreDelegate>
69 + implements DeviceStore {
70 +
71 + private final Logger log = getLogger(getClass());
72 +
73 + public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
74 +
75 + // TODO: Check if inner Map can be replaced with plain Map
76 + // innerMap is used to lock a Device, thus instance should never be replaced.
77 + // collection of Description given from various providers
78 + private final ConcurrentMap<DeviceId,
79 + ConcurrentMap<ProviderId, DeviceDescriptions>>
80 + deviceDescs = new ConcurrentHashMap<>();
81 +
82 + // cache of Device and Ports generated by compositing descriptions from providers
83 + private final ConcurrentMap<DeviceId, Device> devices = new ConcurrentHashMap<>();
84 + private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> devicePorts = new ConcurrentHashMap<>();
85 +
86 + // available(=UP) devices
87 + private final Set<DeviceId> availableDevices = new HashSet<>();
88 +
89 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 + protected ClockService clockService;
91 +
92 + @Activate
93 + public void activate() {
94 + log.info("Started");
95 + }
96 +
97 + @Deactivate
98 + public void deactivate() {
99 + deviceDescs.clear();
100 + devices.clear();
101 + devicePorts.clear();
102 + availableDevices.clear();
103 + log.info("Stopped");
104 + }
105 +
106 + @Override
107 + public int getDeviceCount() {
108 + return devices.size();
109 + }
110 +
111 + @Override
112 + public Iterable<Device> getDevices() {
113 + return Collections.unmodifiableCollection(devices.values());
114 + }
115 +
116 + @Override
117 + public Device getDevice(DeviceId deviceId) {
118 + return devices.get(deviceId);
119 + }
120 +
121 + @Override
122 + public synchronized DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId,
123 + DeviceDescription deviceDescription) {
124 + Timestamp newTimestamp = clockService.getTimestamp(deviceId);
125 + final Timestamped<DeviceDescription> deltaDesc = new Timestamped<>(deviceDescription, newTimestamp);
126 + DeviceEvent event = createOrUpdateDeviceInternal(providerId, deviceId, deltaDesc);
127 + if (event != null) {
128 + // FIXME: broadcast deltaDesc, UP
129 + log.debug("broadcast deltaDesc");
130 + }
131 + return event;
132 + }
133 +
134 + private DeviceEvent createOrUpdateDeviceInternal(ProviderId providerId, DeviceId deviceId,
135 + Timestamped<DeviceDescription> deltaDesc) {
136 +
137 + // Collection of DeviceDescriptions for a Device
138 + ConcurrentMap<ProviderId, DeviceDescriptions> providerDescs
139 + = createIfAbsentUnchecked(deviceDescs, deviceId,
140 + new InitConcurrentHashMap<ProviderId, DeviceDescriptions>());
141 +
142 +
143 + DeviceDescriptions descs
144 + = createIfAbsentUnchecked(providerDescs, providerId,
145 + new InitDeviceDescs(deltaDesc));
146 +
147 + // update description
148 + synchronized (providerDescs) {
149 + // locking per device
150 +
151 + final Device oldDevice = devices.get(deviceId);
152 + final Device newDevice;
153 +
154 + if (deltaDesc == descs.getDeviceDesc() ||
155 + deltaDesc.isNewer(descs.getDeviceDesc())) {
156 + // on new device or valid update
157 + descs.putDeviceDesc(deltaDesc);
158 + newDevice = composeDevice(deviceId, providerDescs);
159 + } else {
160 + // outdated event, ignored.
161 + return null;
162 + }
163 + if (oldDevice == null) {
164 + // ADD
165 + return createDevice(providerId, newDevice);
166 + } else {
167 + // UPDATE or ignore (no change or stale)
168 + return updateDevice(providerId, oldDevice, newDevice);
169 + }
170 + }
171 + }
172 +
173 + // Creates the device and returns the appropriate event if necessary.
174 + // Guarded by deviceDescs value (=locking Device)
175 + private DeviceEvent createDevice(ProviderId providerId,
176 + Device newDevice) {
177 +
178 + // update composed device cache
179 + Device oldDevice = devices.putIfAbsent(newDevice.id(), newDevice);
180 + verify(oldDevice == null,
181 + "Unexpected Device in cache. PID:%s [old=%s, new=%s]",
182 + providerId, oldDevice, newDevice);
183 +
184 + if (!providerId.isAncillary()) {
185 + availableDevices.add(newDevice.id());
186 + }
187 +
188 + return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, newDevice, null);
189 + }
190 +
191 + // Updates the device and returns the appropriate event if necessary.
192 + // Guarded by deviceDescs value (=locking Device)
193 + private DeviceEvent updateDevice(ProviderId providerId,
194 + Device oldDevice, Device newDevice) {
195 +
196 + // We allow only certain attributes to trigger update
197 + if (!Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) ||
198 + !Objects.equals(oldDevice.swVersion(), newDevice.swVersion()) ||
199 + !isAnnotationsEqual(oldDevice.annotations(), newDevice.annotations())) {
200 +
201 + boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice);
202 + if (!replaced) {
203 + verify(replaced,
204 + "Replacing devices cache failed. PID:%s [expected:%s, found:%s, new=%s]",
205 + providerId, oldDevice, devices.get(newDevice.id())
206 + , newDevice);
207 + }
208 + if (!providerId.isAncillary()) {
209 + availableDevices.add(newDevice.id());
210 + }
211 + return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, newDevice, null);
212 + }
213 +
214 + // Otherwise merely attempt to change availability if primary provider
215 + if (!providerId.isAncillary()) {
216 + boolean added = availableDevices.add(newDevice.id());
217 + return !added ? null :
218 + new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, newDevice, null);
219 + }
220 + return null;
221 + }
222 +
223 + @Override
224 + public DeviceEvent markOffline(DeviceId deviceId) {
225 + ConcurrentMap<ProviderId, DeviceDescriptions> providerDescs
226 + = createIfAbsentUnchecked(deviceDescs, deviceId,
227 + new InitConcurrentHashMap<ProviderId, DeviceDescriptions>());
228 +
229 + // locking device
230 + synchronized (providerDescs) {
231 + Device device = devices.get(deviceId);
232 + if (device == null) {
233 + return null;
234 + }
235 + boolean removed = availableDevices.remove(deviceId);
236 + if (removed) {
237 + // TODO: broadcast ... DOWN only?
238 + return new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null);
239 +
240 + }
241 + return null;
242 + }
243 + }
244 +
245 + @Override
246 + public synchronized List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
247 + List<PortDescription> portDescriptions) {
248 + Timestamp newTimestamp = clockService.getTimestamp(deviceId);
249 +
250 + List<Timestamped<PortDescription>> deltaDescs = new ArrayList<>(portDescriptions.size());
251 + for (PortDescription e : portDescriptions) {
252 + deltaDescs.add(new Timestamped<PortDescription>(e, newTimestamp));
253 + }
254 +
255 + List<DeviceEvent> events = updatePortsInternal(providerId, deviceId, deltaDescs);
256 + if (!events.isEmpty()) {
257 + // FIXME: broadcast deltaDesc, UP
258 + log.debug("broadcast deltaDesc");
259 + }
260 + return events;
261 +
262 + }
263 +
264 + private List<DeviceEvent> updatePortsInternal(ProviderId providerId, DeviceId deviceId,
265 + List<Timestamped<PortDescription>> deltaDescs) {
266 +
267 + Device device = devices.get(deviceId);
268 + checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
269 +
270 + ConcurrentMap<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId);
271 + checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId);
272 +
273 + DeviceDescriptions descs = descsMap.get(providerId);
274 + // every provider must provide DeviceDescription.
275 + checkArgument(descs != null,
276 + "Device description for Device ID %s from Provider %s was not found",
277 + deviceId, providerId);
278 +
279 + List<DeviceEvent> events = new ArrayList<>();
280 + synchronized (descsMap) {
281 + Map<PortNumber, Port> ports = getPortMap(deviceId);
282 +
283 + // Add new ports
284 + Set<PortNumber> processed = new HashSet<>();
285 + for (Timestamped<PortDescription> deltaDesc : deltaDescs) {
286 + final PortNumber number = deltaDesc.value().portNumber();
287 + final Port oldPort = ports.get(number);
288 + final Port newPort;
289 +
290 + final Timestamped<PortDescription> existingPortDesc = descs.getPortDesc(number);
291 + if (existingPortDesc == null ||
292 + deltaDesc == existingPortDesc ||
293 + deltaDesc.isNewer(existingPortDesc)) {
294 + // on new port or valid update
295 + // update description
296 + descs.putPortDesc(deltaDesc);
297 + newPort = composePort(device, number, descsMap);
298 + } else {
299 + // outdated event, ignored.
300 + continue;
301 + }
302 +
303 + events.add(oldPort == null ?
304 + createPort(device, newPort, ports) :
305 + updatePort(device, oldPort, newPort, ports));
306 + processed.add(number);
307 + }
308 +
309 + events.addAll(pruneOldPorts(device, ports, processed));
310 + }
311 + return FluentIterable.from(events).filter(notNull()).toList();
312 + }
313 +
314 + // Creates a new port based on the port description adds it to the map and
315 + // Returns corresponding event.
316 + // Guarded by deviceDescs value (=locking Device)
317 + private DeviceEvent createPort(Device device, Port newPort,
318 + Map<PortNumber, Port> ports) {
319 + ports.put(newPort.number(), newPort);
320 + return new DeviceEvent(PORT_ADDED, device, newPort);
321 + }
322 +
323 + // Checks if the specified port requires update and if so, it replaces the
324 + // existing entry in the map and returns corresponding event.
325 + // Guarded by deviceDescs value (=locking Device)
326 + private DeviceEvent updatePort(Device device, Port oldPort,
327 + Port newPort,
328 + Map<PortNumber, Port> ports) {
329 + if (oldPort.isEnabled() != newPort.isEnabled() ||
330 + !isAnnotationsEqual(oldPort.annotations(), newPort.annotations())) {
331 +
332 + ports.put(oldPort.number(), newPort);
333 + return new DeviceEvent(PORT_UPDATED, device, newPort);
334 + }
335 + return null;
336 + }
337 +
338 + // Prunes the specified list of ports based on which ports are in the
339 + // processed list and returns list of corresponding events.
340 + // Guarded by deviceDescs value (=locking Device)
341 + private List<DeviceEvent> pruneOldPorts(Device device,
342 + Map<PortNumber, Port> ports,
343 + Set<PortNumber> processed) {
344 + List<DeviceEvent> events = new ArrayList<>();
345 + Iterator<PortNumber> iterator = ports.keySet().iterator();
346 + while (iterator.hasNext()) {
347 + PortNumber portNumber = iterator.next();
348 + if (!processed.contains(portNumber)) {
349 + events.add(new DeviceEvent(PORT_REMOVED, device,
350 + ports.get(portNumber)));
351 + iterator.remove();
352 + }
353 + }
354 + return events;
355 + }
356 +
357 + // Gets the map of ports for the specified device; if one does not already
358 + // exist, it creates and registers a new one.
359 + private ConcurrentMap<PortNumber, Port> getPortMap(DeviceId deviceId) {
360 + return createIfAbsentUnchecked(devicePorts, deviceId,
361 + new InitConcurrentHashMap<PortNumber, Port>());
362 + }
363 +
364 + @Override
365 + public synchronized DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
366 + PortDescription portDescription) {
367 + Timestamp newTimestamp = clockService.getTimestamp(deviceId);
368 + final Timestamped<PortDescription> deltaDesc = new Timestamped<>(portDescription, newTimestamp);
369 + DeviceEvent event = updatePortStatusInternal(providerId, deviceId, deltaDesc);
370 + if (event != null) {
371 + // FIXME: broadcast deltaDesc
372 + log.debug("broadcast deltaDesc");
373 + }
374 + return event;
375 + }
376 +
377 + private DeviceEvent updatePortStatusInternal(ProviderId providerId, DeviceId deviceId,
378 + Timestamped<PortDescription> deltaDesc) {
379 +
380 + Device device = devices.get(deviceId);
381 + checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
382 +
383 + ConcurrentMap<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId);
384 + checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId);
385 +
386 + DeviceDescriptions descs = descsMap.get(providerId);
387 + // assuming all providers must to give DeviceDescription
388 + checkArgument(descs != null,
389 + "Device description for Device ID %s from Provider %s was not found",
390 + deviceId, providerId);
391 +
392 + synchronized (descsMap) {
393 + ConcurrentMap<PortNumber, Port> ports = getPortMap(deviceId);
394 + final PortNumber number = deltaDesc.value().portNumber();
395 + final Port oldPort = ports.get(number);
396 + final Port newPort;
397 +
398 + final Timestamped<PortDescription> existingPortDesc = descs.getPortDesc(number);
399 + if (existingPortDesc == null ||
400 + deltaDesc == existingPortDesc ||
401 + deltaDesc.isNewer(existingPortDesc)) {
402 + // on new port or valid update
403 + // update description
404 + descs.putPortDesc(deltaDesc);
405 + newPort = composePort(device, number, descsMap);
406 + } else {
407 + // outdated event, ignored.
408 + return null;
409 + }
410 +
411 + if (oldPort == null) {
412 + return createPort(device, newPort, ports);
413 + } else {
414 + return updatePort(device, oldPort, newPort, ports);
415 + }
416 + }
417 + }
418 +
419 + @Override
420 + public List<Port> getPorts(DeviceId deviceId) {
421 + Map<PortNumber, Port> ports = devicePorts.get(deviceId);
422 + if (ports == null) {
423 + return Collections.emptyList();
424 + }
425 + return ImmutableList.copyOf(ports.values());
426 + }
427 +
428 + @Override
429 + public Port getPort(DeviceId deviceId, PortNumber portNumber) {
430 + Map<PortNumber, Port> ports = devicePorts.get(deviceId);
431 + return ports == null ? null : ports.get(portNumber);
432 + }
433 +
434 + @Override
435 + public boolean isAvailable(DeviceId deviceId) {
436 + return availableDevices.contains(deviceId);
437 + }
438 +
439 + @Override
440 + public DeviceEvent removeDevice(DeviceId deviceId) {
441 + synchronized (this) {
442 + Device device = devices.remove(deviceId);
443 + return device == null ? null :
444 + new DeviceEvent(DEVICE_REMOVED, device, null);
445 + }
446 + }
447 +
448 + private static boolean isAnnotationsEqual(Annotations lhs, Annotations rhs) {
449 + if (lhs == rhs) {
450 + return true;
451 + }
452 + if (lhs == null || rhs == null) {
453 + return false;
454 + }
455 +
456 + if (!lhs.keys().equals(rhs.keys())) {
457 + return false;
458 + }
459 +
460 + for (String key : lhs.keys()) {
461 + if (!lhs.value(key).equals(rhs.value(key))) {
462 + return false;
463 + }
464 + }
465 + return true;
466 + }
467 +
468 + /**
469 + * Returns a Device, merging description given from multiple Providers.
470 + *
471 + * @param deviceId device identifier
472 + * @param providerDescs Collection of Descriptions from multiple providers
473 + * @return Device instance
474 + */
475 + private Device composeDevice(DeviceId deviceId,
476 + ConcurrentMap<ProviderId, DeviceDescriptions> providerDescs) {
477 +
478 + checkArgument(!providerDescs.isEmpty(), "No Device descriptions supplied");
479 +
480 + ProviderId primary = pickPrimaryPID(providerDescs);
481 +
482 + DeviceDescriptions desc = providerDescs.get(primary);
483 +
484 + DeviceDescription base = desc.getDeviceDesc().value();
485 + Type type = base.type();
486 + String manufacturer = base.manufacturer();
487 + String hwVersion = base.hwVersion();
488 + String swVersion = base.swVersion();
489 + String serialNumber = base.serialNumber();
490 + DefaultAnnotations annotations = DefaultAnnotations.builder().build();
491 + annotations = merge(annotations, base.annotations());
492 +
493 + for (Entry<ProviderId, DeviceDescriptions> e : providerDescs.entrySet()) {
494 + if (e.getKey().equals(primary)) {
495 + continue;
496 + }
497 + // TODO: should keep track of Description timestamp
498 + // and only merge conflicting keys when timestamp is newer
499 + // Currently assuming there will never be a key conflict between
500 + // providers
501 +
502 + // annotation merging. not so efficient, should revisit later
503 + annotations = merge(annotations, e.getValue().getDeviceDesc().value().annotations());
504 + }
505 +
506 + return new DefaultDevice(primary, deviceId , type, manufacturer,
507 + hwVersion, swVersion, serialNumber, annotations);
508 + }
509 +
510 + /**
511 + * Returns a Port, merging description given from multiple Providers.
512 + *
513 + * @param device device the port is on
514 + * @param number port number
515 + * @param providerDescs Collection of Descriptions from multiple providers
516 + * @return Port instance
517 + */
518 + private Port composePort(Device device, PortNumber number,
519 + ConcurrentMap<ProviderId, DeviceDescriptions> providerDescs) {
520 +
521 + ProviderId primary = pickPrimaryPID(providerDescs);
522 + DeviceDescriptions primDescs = providerDescs.get(primary);
523 + // if no primary, assume not enabled
524 + // TODO: revisit this default port enabled/disabled behavior
525 + boolean isEnabled = false;
526 + DefaultAnnotations annotations = DefaultAnnotations.builder().build();
527 +
528 + final Timestamped<PortDescription> portDesc = primDescs.getPortDesc(number);
529 + if (portDesc != null) {
530 + isEnabled = portDesc.value().isEnabled();
531 + annotations = merge(annotations, portDesc.value().annotations());
532 + }
533 +
534 + for (Entry<ProviderId, DeviceDescriptions> e : providerDescs.entrySet()) {
535 + if (e.getKey().equals(primary)) {
536 + continue;
537 + }
538 + // TODO: should keep track of Description timestamp
539 + // and only merge conflicting keys when timestamp is newer
540 + // Currently assuming there will never be a key conflict between
541 + // providers
542 +
543 + // annotation merging. not so efficient, should revisit later
544 + final Timestamped<PortDescription> otherPortDesc = e.getValue().getPortDesc(number);
545 + if (otherPortDesc != null) {
546 + annotations = merge(annotations, otherPortDesc.value().annotations());
547 + }
548 + }
549 +
550 + return new DefaultPort(device, number, isEnabled, annotations);
551 + }
552 +
553 + /**
554 + * @return primary ProviderID, or randomly chosen one if none exists
555 + */
556 + private ProviderId pickPrimaryPID(
557 + ConcurrentMap<ProviderId, DeviceDescriptions> providerDescs) {
558 + ProviderId fallBackPrimary = null;
559 + for (Entry<ProviderId, DeviceDescriptions> e : providerDescs.entrySet()) {
560 + if (!e.getKey().isAncillary()) {
561 + return e.getKey();
562 + } else if (fallBackPrimary == null) {
563 + // pick randomly as a fallback in case there is no primary
564 + fallBackPrimary = e.getKey();
565 + }
566 + }
567 + return fallBackPrimary;
568 + }
569 +
570 + private static final class InitConcurrentHashMap<K, V> implements
571 + ConcurrentInitializer<ConcurrentMap<K, V>> {
572 + @Override
573 + public ConcurrentMap<K, V> get() throws ConcurrentException {
574 + return new ConcurrentHashMap<>();
575 + }
576 + }
577 +
578 + public static final class InitDeviceDescs
579 + implements ConcurrentInitializer<DeviceDescriptions> {
580 +
581 + private final Timestamped<DeviceDescription> deviceDesc;
582 +
583 + public InitDeviceDescs(Timestamped<DeviceDescription> deviceDesc) {
584 + this.deviceDesc = checkNotNull(deviceDesc);
585 + }
586 + @Override
587 + public DeviceDescriptions get() throws ConcurrentException {
588 + return new DeviceDescriptions(deviceDesc);
589 + }
590 + }
591 +
592 +
593 + /**
594 + * Collection of Description of a Device and it's Ports given from a Provider.
595 + */
596 + public static class DeviceDescriptions {
597 +
598 + private final AtomicReference<Timestamped<DeviceDescription>> deviceDesc;
599 + private final ConcurrentMap<PortNumber, Timestamped<PortDescription>> portDescs;
600 +
601 + public DeviceDescriptions(Timestamped<DeviceDescription> desc) {
602 + this.deviceDesc = new AtomicReference<>(checkNotNull(desc));
603 + this.portDescs = new ConcurrentHashMap<>();
604 + }
605 +
606 + public Timestamped<DeviceDescription> getDeviceDesc() {
607 + return deviceDesc.get();
608 + }
609 +
610 + public Timestamped<PortDescription> getPortDesc(PortNumber number) {
611 + return portDescs.get(number);
612 + }
613 +
614 + /**
615 + * Puts DeviceDescription, merging annotations as necessary.
616 + *
617 + * @param newDesc new DeviceDescription
618 + * @return previous DeviceDescription
619 + */
620 + public synchronized Timestamped<DeviceDescription> putDeviceDesc(Timestamped<DeviceDescription> newDesc) {
621 + Timestamped<DeviceDescription> oldOne = deviceDesc.get();
622 + Timestamped<DeviceDescription> newOne = newDesc;
623 + if (oldOne != null) {
624 + SparseAnnotations merged = merge(oldOne.value().annotations(),
625 + newDesc.value().annotations());
626 + newOne = new Timestamped<DeviceDescription>(
627 + new DefaultDeviceDescription(newDesc.value(), merged),
628 + newDesc.timestamp());
629 + }
630 + return deviceDesc.getAndSet(newOne);
631 + }
632 +
633 + /**
634 + * Puts PortDescription, merging annotations as necessary.
635 + *
636 + * @param newDesc new PortDescription
637 + * @return previous PortDescription
638 + */
639 + public synchronized Timestamped<PortDescription> putPortDesc(Timestamped<PortDescription> newDesc) {
640 + Timestamped<PortDescription> oldOne = portDescs.get(newDesc.value().portNumber());
641 + Timestamped<PortDescription> newOne = newDesc;
642 + if (oldOne != null) {
643 + SparseAnnotations merged = merge(oldOne.value().annotations(),
644 + newDesc.value().annotations());
645 + newOne = new Timestamped<PortDescription>(
646 + new DefaultPortDescription(newDesc.value(), merged),
647 + newDesc.timestamp());
648 + }
649 + return portDescs.put(newOne.value().portNumber(), newOne);
650 + }
651 + }
652 +}
1 -package org.onlab.onos.store.device.impl;
2 -
3 -import static com.google.common.base.Predicates.notNull;
4 -import static com.google.common.base.Preconditions.checkState;
5 -
6 -import com.google.common.collect.FluentIterable;
7 -import com.google.common.collect.ImmutableSet;
8 -import com.google.common.collect.ImmutableSet.Builder;
9 -
10 -import org.apache.felix.scr.annotations.Activate;
11 -import org.apache.felix.scr.annotations.Component;
12 -import org.apache.felix.scr.annotations.Deactivate;
13 -import org.apache.felix.scr.annotations.Reference;
14 -import org.apache.felix.scr.annotations.ReferenceCardinality;
15 -import org.apache.felix.scr.annotations.Service;
16 -import org.onlab.onos.net.DefaultDevice;
17 -import org.onlab.onos.net.DefaultPort;
18 -import org.onlab.onos.net.Device;
19 -import org.onlab.onos.net.DeviceId;
20 -import org.onlab.onos.net.Port;
21 -import org.onlab.onos.net.PortNumber;
22 -import org.onlab.onos.net.device.DeviceDescription;
23 -import org.onlab.onos.net.device.DeviceEvent;
24 -import org.onlab.onos.net.device.DeviceStore;
25 -import org.onlab.onos.net.device.DeviceStoreDelegate;
26 -import org.onlab.onos.net.device.PortDescription;
27 -import org.onlab.onos.net.provider.ProviderId;
28 -import org.onlab.onos.store.AbstractStore;
29 -import org.onlab.onos.store.ClockService;
30 -import org.onlab.onos.store.Timestamp;
31 -import org.slf4j.Logger;
32 -
33 -import java.util.ArrayList;
34 -import java.util.Collections;
35 -import java.util.HashMap;
36 -import java.util.HashSet;
37 -import java.util.Iterator;
38 -import java.util.List;
39 -import java.util.Map;
40 -import java.util.Objects;
41 -import java.util.Set;
42 -import java.util.concurrent.ConcurrentHashMap;
43 -import java.util.concurrent.ConcurrentMap;
44 -
45 -import static com.google.common.base.Preconditions.checkArgument;
46 -import static org.onlab.onos.net.device.DeviceEvent.Type.*;
47 -import static org.slf4j.LoggerFactory.getLogger;
48 -
49 -/**
50 - * Manages inventory of infrastructure devices using a protocol that takes into consideration
51 - * the order in which device events occur.
52 - */
53 -@Component(immediate = true)
54 -@Service
55 -public class OnosDistributedDeviceStore
56 - extends AbstractStore<DeviceEvent, DeviceStoreDelegate>
57 - implements DeviceStore {
58 -
59 - private final Logger log = getLogger(getClass());
60 -
61 - public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
62 -
63 - private ConcurrentMap<DeviceId, VersionedValue<Device>> devices;
64 - private ConcurrentMap<DeviceId, Map<PortNumber, VersionedValue<Port>>> devicePorts;
65 -
66 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 - protected ClockService clockService;
68 -
69 - @Activate
70 - public void activate() {
71 -
72 - devices = new ConcurrentHashMap<>();
73 - devicePorts = new ConcurrentHashMap<>();
74 -
75 - log.info("Started");
76 - }
77 -
78 - @Deactivate
79 - public void deactivate() {
80 - log.info("Stopped");
81 - }
82 -
83 - @Override
84 - public int getDeviceCount() {
85 - return devices.size();
86 - }
87 -
88 - @Override
89 - public Iterable<Device> getDevices() {
90 - Builder<Device> builder = ImmutableSet.builder();
91 - synchronized (this) {
92 - for (VersionedValue<Device> device : devices.values()) {
93 - builder.add(device.entity());
94 - }
95 - return builder.build();
96 - }
97 - }
98 -
99 - @Override
100 - public Device getDevice(DeviceId deviceId) {
101 - VersionedValue<Device> device = devices.get(deviceId);
102 - checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
103 - return device.entity();
104 - }
105 -
106 - @Override
107 - public DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId,
108 - DeviceDescription deviceDescription) {
109 - Timestamp newTimestamp = clockService.getTimestamp(deviceId);
110 - VersionedValue<Device> device = devices.get(deviceId);
111 -
112 - if (device == null) {
113 - return createDevice(providerId, deviceId, deviceDescription, newTimestamp);
114 - }
115 -
116 - checkState(newTimestamp.compareTo(device.timestamp()) > 0,
117 - "Existing device has a timestamp in the future!");
118 -
119 - return updateDevice(providerId, device.entity(), deviceDescription, newTimestamp);
120 - }
121 -
122 - // Creates the device and returns the appropriate event if necessary.
123 - private DeviceEvent createDevice(ProviderId providerId, DeviceId deviceId,
124 - DeviceDescription desc, Timestamp timestamp) {
125 - Device device = new DefaultDevice(providerId, deviceId, desc.type(),
126 - desc.manufacturer(),
127 - desc.hwVersion(), desc.swVersion(),
128 - desc.serialNumber());
129 -
130 - devices.put(deviceId, new VersionedValue<>(device, true, timestamp));
131 - // TODO,FIXME: broadcast a message telling peers of a device event.
132 - return new DeviceEvent(DEVICE_ADDED, device, null);
133 - }
134 -
135 - // Updates the device and returns the appropriate event if necessary.
136 - private DeviceEvent updateDevice(ProviderId providerId, Device device,
137 - DeviceDescription desc, Timestamp timestamp) {
138 - // We allow only certain attributes to trigger update
139 - if (!Objects.equals(device.hwVersion(), desc.hwVersion()) ||
140 - !Objects.equals(device.swVersion(), desc.swVersion())) {
141 -
142 - Device updated = new DefaultDevice(providerId, device.id(),
143 - desc.type(),
144 - desc.manufacturer(),
145 - desc.hwVersion(),
146 - desc.swVersion(),
147 - desc.serialNumber());
148 - devices.put(device.id(), new VersionedValue<Device>(updated, true, timestamp));
149 - // FIXME: broadcast a message telling peers of a device event.
150 - return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, updated, null);
151 - }
152 -
153 - // Otherwise merely attempt to change availability
154 - Device updated = new DefaultDevice(providerId, device.id(),
155 - desc.type(),
156 - desc.manufacturer(),
157 - desc.hwVersion(),
158 - desc.swVersion(),
159 - desc.serialNumber());
160 -
161 - VersionedValue<Device> oldDevice = devices.put(device.id(),
162 - new VersionedValue<Device>(updated, true, timestamp));
163 - if (!oldDevice.isUp()) {
164 - return new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null);
165 - } else {
166 - return null;
167 - }
168 - }
169 -
170 - @Override
171 - public DeviceEvent markOffline(DeviceId deviceId) {
172 - VersionedValue<Device> device = devices.get(deviceId);
173 - boolean willRemove = device != null && device.isUp();
174 - if (!willRemove) {
175 - return null;
176 - }
177 - Timestamp timestamp = clockService.getTimestamp(deviceId);
178 - if (replaceIfLatest(device.entity(), false, timestamp)) {
179 - return new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device.entity(), null);
180 - }
181 - return null;
182 - }
183 -
184 - // Replace existing value if its timestamp is older.
185 - private synchronized boolean replaceIfLatest(Device device, boolean isUp, Timestamp timestamp) {
186 - VersionedValue<Device> existingValue = devices.get(device.id());
187 - if (timestamp.compareTo(existingValue.timestamp()) > 0) {
188 - devices.put(device.id(), new VersionedValue<Device>(device, isUp, timestamp));
189 - return true;
190 - }
191 - return false;
192 - }
193 -
194 - @Override
195 - public List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
196 - List<PortDescription> portDescriptions) {
197 - List<DeviceEvent> events = new ArrayList<>();
198 - synchronized (this) {
199 - VersionedValue<Device> device = devices.get(deviceId);
200 - checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
201 - Map<PortNumber, VersionedValue<Port>> ports = getPortMap(deviceId);
202 - Timestamp newTimestamp = clockService.getTimestamp(deviceId);
203 -
204 - // Add new ports
205 - Set<PortNumber> processed = new HashSet<>();
206 - for (PortDescription portDescription : portDescriptions) {
207 - VersionedValue<Port> port = ports.get(portDescription.portNumber());
208 - if (port == null) {
209 - events.add(createPort(device, portDescription, ports, newTimestamp));
210 - }
211 - checkState(newTimestamp.compareTo(port.timestamp()) > 0,
212 - "Existing port state has a timestamp in the future!");
213 - events.add(updatePort(device.entity(), port.entity(), portDescription, ports, newTimestamp));
214 - processed.add(portDescription.portNumber());
215 - }
216 -
217 - updatePortMap(deviceId, ports);
218 -
219 - events.addAll(pruneOldPorts(device.entity(), ports, processed));
220 - }
221 - return FluentIterable.from(events).filter(notNull()).toList();
222 - }
223 -
224 - // Creates a new port based on the port description adds it to the map and
225 - // Returns corresponding event.
226 - //@GuardedBy("this")
227 - private DeviceEvent createPort(VersionedValue<Device> device, PortDescription portDescription,
228 - Map<PortNumber, VersionedValue<Port>> ports, Timestamp timestamp) {
229 - Port port = new DefaultPort(device.entity(), portDescription.portNumber(),
230 - portDescription.isEnabled());
231 - ports.put(port.number(), new VersionedValue<Port>(port, true, timestamp));
232 - updatePortMap(device.entity().id(), ports);
233 - return new DeviceEvent(PORT_ADDED, device.entity(), port);
234 - }
235 -
236 - // Checks if the specified port requires update and if so, it replaces the
237 - // existing entry in the map and returns corresponding event.
238 - //@GuardedBy("this")
239 - private DeviceEvent updatePort(Device device, Port port,
240 - PortDescription portDescription,
241 - Map<PortNumber, VersionedValue<Port>> ports,
242 - Timestamp timestamp) {
243 - if (port.isEnabled() != portDescription.isEnabled()) {
244 - VersionedValue<Port> updatedPort = new VersionedValue<Port>(
245 - new DefaultPort(device, portDescription.portNumber(),
246 - portDescription.isEnabled()),
247 - portDescription.isEnabled(),
248 - timestamp);
249 - ports.put(port.number(), updatedPort);
250 - updatePortMap(device.id(), ports);
251 - return new DeviceEvent(PORT_UPDATED, device, updatedPort.entity());
252 - }
253 - return null;
254 - }
255 -
256 - // Prunes the specified list of ports based on which ports are in the
257 - // processed list and returns list of corresponding events.
258 - //@GuardedBy("this")
259 - private List<DeviceEvent> pruneOldPorts(Device device,
260 - Map<PortNumber, VersionedValue<Port>> ports,
261 - Set<PortNumber> processed) {
262 - List<DeviceEvent> events = new ArrayList<>();
263 - Iterator<PortNumber> iterator = ports.keySet().iterator();
264 - while (iterator.hasNext()) {
265 - PortNumber portNumber = iterator.next();
266 - if (!processed.contains(portNumber)) {
267 - events.add(new DeviceEvent(PORT_REMOVED, device,
268 - ports.get(portNumber).entity()));
269 - iterator.remove();
270 - }
271 - }
272 - if (!events.isEmpty()) {
273 - updatePortMap(device.id(), ports);
274 - }
275 - return events;
276 - }
277 -
278 - // Gets the map of ports for the specified device; if one does not already
279 - // exist, it creates and registers a new one.
280 - // WARN: returned value is a copy, changes made to the Map
281 - // needs to be written back using updatePortMap
282 - //@GuardedBy("this")
283 - private Map<PortNumber, VersionedValue<Port>> getPortMap(DeviceId deviceId) {
284 - Map<PortNumber, VersionedValue<Port>> ports = devicePorts.get(deviceId);
285 - if (ports == null) {
286 - ports = new HashMap<>();
287 - // this probably is waste of time in most cases.
288 - updatePortMap(deviceId, ports);
289 - }
290 - return ports;
291 - }
292 -
293 - //@GuardedBy("this")
294 - private void updatePortMap(DeviceId deviceId, Map<PortNumber, VersionedValue<Port>> ports) {
295 - devicePorts.put(deviceId, ports);
296 - }
297 -
298 - @Override
299 - public DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
300 - PortDescription portDescription) {
301 - VersionedValue<Device> device = devices.get(deviceId);
302 - checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
303 - Map<PortNumber, VersionedValue<Port>> ports = getPortMap(deviceId);
304 - VersionedValue<Port> port = ports.get(portDescription.portNumber());
305 - Timestamp timestamp = clockService.getTimestamp(deviceId);
306 - return updatePort(device.entity(), port.entity(), portDescription, ports, timestamp);
307 - }
308 -
309 - @Override
310 - public List<Port> getPorts(DeviceId deviceId) {
311 - Map<PortNumber, VersionedValue<Port>> versionedPorts = devicePorts.get(deviceId);
312 - if (versionedPorts == null) {
313 - return Collections.emptyList();
314 - }
315 - List<Port> ports = new ArrayList<>();
316 - for (VersionedValue<Port> port : versionedPorts.values()) {
317 - ports.add(port.entity());
318 - }
319 - return ports;
320 - }
321 -
322 - @Override
323 - public Port getPort(DeviceId deviceId, PortNumber portNumber) {
324 - Map<PortNumber, VersionedValue<Port>> ports = devicePorts.get(deviceId);
325 - return ports == null ? null : ports.get(portNumber).entity();
326 - }
327 -
328 - @Override
329 - public boolean isAvailable(DeviceId deviceId) {
330 - return devices.get(deviceId).isUp();
331 - }
332 -
333 - @Override
334 - public DeviceEvent removeDevice(DeviceId deviceId) {
335 - VersionedValue<Device> previousDevice = devices.remove(deviceId);
336 - return previousDevice == null ? null :
337 - new DeviceEvent(DEVICE_REMOVED, previousDevice.entity(), null);
338 - }
339 -}
1 /** 1 /**
2 * Implementation of device store using distributed distributed p2p synchronization protocol. 2 * Implementation of device store using distributed distributed p2p synchronization protocol.
3 */ 3 */
4 -package org.onlab.onos.store.device.impl;
...\ No newline at end of file ...\ No newline at end of file
4 +package org.onlab.onos.store.device.impl;
......
...@@ -42,6 +42,7 @@ import com.google.common.collect.ImmutableSet.Builder; ...@@ -42,6 +42,7 @@ import com.google.common.collect.ImmutableSet.Builder;
42 import static com.google.common.base.Preconditions.checkArgument; 42 import static com.google.common.base.Preconditions.checkArgument;
43 import static com.google.common.base.Preconditions.checkState; 43 import static com.google.common.base.Preconditions.checkState;
44 44
45 +//TODO: Add support for multiple provider and annotations
45 /** 46 /**
46 * Manages inventory of infrastructure links using a protocol that takes into consideration 47 * Manages inventory of infrastructure links using a protocol that takes into consideration
47 * the order in which events occur. 48 * the order in which events occur.
......
1 /** 1 /**
2 * Implementation of link store using distributed p2p synchronization protocol. 2 * Implementation of link store using distributed p2p synchronization protocol.
3 */ 3 */
4 -package org.onlab.onos.store.link.impl;
...\ No newline at end of file ...\ No newline at end of file
4 +package org.onlab.onos.store.link.impl;
......
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 -import org.onlab.onos.store.impl.OnosTimestamp; 3 +import org.onlab.onos.store.common.impl.MastershipBasedTimestamp;
4 4
5 import com.esotericsoftware.kryo.Kryo; 5 import com.esotericsoftware.kryo.Kryo;
6 import com.esotericsoftware.kryo.Serializer; 6 import com.esotericsoftware.kryo.Serializer;
7 import com.esotericsoftware.kryo.io.Input; 7 import com.esotericsoftware.kryo.io.Input;
8 import com.esotericsoftware.kryo.io.Output; 8 import com.esotericsoftware.kryo.io.Output;
9 9
10 +// To be used if Timestamp ever needs to cross bundle boundary.
10 /** 11 /**
11 - * Kryo Serializer for {@link OnosTimestamp}. 12 + * Kryo Serializer for {@link MastershipBasedTimestamp}.
12 */ 13 */
13 -public class OnosTimestampSerializer extends Serializer<OnosTimestamp> { 14 +public class MastershipBasedTimestampSerializer extends Serializer<MastershipBasedTimestamp> {
14 15
15 /** 16 /**
16 * Default constructor. 17 * Default constructor.
17 */ 18 */
18 - public OnosTimestampSerializer() { 19 + public MastershipBasedTimestampSerializer() {
19 // non-null, immutable 20 // non-null, immutable
20 super(false, true); 21 super(false, true);
21 } 22 }
22 23
23 @Override 24 @Override
24 - public void write(Kryo kryo, Output output, OnosTimestamp object) { 25 + public void write(Kryo kryo, Output output, MastershipBasedTimestamp object) {
25 output.writeInt(object.termNumber()); 26 output.writeInt(object.termNumber());
26 output.writeInt(object.sequenceNumber()); 27 output.writeInt(object.sequenceNumber());
27 } 28 }
28 29
29 @Override 30 @Override
30 - public OnosTimestamp read(Kryo kryo, Input input, Class<OnosTimestamp> type) { 31 + public MastershipBasedTimestamp read(Kryo kryo, Input input, Class<MastershipBasedTimestamp> type) {
31 final int term = input.readInt(); 32 final int term = input.readInt();
32 final int sequence = input.readInt(); 33 final int sequence = input.readInt();
33 - return new OnosTimestamp(term, sequence); 34 + return new MastershipBasedTimestamp(term, sequence);
34 } 35 }
35 } 36 }
......
1 +package org.onlab.onos.store.common.impl;
2 +
3 +import static org.junit.Assert.*;
4 +
5 +import java.nio.ByteBuffer;
6 +
7 +import org.junit.Test;
8 +import org.onlab.onos.store.Timestamp;
9 +import org.onlab.onos.store.serializers.MastershipBasedTimestampSerializer;
10 +import org.onlab.util.KryoPool;
11 +
12 +import com.google.common.testing.EqualsTester;
13 +
14 +/**
15 + * Test of {@link MastershipBasedTimestamp}.
16 + */
17 +public class MastershipBasedTimestampTest {
18 +
19 + private static final Timestamp TS_1_1 = new MastershipBasedTimestamp(1, 1);
20 + private static final Timestamp TS_1_2 = new MastershipBasedTimestamp(1, 2);
21 + private static final Timestamp TS_2_1 = new MastershipBasedTimestamp(2, 1);
22 + private static final Timestamp TS_2_2 = new MastershipBasedTimestamp(2, 2);
23 +
24 + @Test
25 + public final void testBasic() {
26 + final int termNumber = 5;
27 + final int sequenceNumber = 6;
28 + MastershipBasedTimestamp ts = new MastershipBasedTimestamp(termNumber,
29 + sequenceNumber);
30 +
31 + assertEquals(termNumber, ts.termNumber());
32 + assertEquals(sequenceNumber, ts.sequenceNumber());
33 + }
34 +
35 + @Test
36 + public final void testCompareTo() {
37 + assertTrue(TS_1_1.compareTo(TS_1_1) == 0);
38 + assertTrue(TS_1_1.compareTo(new MastershipBasedTimestamp(1, 1)) == 0);
39 +
40 + assertTrue(TS_1_1.compareTo(TS_1_2) < 0);
41 + assertTrue(TS_1_2.compareTo(TS_1_1) > 0);
42 +
43 + assertTrue(TS_1_2.compareTo(TS_2_1) < 0);
44 + assertTrue(TS_1_2.compareTo(TS_2_2) < 0);
45 + assertTrue(TS_2_1.compareTo(TS_1_1) > 0);
46 + assertTrue(TS_2_2.compareTo(TS_1_1) > 0);
47 + }
48 +
49 + @Test
50 + public final void testEqualsObject() {
51 + new EqualsTester()
52 + .addEqualityGroup(new MastershipBasedTimestamp(1, 1),
53 + new MastershipBasedTimestamp(1, 1), TS_1_1)
54 + .addEqualityGroup(new MastershipBasedTimestamp(1, 2),
55 + new MastershipBasedTimestamp(1, 2), TS_1_2)
56 + .addEqualityGroup(new MastershipBasedTimestamp(2, 1),
57 + new MastershipBasedTimestamp(2, 1), TS_2_1)
58 + .addEqualityGroup(new MastershipBasedTimestamp(2, 2),
59 + new MastershipBasedTimestamp(2, 2), TS_2_2)
60 + .testEquals();
61 + }
62 +
63 + @Test
64 + public final void testKryoSerializable() {
65 + final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024);
66 + final KryoPool kryos = KryoPool.newBuilder()
67 + .register(MastershipBasedTimestamp.class)
68 + .build();
69 +
70 + kryos.serialize(TS_2_1, buffer);
71 + buffer.flip();
72 + Timestamp copy = kryos.deserialize(buffer);
73 +
74 + new EqualsTester()
75 + .addEqualityGroup(TS_2_1, copy)
76 + .testEquals();
77 + }
78 +
79 + @Test
80 + public final void testKryoSerializableWithHandcraftedSerializer() {
81 + final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024);
82 + final KryoPool kryos = KryoPool.newBuilder()
83 + .register(MastershipBasedTimestamp.class, new MastershipBasedTimestampSerializer())
84 + .build();
85 +
86 + kryos.serialize(TS_1_2, buffer);
87 + buffer.flip();
88 + Timestamp copy = kryos.deserialize(buffer);
89 +
90 + new EqualsTester()
91 + .addEqualityGroup(TS_1_2, copy)
92 + .testEquals();
93 + }
94 +
95 +}
1 +package org.onlab.onos.store.common.impl;
2 +
3 +import static org.junit.Assert.*;
4 +
5 +import java.nio.ByteBuffer;
6 +
7 +import org.junit.Test;
8 +import org.onlab.onos.store.Timestamp;
9 +import org.onlab.util.KryoPool;
10 +
11 +import com.google.common.testing.EqualsTester;
12 +
13 +/**
14 + * Test of {@link Timestamped}.
15 + */
16 +public class TimestampedTest {
17 +
18 + private static final Timestamp TS_1_1 = new MastershipBasedTimestamp(1, 1);
19 + private static final Timestamp TS_1_2 = new MastershipBasedTimestamp(1, 2);
20 + private static final Timestamp TS_2_1 = new MastershipBasedTimestamp(2, 1);
21 +
22 + @Test
23 + public final void testHashCode() {
24 + Timestamped<String> a = new Timestamped<>("a", TS_1_1);
25 + Timestamped<String> b = new Timestamped<>("b", TS_1_1);
26 + assertTrue("value does not impact hashCode",
27 + a.hashCode() == b.hashCode());
28 + }
29 +
30 + @Test
31 + public final void testEquals() {
32 + Timestamped<String> a = new Timestamped<>("a", TS_1_1);
33 + Timestamped<String> b = new Timestamped<>("b", TS_1_1);
34 + assertTrue("value does not impact equality",
35 + a.equals(b));
36 +
37 + new EqualsTester()
38 + .addEqualityGroup(new Timestamped<>("a", TS_1_1),
39 + new Timestamped<>("b", TS_1_1),
40 + new Timestamped<>("c", TS_1_1))
41 + .addEqualityGroup(new Timestamped<>("a", TS_1_2),
42 + new Timestamped<>("b", TS_1_2),
43 + new Timestamped<>("c", TS_1_2))
44 + .addEqualityGroup(new Timestamped<>("a", TS_2_1),
45 + new Timestamped<>("b", TS_2_1),
46 + new Timestamped<>("c", TS_2_1))
47 + .testEquals();
48 +
49 + }
50 +
51 + @Test
52 + public final void testValue() {
53 + final Integer n = Integer.valueOf(42);
54 + Timestamped<Integer> tsv = new Timestamped<>(n, TS_1_1);
55 + assertSame(n, tsv.value());
56 +
57 + }
58 +
59 + @Test(expected = NullPointerException.class)
60 + public final void testValueNonNull() {
61 + new Timestamped<>(null, TS_1_1);
62 + }
63 +
64 + @Test(expected = NullPointerException.class)
65 + public final void testTimestampNonNull() {
66 + new Timestamped<>("Foo", null);
67 + }
68 +
69 + @Test
70 + public final void testIsNewer() {
71 + Timestamped<String> a = new Timestamped<>("a", TS_1_2);
72 + Timestamped<String> b = new Timestamped<>("b", TS_1_1);
73 + assertTrue(a.isNewer(b));
74 + assertFalse(b.isNewer(a));
75 + }
76 +
77 + @Test
78 + public final void testKryoSerializable() {
79 + final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024);
80 + final KryoPool kryos = KryoPool.newBuilder()
81 + .register(Timestamped.class,
82 + MastershipBasedTimestamp.class)
83 + .build();
84 +
85 + Timestamped<String> original = new Timestamped<>("foobar", TS_1_1);
86 + kryos.serialize(original, buffer);
87 + buffer.flip();
88 + Timestamped<String> copy = kryos.deserialize(buffer);
89 +
90 + new EqualsTester()
91 + .addEqualityGroup(original, copy)
92 + .testEquals();
93 + }
94 +}
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import static org.junit.Assert.*;
4 +import static org.onlab.onos.net.Device.Type.SWITCH;
5 +import static org.onlab.onos.net.DeviceId.deviceId;
6 +import static org.onlab.onos.net.device.DeviceEvent.Type.*;
7 +
8 +import java.util.Arrays;
9 +import java.util.HashMap;
10 +import java.util.List;
11 +import java.util.Map;
12 +import java.util.Set;
13 +import java.util.concurrent.CountDownLatch;
14 +import java.util.concurrent.TimeUnit;
15 +
16 +import org.junit.After;
17 +import org.junit.AfterClass;
18 +import org.junit.Before;
19 +import org.junit.BeforeClass;
20 +import org.junit.Ignore;
21 +import org.junit.Test;
22 +import org.onlab.onos.cluster.MastershipTerm;
23 +import org.onlab.onos.cluster.NodeId;
24 +import org.onlab.onos.net.Annotations;
25 +import org.onlab.onos.net.DefaultAnnotations;
26 +import org.onlab.onos.net.Device;
27 +import org.onlab.onos.net.DeviceId;
28 +import org.onlab.onos.net.Port;
29 +import org.onlab.onos.net.PortNumber;
30 +import org.onlab.onos.net.SparseAnnotations;
31 +import org.onlab.onos.net.device.DefaultDeviceDescription;
32 +import org.onlab.onos.net.device.DefaultPortDescription;
33 +import org.onlab.onos.net.device.DeviceDescription;
34 +import org.onlab.onos.net.device.DeviceEvent;
35 +import org.onlab.onos.net.device.DeviceStore;
36 +import org.onlab.onos.net.device.DeviceStoreDelegate;
37 +import org.onlab.onos.net.device.PortDescription;
38 +import org.onlab.onos.net.provider.ProviderId;
39 +import org.onlab.onos.store.ClockService;
40 +
41 +import com.google.common.collect.Iterables;
42 +import com.google.common.collect.Sets;
43 +
44 +
45 +// TODO add tests for remote replication
46 +/**
47 + * Test of the gossip based distributed DeviceStore implementation.
48 + */
49 +public class GossipDeviceStoreTest {
50 +
51 + private static final ProviderId PID = new ProviderId("of", "foo");
52 + private static final ProviderId PIDA = new ProviderId("of", "bar", true);
53 + private static final DeviceId DID1 = deviceId("of:foo");
54 + private static final DeviceId DID2 = deviceId("of:bar");
55 + private static final String MFR = "whitebox";
56 + private static final String HW = "1.1.x";
57 + private static final String SW1 = "3.8.1";
58 + private static final String SW2 = "3.9.5";
59 + private static final String SN = "43311-12345";
60 +
61 + private static final PortNumber P1 = PortNumber.portNumber(1);
62 + private static final PortNumber P2 = PortNumber.portNumber(2);
63 + private static final PortNumber P3 = PortNumber.portNumber(3);
64 +
65 + private static final SparseAnnotations A1 = DefaultAnnotations.builder()
66 + .set("A1", "a1")
67 + .set("B1", "b1")
68 + .build();
69 + private static final SparseAnnotations A1_2 = DefaultAnnotations.builder()
70 + .remove("A1")
71 + .set("B3", "b3")
72 + .build();
73 + private static final SparseAnnotations A2 = DefaultAnnotations.builder()
74 + .set("A2", "a2")
75 + .set("B2", "b2")
76 + .build();
77 + private static final SparseAnnotations A2_2 = DefaultAnnotations.builder()
78 + .remove("A2")
79 + .set("B4", "b4")
80 + .build();
81 +
82 + private static final NodeId MYSELF = new NodeId("myself");
83 +
84 + private GossipDeviceStore gossipDeviceStore;
85 + private DeviceStore deviceStore;
86 +
87 + private DeviceClockManager deviceClockManager;
88 + private ClockService clockService;
89 +
90 + @BeforeClass
91 + public static void setUpBeforeClass() throws Exception {
92 + }
93 +
94 + @AfterClass
95 + public static void tearDownAfterClass() throws Exception {
96 + }
97 +
98 +
99 + @Before
100 + public void setUp() throws Exception {
101 + deviceClockManager = new DeviceClockManager();
102 + deviceClockManager.activate();
103 + clockService = deviceClockManager;
104 +
105 + deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(MYSELF, 1));
106 + deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(MYSELF, 2));
107 +
108 + gossipDeviceStore = new TestGossipDeviceStore(clockService);
109 + gossipDeviceStore.activate();
110 + deviceStore = gossipDeviceStore;
111 + }
112 +
113 + @After
114 + public void tearDown() throws Exception {
115 + gossipDeviceStore.deactivate();
116 + deviceClockManager.deactivate();
117 + }
118 +
119 + private void putDevice(DeviceId deviceId, String swVersion) {
120 + DeviceDescription description =
121 + new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
122 + HW, swVersion, SN);
123 + deviceStore.createOrUpdateDevice(PID, deviceId, description);
124 + }
125 +
126 + private void putDeviceAncillary(DeviceId deviceId, String swVersion) {
127 + DeviceDescription description =
128 + new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
129 + HW, swVersion, SN);
130 + deviceStore.createOrUpdateDevice(PIDA, deviceId, description);
131 + }
132 +
133 + private static void assertDevice(DeviceId id, String swVersion, Device device) {
134 + assertNotNull(device);
135 + assertEquals(id, device.id());
136 + assertEquals(MFR, device.manufacturer());
137 + assertEquals(HW, device.hwVersion());
138 + assertEquals(swVersion, device.swVersion());
139 + assertEquals(SN, device.serialNumber());
140 + }
141 +
142 + /**
143 + * Verifies that Annotations created by merging {@code annotations} is
144 + * equal to actual Annotations.
145 + *
146 + * @param actual Annotations to check
147 + * @param annotations
148 + */
149 + private static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) {
150 + DefaultAnnotations expected = DefaultAnnotations.builder().build();
151 + for (SparseAnnotations a : annotations) {
152 + expected = DefaultAnnotations.merge(expected, a);
153 + }
154 + assertEquals(expected.keys(), actual.keys());
155 + for (String key : expected.keys()) {
156 + assertEquals(expected.value(key), actual.value(key));
157 + }
158 + }
159 +
160 + @Test
161 + public final void testGetDeviceCount() {
162 + assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
163 +
164 + putDevice(DID1, SW1);
165 + putDevice(DID2, SW2);
166 + putDevice(DID1, SW1);
167 +
168 + assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount());
169 + }
170 +
171 + @Test
172 + public final void testGetDevices() {
173 + assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices()));
174 +
175 + putDevice(DID1, SW1);
176 + putDevice(DID2, SW2);
177 + putDevice(DID1, SW1);
178 +
179 + assertEquals("expect 2 uniq devices",
180 + 2, Iterables.size(deviceStore.getDevices()));
181 +
182 + Map<DeviceId, Device> devices = new HashMap<>();
183 + for (Device device : deviceStore.getDevices()) {
184 + devices.put(device.id(), device);
185 + }
186 +
187 + assertDevice(DID1, SW1, devices.get(DID1));
188 + assertDevice(DID2, SW2, devices.get(DID2));
189 +
190 + // add case for new node?
191 + }
192 +
193 + @Test
194 + public final void testGetDevice() {
195 +
196 + putDevice(DID1, SW1);
197 +
198 + assertDevice(DID1, SW1, deviceStore.getDevice(DID1));
199 + assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
200 + }
201 +
202 + @Test
203 + public final void testCreateOrUpdateDevice() {
204 + DeviceDescription description =
205 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
206 + HW, SW1, SN);
207 + DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
208 + assertEquals(DEVICE_ADDED, event.type());
209 + assertDevice(DID1, SW1, event.subject());
210 +
211 + DeviceDescription description2 =
212 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
213 + HW, SW2, SN);
214 + DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
215 + assertEquals(DEVICE_UPDATED, event2.type());
216 + assertDevice(DID1, SW2, event2.subject());
217 +
218 + assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
219 + }
220 +
221 + @Test
222 + public final void testCreateOrUpdateDeviceAncillary() {
223 + DeviceDescription description =
224 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
225 + HW, SW1, SN, A2);
226 + DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
227 + assertEquals(DEVICE_ADDED, event.type());
228 + assertDevice(DID1, SW1, event.subject());
229 + assertEquals(PIDA, event.subject().providerId());
230 + assertAnnotationsEquals(event.subject().annotations(), A2);
231 + assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1));
232 +
233 + DeviceDescription description2 =
234 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
235 + HW, SW2, SN, A1);
236 + DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
237 + assertEquals(DEVICE_UPDATED, event2.type());
238 + assertDevice(DID1, SW2, event2.subject());
239 + assertEquals(PID, event2.subject().providerId());
240 + assertAnnotationsEquals(event2.subject().annotations(), A1, A2);
241 + assertTrue(deviceStore.isAvailable(DID1));
242 +
243 + assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
244 +
245 + // For now, Ancillary is ignored once primary appears
246 + assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
247 +
248 + // But, Ancillary annotations will be in effect
249 + DeviceDescription description3 =
250 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
251 + HW, SW1, SN, A2_2);
252 + DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
253 + assertEquals(DEVICE_UPDATED, event3.type());
254 + // basic information will be the one from Primary
255 + assertDevice(DID1, SW2, event3.subject());
256 + assertEquals(PID, event3.subject().providerId());
257 + // but annotation from Ancillary will be merged
258 + assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2);
259 + assertTrue(deviceStore.isAvailable(DID1));
260 + }
261 +
262 +
263 + @Test
264 + public final void testMarkOffline() {
265 +
266 + putDevice(DID1, SW1);
267 + assertTrue(deviceStore.isAvailable(DID1));
268 +
269 + DeviceEvent event = deviceStore.markOffline(DID1);
270 + assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
271 + assertDevice(DID1, SW1, event.subject());
272 + assertFalse(deviceStore.isAvailable(DID1));
273 +
274 + DeviceEvent event2 = deviceStore.markOffline(DID1);
275 + assertNull("No change, no event", event2);
276 +}
277 +
278 + @Test
279 + public final void testUpdatePorts() {
280 + putDevice(DID1, SW1);
281 + List<PortDescription> pds = Arrays.<PortDescription>asList(
282 + new DefaultPortDescription(P1, true),
283 + new DefaultPortDescription(P2, true)
284 + );
285 +
286 + List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
287 +
288 + Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
289 + for (DeviceEvent event : events) {
290 + assertEquals(PORT_ADDED, event.type());
291 + assertDevice(DID1, SW1, event.subject());
292 + assertTrue("PortNumber is one of expected",
293 + expectedPorts.remove(event.port().number()));
294 + assertTrue("Port is enabled", event.port().isEnabled());
295 + }
296 + assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
297 +
298 +
299 + List<PortDescription> pds2 = Arrays.<PortDescription>asList(
300 + new DefaultPortDescription(P1, false),
301 + new DefaultPortDescription(P2, true),
302 + new DefaultPortDescription(P3, true)
303 + );
304 +
305 + events = deviceStore.updatePorts(PID, DID1, pds2);
306 + assertFalse("event should be triggered", events.isEmpty());
307 + for (DeviceEvent event : events) {
308 + PortNumber num = event.port().number();
309 + if (P1.equals(num)) {
310 + assertEquals(PORT_UPDATED, event.type());
311 + assertDevice(DID1, SW1, event.subject());
312 + assertFalse("Port is disabled", event.port().isEnabled());
313 + } else if (P2.equals(num)) {
314 + fail("P2 event not expected.");
315 + } else if (P3.equals(num)) {
316 + assertEquals(PORT_ADDED, event.type());
317 + assertDevice(DID1, SW1, event.subject());
318 + assertTrue("Port is enabled", event.port().isEnabled());
319 + } else {
320 + fail("Unknown port number encountered: " + num);
321 + }
322 + }
323 +
324 + List<PortDescription> pds3 = Arrays.<PortDescription>asList(
325 + new DefaultPortDescription(P1, false),
326 + new DefaultPortDescription(P2, true)
327 + );
328 + events = deviceStore.updatePorts(PID, DID1, pds3);
329 + assertFalse("event should be triggered", events.isEmpty());
330 + for (DeviceEvent event : events) {
331 + PortNumber num = event.port().number();
332 + if (P1.equals(num)) {
333 + fail("P1 event not expected.");
334 + } else if (P2.equals(num)) {
335 + fail("P2 event not expected.");
336 + } else if (P3.equals(num)) {
337 + assertEquals(PORT_REMOVED, event.type());
338 + assertDevice(DID1, SW1, event.subject());
339 + assertTrue("Port was enabled", event.port().isEnabled());
340 + } else {
341 + fail("Unknown port number encountered: " + num);
342 + }
343 + }
344 +
345 + }
346 +
347 + @Test
348 + public final void testUpdatePortStatus() {
349 + putDevice(DID1, SW1);
350 + List<PortDescription> pds = Arrays.<PortDescription>asList(
351 + new DefaultPortDescription(P1, true)
352 + );
353 + deviceStore.updatePorts(PID, DID1, pds);
354 +
355 + DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
356 + new DefaultPortDescription(P1, false));
357 + assertEquals(PORT_UPDATED, event.type());
358 + assertDevice(DID1, SW1, event.subject());
359 + assertEquals(P1, event.port().number());
360 + assertFalse("Port is disabled", event.port().isEnabled());
361 +
362 + }
363 + @Test
364 + public final void testUpdatePortStatusAncillary() {
365 + putDeviceAncillary(DID1, SW1);
366 + putDevice(DID1, SW1);
367 + List<PortDescription> pds = Arrays.<PortDescription>asList(
368 + new DefaultPortDescription(P1, true, A1)
369 + );
370 + deviceStore.updatePorts(PID, DID1, pds);
371 +
372 + DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
373 + new DefaultPortDescription(P1, false, A1_2));
374 + assertEquals(PORT_UPDATED, event.type());
375 + assertDevice(DID1, SW1, event.subject());
376 + assertEquals(P1, event.port().number());
377 + assertAnnotationsEquals(event.port().annotations(), A1, A1_2);
378 + assertFalse("Port is disabled", event.port().isEnabled());
379 +
380 + DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1,
381 + new DefaultPortDescription(P1, true));
382 + assertNull("Ancillary is ignored if primary exists", event2);
383 +
384 + // but, Ancillary annotation update will be notified
385 + DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1,
386 + new DefaultPortDescription(P1, true, A2));
387 + assertEquals(PORT_UPDATED, event3.type());
388 + assertDevice(DID1, SW1, event3.subject());
389 + assertEquals(P1, event3.port().number());
390 + assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2);
391 + assertFalse("Port is disabled", event3.port().isEnabled());
392 +
393 + // port only reported from Ancillary will be notified as down
394 + DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1,
395 + new DefaultPortDescription(P2, true));
396 + assertEquals(PORT_ADDED, event4.type());
397 + assertDevice(DID1, SW1, event4.subject());
398 + assertEquals(P2, event4.port().number());
399 + assertAnnotationsEquals(event4.port().annotations());
400 + assertFalse("Port is disabled if not given from primary provider",
401 + event4.port().isEnabled());
402 + }
403 +
404 + @Test
405 + public final void testGetPorts() {
406 + putDevice(DID1, SW1);
407 + putDevice(DID2, SW1);
408 + List<PortDescription> pds = Arrays.<PortDescription>asList(
409 + new DefaultPortDescription(P1, true),
410 + new DefaultPortDescription(P2, true)
411 + );
412 + deviceStore.updatePorts(PID, DID1, pds);
413 +
414 + Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
415 + List<Port> ports = deviceStore.getPorts(DID1);
416 + for (Port port : ports) {
417 + assertTrue("Port is enabled", port.isEnabled());
418 + assertTrue("PortNumber is one of expected",
419 + expectedPorts.remove(port.number()));
420 + }
421 + assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
422 +
423 +
424 + assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty());
425 + }
426 +
427 + @Test
428 + public final void testGetPort() {
429 + putDevice(DID1, SW1);
430 + putDevice(DID2, SW1);
431 + List<PortDescription> pds = Arrays.<PortDescription>asList(
432 + new DefaultPortDescription(P1, true),
433 + new DefaultPortDescription(P2, false)
434 + );
435 + deviceStore.updatePorts(PID, DID1, pds);
436 +
437 + Port port1 = deviceStore.getPort(DID1, P1);
438 + assertEquals(P1, port1.number());
439 + assertTrue("Port is enabled", port1.isEnabled());
440 +
441 + Port port2 = deviceStore.getPort(DID1, P2);
442 + assertEquals(P2, port2.number());
443 + assertFalse("Port is disabled", port2.isEnabled());
444 +
445 + Port port3 = deviceStore.getPort(DID1, P3);
446 + assertNull("P3 not expected", port3);
447 + }
448 +
449 + @Test
450 + public final void testRemoveDevice() {
451 + putDevice(DID1, SW1);
452 + putDevice(DID2, SW1);
453 +
454 + assertEquals(2, deviceStore.getDeviceCount());
455 +
456 + DeviceEvent event = deviceStore.removeDevice(DID1);
457 + assertEquals(DEVICE_REMOVED, event.type());
458 + assertDevice(DID1, SW1, event.subject());
459 +
460 + assertEquals(1, deviceStore.getDeviceCount());
461 + }
462 +
463 + // If Delegates should be called only on remote events,
464 + // then Simple* should never call them, thus not test required.
465 + // TODO add test for Port events when we have them
466 + @Ignore("Ignore until Delegate spec. is clear.")
467 + @Test
468 + public final void testEvents() throws InterruptedException {
469 + final CountDownLatch addLatch = new CountDownLatch(1);
470 + DeviceStoreDelegate checkAdd = new DeviceStoreDelegate() {
471 + @Override
472 + public void notify(DeviceEvent event) {
473 + assertEquals(DEVICE_ADDED, event.type());
474 + assertDevice(DID1, SW1, event.subject());
475 + addLatch.countDown();
476 + }
477 + };
478 + final CountDownLatch updateLatch = new CountDownLatch(1);
479 + DeviceStoreDelegate checkUpdate = new DeviceStoreDelegate() {
480 + @Override
481 + public void notify(DeviceEvent event) {
482 + assertEquals(DEVICE_UPDATED, event.type());
483 + assertDevice(DID1, SW2, event.subject());
484 + updateLatch.countDown();
485 + }
486 + };
487 + final CountDownLatch removeLatch = new CountDownLatch(1);
488 + DeviceStoreDelegate checkRemove = new DeviceStoreDelegate() {
489 + @Override
490 + public void notify(DeviceEvent event) {
491 + assertEquals(DEVICE_REMOVED, event.type());
492 + assertDevice(DID1, SW2, event.subject());
493 + removeLatch.countDown();
494 + }
495 + };
496 +
497 + DeviceDescription description =
498 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
499 + HW, SW1, SN);
500 + deviceStore.setDelegate(checkAdd);
501 + deviceStore.createOrUpdateDevice(PID, DID1, description);
502 + assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
503 +
504 +
505 + DeviceDescription description2 =
506 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
507 + HW, SW2, SN);
508 + deviceStore.unsetDelegate(checkAdd);
509 + deviceStore.setDelegate(checkUpdate);
510 + deviceStore.createOrUpdateDevice(PID, DID1, description2);
511 + assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
512 +
513 + deviceStore.unsetDelegate(checkUpdate);
514 + deviceStore.setDelegate(checkRemove);
515 + deviceStore.removeDevice(DID1);
516 + assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));
517 + }
518 +
519 + private static final class TestGossipDeviceStore extends GossipDeviceStore {
520 +
521 + public TestGossipDeviceStore(ClockService clockService) {
522 + this.clockService = clockService;
523 + }
524 + }
525 +}
...@@ -47,6 +47,7 @@ import static com.google.common.cache.CacheBuilder.newBuilder; ...@@ -47,6 +47,7 @@ import static com.google.common.cache.CacheBuilder.newBuilder;
47 import static org.onlab.onos.net.device.DeviceEvent.Type.*; 47 import static org.onlab.onos.net.device.DeviceEvent.Type.*;
48 import static org.slf4j.LoggerFactory.getLogger; 48 import static org.slf4j.LoggerFactory.getLogger;
49 49
50 +//TODO: Add support for multiple provider and annotations
50 /** 51 /**
51 * Manages inventory of infrastructure devices using Hazelcast-backed map. 52 * Manages inventory of infrastructure devices using Hazelcast-backed map.
52 */ 53 */
......
...@@ -4,27 +4,15 @@ import org.apache.felix.scr.annotations.Component; ...@@ -4,27 +4,15 @@ import org.apache.felix.scr.annotations.Component;
4 import org.apache.felix.scr.annotations.Service; 4 import org.apache.felix.scr.annotations.Service;
5 import org.onlab.onos.cluster.MastershipTerm; 5 import org.onlab.onos.cluster.MastershipTerm;
6 import org.onlab.onos.net.DeviceId; 6 import org.onlab.onos.net.DeviceId;
7 -import org.onlab.onos.store.ClockService; 7 +import org.onlab.onos.store.ClockProviderService;
8 -import org.onlab.onos.store.Timestamp;
9 8
10 // FIXME: Code clone in onos-core-trivial, onos-core-hz-net 9 // FIXME: Code clone in onos-core-trivial, onos-core-hz-net
11 /** 10 /**
12 - * Dummy implementation of {@link ClockService}. 11 + * Dummy implementation of {@link ClockProviderService}.
13 */ 12 */
14 @Component(immediate = true) 13 @Component(immediate = true)
15 @Service 14 @Service
16 -public class NoOpClockService implements ClockService { 15 +public class NoOpClockProviderService implements ClockProviderService {
17 -
18 - @Override
19 - public Timestamp getTimestamp(DeviceId deviceId) {
20 - return new Timestamp() {
21 -
22 - @Override
23 - public int compareTo(Timestamp o) {
24 - throw new IllegalStateException("Never expected to be used.");
25 - }
26 - };
27 - }
28 16
29 @Override 17 @Override
30 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { 18 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
......
...@@ -38,6 +38,7 @@ import com.google.common.collect.Multimap; ...@@ -38,6 +38,7 @@ import com.google.common.collect.Multimap;
38 import com.google.common.collect.ImmutableSet.Builder; 38 import com.google.common.collect.ImmutableSet.Builder;
39 import com.hazelcast.core.IMap; 39 import com.hazelcast.core.IMap;
40 40
41 +//TODO: Add support for multiple provider and annotations
41 /** 42 /**
42 * Manages inventory of infrastructure links using Hazelcast-backed map. 43 * Manages inventory of infrastructure links using Hazelcast-backed map.
43 */ 44 */
......
...@@ -3,7 +3,6 @@ package org.onlab.onos.store.serializers; ...@@ -3,7 +3,6 @@ package org.onlab.onos.store.serializers;
3 import org.onlab.onos.net.ConnectPoint; 3 import org.onlab.onos.net.ConnectPoint;
4 import org.onlab.onos.net.ElementId; 4 import org.onlab.onos.net.ElementId;
5 import org.onlab.onos.net.PortNumber; 5 import org.onlab.onos.net.PortNumber;
6 -
7 import com.esotericsoftware.kryo.Kryo; 6 import com.esotericsoftware.kryo.Kryo;
8 import com.esotericsoftware.kryo.Serializer; 7 import com.esotericsoftware.kryo.Serializer;
9 import com.esotericsoftware.kryo.io.Input; 8 import com.esotericsoftware.kryo.io.Input;
...@@ -15,7 +14,7 @@ import com.esotericsoftware.kryo.io.Output; ...@@ -15,7 +14,7 @@ import com.esotericsoftware.kryo.io.Output;
15 public class ConnectPointSerializer extends Serializer<ConnectPoint> { 14 public class ConnectPointSerializer extends Serializer<ConnectPoint> {
16 15
17 /** 16 /**
18 - * Default constructor. 17 + * Creates {@link ConnectPointSerializer} serializer instance.
19 */ 18 */
20 public ConnectPointSerializer() { 19 public ConnectPointSerializer() {
21 // non-null, immutable 20 // non-null, immutable
......
...@@ -16,7 +16,7 @@ import com.esotericsoftware.kryo.io.Output; ...@@ -16,7 +16,7 @@ import com.esotericsoftware.kryo.io.Output;
16 public class DefaultLinkSerializer extends Serializer<DefaultLink> { 16 public class DefaultLinkSerializer extends Serializer<DefaultLink> {
17 17
18 /** 18 /**
19 - * Default constructor. 19 + * Creates {@link DefaultLink} serializer instance.
20 */ 20 */
21 public DefaultLinkSerializer() { 21 public DefaultLinkSerializer() {
22 // non-null, immutable 22 // non-null, immutable
......
...@@ -16,7 +16,7 @@ public final class DefaultPortSerializer extends ...@@ -16,7 +16,7 @@ public final class DefaultPortSerializer extends
16 Serializer<DefaultPort> { 16 Serializer<DefaultPort> {
17 17
18 /** 18 /**
19 - * Default constructor. 19 + * Creates {@link DefaultPort} serializer instance.
20 */ 20 */
21 public DefaultPortSerializer() { 21 public DefaultPortSerializer() {
22 // non-null, immutable 22 // non-null, immutable
......
...@@ -14,6 +14,14 @@ import com.esotericsoftware.kryo.io.Output; ...@@ -14,6 +14,14 @@ import com.esotericsoftware.kryo.io.Output;
14 */ 14 */
15 public final class DeviceIdSerializer extends Serializer<DeviceId> { 15 public final class DeviceIdSerializer extends Serializer<DeviceId> {
16 16
17 + /**
18 + * Creates {@link DeviceId} serializer instance.
19 + */
20 + public DeviceIdSerializer() {
21 + // non-null, immutable
22 + super(false, true);
23 + }
24 +
17 @Override 25 @Override
18 public void write(Kryo kryo, Output output, DeviceId object) { 26 public void write(Kryo kryo, Output output, DeviceId object) {
19 kryo.writeObject(output, object.uri()); 27 kryo.writeObject(output, object.uri());
......
...@@ -19,6 +19,9 @@ public class ImmutableMapSerializer extends FamilySerializer<ImmutableMap<?, ?>> ...@@ -19,6 +19,9 @@ public class ImmutableMapSerializer extends FamilySerializer<ImmutableMap<?, ?>>
19 19
20 private final MapSerializer mapSerializer = new MapSerializer(); 20 private final MapSerializer mapSerializer = new MapSerializer();
21 21
22 + /**
23 + * Creates {@link ImmutableMap} serializer instance.
24 + */
22 public ImmutableMapSerializer() { 25 public ImmutableMapSerializer() {
23 // non-null, immutable 26 // non-null, immutable
24 super(false, true); 27 super(false, true);
......
...@@ -18,6 +18,9 @@ public class ImmutableSetSerializer extends FamilySerializer<ImmutableSet<?>> { ...@@ -18,6 +18,9 @@ public class ImmutableSetSerializer extends FamilySerializer<ImmutableSet<?>> {
18 18
19 private final CollectionSerializer serializer = new CollectionSerializer(); 19 private final CollectionSerializer serializer = new CollectionSerializer();
20 20
21 + /**
22 + * Creates {@link ImmutableSet} serializer instance.
23 + */
21 public ImmutableSetSerializer() { 24 public ImmutableSetSerializer() {
22 // non-null, immutable 25 // non-null, immutable
23 super(false, true); 26 super(false, true);
......
1 +package org.onlab.onos.store.serializers;
2 +
3 +import org.onlab.packet.IpAddress;
4 +import com.esotericsoftware.kryo.Kryo;
5 +import com.esotericsoftware.kryo.Serializer;
6 +import com.esotericsoftware.kryo.io.Input;
7 +import com.esotericsoftware.kryo.io.Output;
8 +
9 +/**
10 + * Kryo Serializer for {@link IpAddress}.
11 + */
12 +public class IpAddressSerializer extends Serializer<IpAddress> {
13 +
14 + /**
15 + * Creates {@link IpAddress} serializer instance.
16 + */
17 + public IpAddressSerializer() {
18 + // non-null, immutable
19 + super(false, true);
20 + }
21 +
22 + @Override
23 + public void write(Kryo kryo, Output output,
24 + IpAddress object) {
25 + byte[] octs = object.toOctets();
26 + output.writeInt(octs.length);
27 + output.writeBytes(octs);
28 + output.writeInt(object.prefixLength());
29 + }
30 +
31 + @Override
32 + public IpAddress read(Kryo kryo, Input input,
33 + Class<IpAddress> type) {
34 + int octLen = input.readInt();
35 + byte[] octs = new byte[octLen];
36 + input.read(octs);
37 + int prefLen = input.readInt();
38 + return IpAddress.valueOf(octs, prefLen);
39 + }
40 +
41 +}
...@@ -13,7 +13,7 @@ import com.esotericsoftware.kryo.io.Output; ...@@ -13,7 +13,7 @@ import com.esotericsoftware.kryo.io.Output;
13 public final class IpPrefixSerializer extends Serializer<IpPrefix> { 13 public final class IpPrefixSerializer extends Serializer<IpPrefix> {
14 14
15 /** 15 /**
16 - * Default constructor. 16 + * Creates {@link IpPrefix} serializer instance.
17 */ 17 */
18 public IpPrefixSerializer() { 18 public IpPrefixSerializer() {
19 // non-null, immutable 19 // non-null, immutable
......
1 +package org.onlab.onos.store.serializers;
2 +
3 +import java.net.URI;
4 +import java.util.ArrayList;
5 +import java.util.HashMap;
6 +
7 +import org.onlab.onos.cluster.ControllerNode;
8 +import org.onlab.onos.cluster.DefaultControllerNode;
9 +import org.onlab.onos.cluster.MastershipTerm;
10 +import org.onlab.onos.cluster.NodeId;
11 +import org.onlab.onos.net.ConnectPoint;
12 +import org.onlab.onos.net.DefaultAnnotations;
13 +import org.onlab.onos.net.DefaultDevice;
14 +import org.onlab.onos.net.DefaultLink;
15 +import org.onlab.onos.net.DefaultPort;
16 +import org.onlab.onos.net.Device;
17 +import org.onlab.onos.net.DeviceId;
18 +import org.onlab.onos.net.Element;
19 +import org.onlab.onos.net.Link;
20 +import org.onlab.onos.net.LinkKey;
21 +import org.onlab.onos.net.MastershipRole;
22 +import org.onlab.onos.net.Port;
23 +import org.onlab.onos.net.PortNumber;
24 +import org.onlab.onos.net.provider.ProviderId;
25 +import org.onlab.packet.IpAddress;
26 +import org.onlab.packet.IpPrefix;
27 +import org.onlab.util.KryoPool;
28 +
29 +import de.javakaffee.kryoserializers.URISerializer;
30 +
31 +public final class KryoPoolUtil {
32 +
33 + /**
34 + * KryoPool which can serialize ON.lab misc classes.
35 + */
36 + public static final KryoPool MISC = KryoPool.newBuilder()
37 + .register(IpPrefix.class, new IpPrefixSerializer())
38 + .register(IpAddress.class, new IpAddressSerializer())
39 + .build();
40 +
41 + // TODO: Populate other classes
42 + /**
43 + * KryoPool which can serialize API bundle classes.
44 + */
45 + public static final KryoPool API = KryoPool.newBuilder()
46 + .register(MISC)
47 + .register(
48 + //
49 + ArrayList.class,
50 + HashMap.class,
51 + //
52 + ControllerNode.State.class,
53 + Device.Type.class,
54 + DefaultAnnotations.class,
55 + DefaultControllerNode.class,
56 + DefaultDevice.class,
57 + MastershipRole.class,
58 + Port.class,
59 + Element.class,
60 + Link.Type.class
61 + )
62 + .register(URI.class, new URISerializer())
63 + .register(NodeId.class, new NodeIdSerializer())
64 + .register(ProviderId.class, new ProviderIdSerializer())
65 + .register(DeviceId.class, new DeviceIdSerializer())
66 + .register(PortNumber.class, new PortNumberSerializer())
67 + .register(DefaultPort.class, new DefaultPortSerializer())
68 + .register(LinkKey.class, new LinkKeySerializer())
69 + .register(ConnectPoint.class, new ConnectPointSerializer())
70 + .register(DefaultLink.class, new DefaultLinkSerializer())
71 + .register(MastershipTerm.class, new MastershipTermSerializer())
72 + .register(MastershipRole.class, new MastershipRoleSerializer())
73 +
74 + .build();
75 +
76 +
77 + // not to be instantiated
78 + private KryoPoolUtil() {}
79 +}
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 -import de.javakaffee.kryoserializers.URISerializer;
4 import org.apache.felix.scr.annotations.Activate; 3 import org.apache.felix.scr.annotations.Activate;
5 import org.apache.felix.scr.annotations.Component; 4 import org.apache.felix.scr.annotations.Component;
6 import org.apache.felix.scr.annotations.Deactivate; 5 import org.apache.felix.scr.annotations.Deactivate;
7 import org.apache.felix.scr.annotations.Service; 6 import org.apache.felix.scr.annotations.Service;
8 -import org.onlab.onos.cluster.ControllerNode;
9 -import org.onlab.onos.cluster.DefaultControllerNode;
10 -import org.onlab.onos.cluster.NodeId;
11 -import org.onlab.onos.net.ConnectPoint;
12 -import org.onlab.onos.net.DefaultAnnotations;
13 -import org.onlab.onos.net.DefaultDevice;
14 -import org.onlab.onos.net.DefaultLink;
15 -import org.onlab.onos.net.DefaultPort;
16 -import org.onlab.onos.net.Device;
17 -import org.onlab.onos.net.DeviceId;
18 -import org.onlab.onos.net.Element;
19 -import org.onlab.onos.net.Link;
20 -import org.onlab.onos.net.LinkKey;
21 -import org.onlab.onos.net.MastershipRole;
22 -import org.onlab.onos.net.Port;
23 -import org.onlab.onos.net.PortNumber;
24 -import org.onlab.onos.net.provider.ProviderId;
25 -import org.onlab.packet.IpPrefix;
26 import org.onlab.util.KryoPool; 7 import org.onlab.util.KryoPool;
27 import org.slf4j.Logger; 8 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory; 9 import org.slf4j.LoggerFactory;
29 10
30 -import java.net.URI;
31 import java.nio.ByteBuffer; 11 import java.nio.ByteBuffer;
32 -import java.util.ArrayList;
33 -import java.util.HashMap;
34 12
35 /** 13 /**
36 * Serialization service using Kryo. 14 * Serialization service using Kryo.
...@@ -58,33 +36,8 @@ public class KryoSerializationManager implements KryoSerializationService { ...@@ -58,33 +36,8 @@ public class KryoSerializationManager implements KryoSerializationService {
58 * Sets up the common serialzers pool. 36 * Sets up the common serialzers pool.
59 */ 37 */
60 protected void setupKryoPool() { 38 protected void setupKryoPool() {
61 - // FIXME Slice out types used in common to separate pool/namespace.
62 serializerPool = KryoPool.newBuilder() 39 serializerPool = KryoPool.newBuilder()
63 - .register(ArrayList.class, 40 + .register(KryoPoolUtil.API)
64 - HashMap.class,
65 -
66 - ControllerNode.State.class,
67 - Device.Type.class,
68 -
69 - DefaultAnnotations.class,
70 - DefaultControllerNode.class,
71 - DefaultDevice.class,
72 - MastershipRole.class,
73 - Port.class,
74 - Element.class,
75 -
76 - Link.Type.class
77 - )
78 - .register(IpPrefix.class, new IpPrefixSerializer())
79 - .register(URI.class, new URISerializer())
80 - .register(NodeId.class, new NodeIdSerializer())
81 - .register(ProviderId.class, new ProviderIdSerializer())
82 - .register(DeviceId.class, new DeviceIdSerializer())
83 - .register(PortNumber.class, new PortNumberSerializer())
84 - .register(DefaultPort.class, new DefaultPortSerializer())
85 - .register(LinkKey.class, new LinkKeySerializer())
86 - .register(ConnectPoint.class, new ConnectPointSerializer())
87 - .register(DefaultLink.class, new DefaultLinkSerializer())
88 .build() 41 .build()
89 .populate(1); 42 .populate(1);
90 } 43 }
......
...@@ -2,6 +2,7 @@ package org.onlab.onos.store.serializers; ...@@ -2,6 +2,7 @@ package org.onlab.onos.store.serializers;
2 2
3 import org.onlab.onos.net.ConnectPoint; 3 import org.onlab.onos.net.ConnectPoint;
4 import org.onlab.onos.net.LinkKey; 4 import org.onlab.onos.net.LinkKey;
5 +
5 import com.esotericsoftware.kryo.Kryo; 6 import com.esotericsoftware.kryo.Kryo;
6 import com.esotericsoftware.kryo.Serializer; 7 import com.esotericsoftware.kryo.Serializer;
7 import com.esotericsoftware.kryo.io.Input; 8 import com.esotericsoftware.kryo.io.Input;
...@@ -13,7 +14,7 @@ import com.esotericsoftware.kryo.io.Output; ...@@ -13,7 +14,7 @@ import com.esotericsoftware.kryo.io.Output;
13 public class LinkKeySerializer extends Serializer<LinkKey> { 14 public class LinkKeySerializer extends Serializer<LinkKey> {
14 15
15 /** 16 /**
16 - * Default constructor. 17 + * Creates {@link LinkKey} serializer instance.
17 */ 18 */
18 public LinkKeySerializer() { 19 public LinkKeySerializer() {
19 // non-null, immutable 20 // non-null, immutable
......
...@@ -12,6 +12,14 @@ import com.esotericsoftware.kryo.io.Output; ...@@ -12,6 +12,14 @@ import com.esotericsoftware.kryo.io.Output;
12 */ 12 */
13 public class MastershipRoleSerializer extends Serializer<MastershipRole> { 13 public class MastershipRoleSerializer extends Serializer<MastershipRole> {
14 14
15 + /**
16 + * Creates {@link MastershipRole} serializer instance.
17 + */
18 + public MastershipRoleSerializer() {
19 + // non-null, immutable
20 + super(false, true);
21 + }
22 +
15 @Override 23 @Override
16 public MastershipRole read(Kryo kryo, Input input, Class<MastershipRole> type) { 24 public MastershipRole read(Kryo kryo, Input input, Class<MastershipRole> type) {
17 final String role = kryo.readObject(input, String.class); 25 final String role = kryo.readObject(input, String.class);
......
...@@ -2,7 +2,6 @@ package org.onlab.onos.store.serializers; ...@@ -2,7 +2,6 @@ package org.onlab.onos.store.serializers;
2 2
3 import org.onlab.onos.cluster.MastershipTerm; 3 import org.onlab.onos.cluster.MastershipTerm;
4 import org.onlab.onos.cluster.NodeId; 4 import org.onlab.onos.cluster.NodeId;
5 -
6 import com.esotericsoftware.kryo.Kryo; 5 import com.esotericsoftware.kryo.Kryo;
7 import com.esotericsoftware.kryo.Serializer; 6 import com.esotericsoftware.kryo.Serializer;
8 import com.esotericsoftware.kryo.io.Input; 7 import com.esotericsoftware.kryo.io.Input;
...@@ -13,6 +12,14 @@ import com.esotericsoftware.kryo.io.Output; ...@@ -13,6 +12,14 @@ import com.esotericsoftware.kryo.io.Output;
13 */ 12 */
14 public class MastershipTermSerializer extends Serializer<MastershipTerm> { 13 public class MastershipTermSerializer extends Serializer<MastershipTerm> {
15 14
15 + /**
16 + * Creates {@link MastershipTerm} serializer instance.
17 + */
18 + public MastershipTermSerializer() {
19 + // non-null, immutable
20 + super(false, true);
21 + }
22 +
16 @Override 23 @Override
17 public MastershipTerm read(Kryo kryo, Input input, Class<MastershipTerm> type) { 24 public MastershipTerm read(Kryo kryo, Input input, Class<MastershipTerm> type) {
18 final NodeId node = new NodeId(kryo.readObject(input, String.class)); 25 final NodeId node = new NodeId(kryo.readObject(input, String.class));
......
...@@ -4,6 +4,7 @@ import com.esotericsoftware.kryo.Kryo; ...@@ -4,6 +4,7 @@ import com.esotericsoftware.kryo.Kryo;
4 import com.esotericsoftware.kryo.Serializer; 4 import com.esotericsoftware.kryo.Serializer;
5 import com.esotericsoftware.kryo.io.Input; 5 import com.esotericsoftware.kryo.io.Input;
6 import com.esotericsoftware.kryo.io.Output; 6 import com.esotericsoftware.kryo.io.Output;
7 +
7 import org.onlab.onos.cluster.NodeId; 8 import org.onlab.onos.cluster.NodeId;
8 9
9 /** 10 /**
...@@ -11,6 +12,14 @@ import org.onlab.onos.cluster.NodeId; ...@@ -11,6 +12,14 @@ import org.onlab.onos.cluster.NodeId;
11 */ 12 */
12 public final class NodeIdSerializer extends Serializer<NodeId> { 13 public final class NodeIdSerializer extends Serializer<NodeId> {
13 14
15 + /**
16 + * Creates {@link NodeId} serializer instance.
17 + */
18 + public NodeIdSerializer() {
19 + // non-null, immutable
20 + super(false, true);
21 + }
22 +
14 @Override 23 @Override
15 public void write(Kryo kryo, Output output, NodeId object) { 24 public void write(Kryo kryo, Output output, NodeId object) {
16 kryo.writeObject(output, object.toString()); 25 kryo.writeObject(output, object.toString());
......
...@@ -14,7 +14,7 @@ public final class PortNumberSerializer extends ...@@ -14,7 +14,7 @@ public final class PortNumberSerializer extends
14 Serializer<PortNumber> { 14 Serializer<PortNumber> {
15 15
16 /** 16 /**
17 - * Default constructor. 17 + * Creates {@link PortNumber} serializer instance.
18 */ 18 */
19 public PortNumberSerializer() { 19 public PortNumberSerializer() {
20 // non-null, immutable 20 // non-null, immutable
......
...@@ -13,7 +13,7 @@ import com.esotericsoftware.kryo.io.Output; ...@@ -13,7 +13,7 @@ import com.esotericsoftware.kryo.io.Output;
13 public class ProviderIdSerializer extends Serializer<ProviderId> { 13 public class ProviderIdSerializer extends Serializer<ProviderId> {
14 14
15 /** 15 /**
16 - * Default constructor. 16 + * Creates {@link ProviderId} serializer instance.
17 */ 17 */
18 public ProviderIdSerializer() { 18 public ProviderIdSerializer() {
19 // non-null, immutable 19 // non-null, immutable
......
...@@ -3,16 +3,11 @@ package org.onlab.onos.store.serializers; ...@@ -3,16 +3,11 @@ package org.onlab.onos.store.serializers;
3 import static org.onlab.onos.net.DeviceId.deviceId; 3 import static org.onlab.onos.net.DeviceId.deviceId;
4 import static org.onlab.onos.net.PortNumber.portNumber; 4 import static org.onlab.onos.net.PortNumber.portNumber;
5 5
6 -import java.net.URI;
7 import java.nio.ByteBuffer; 6 import java.nio.ByteBuffer;
8 -import java.util.ArrayList;
9 -import java.util.HashMap;
10 -
11 import org.junit.After; 7 import org.junit.After;
12 import org.junit.Before; 8 import org.junit.Before;
13 import org.junit.BeforeClass; 9 import org.junit.BeforeClass;
14 import org.junit.Test; 10 import org.junit.Test;
15 -import org.onlab.onos.cluster.MastershipTerm;
16 import org.onlab.onos.cluster.NodeId; 11 import org.onlab.onos.cluster.NodeId;
17 import org.onlab.onos.net.ConnectPoint; 12 import org.onlab.onos.net.ConnectPoint;
18 import org.onlab.onos.net.DefaultDevice; 13 import org.onlab.onos.net.DefaultDevice;
...@@ -22,7 +17,6 @@ import org.onlab.onos.net.Device; ...@@ -22,7 +17,6 @@ import org.onlab.onos.net.Device;
22 import org.onlab.onos.net.DeviceId; 17 import org.onlab.onos.net.DeviceId;
23 import org.onlab.onos.net.Link; 18 import org.onlab.onos.net.Link;
24 import org.onlab.onos.net.LinkKey; 19 import org.onlab.onos.net.LinkKey;
25 -import org.onlab.onos.net.MastershipRole;
26 import org.onlab.onos.net.PortNumber; 20 import org.onlab.onos.net.PortNumber;
27 import org.onlab.onos.net.provider.ProviderId; 21 import org.onlab.onos.net.provider.ProviderId;
28 import org.onlab.packet.IpPrefix; 22 import org.onlab.packet.IpPrefix;
...@@ -32,8 +26,6 @@ import com.google.common.collect.ImmutableMap; ...@@ -32,8 +26,6 @@ import com.google.common.collect.ImmutableMap;
32 import com.google.common.collect.ImmutableSet; 26 import com.google.common.collect.ImmutableSet;
33 import com.google.common.testing.EqualsTester; 27 import com.google.common.testing.EqualsTester;
34 28
35 -import de.javakaffee.kryoserializers.URISerializer;
36 -
37 public class KryoSerializerTests { 29 public class KryoSerializerTests {
38 private static final ProviderId PID = new ProviderId("of", "foo"); 30 private static final ProviderId PID = new ProviderId("of", "foo");
39 private static final DeviceId DID1 = deviceId("of:foo"); 31 private static final DeviceId DID1 = deviceId("of:foo");
...@@ -54,38 +46,12 @@ public class KryoSerializerTests { ...@@ -54,38 +46,12 @@ public class KryoSerializerTests {
54 @BeforeClass 46 @BeforeClass
55 public static void setUpBeforeClass() throws Exception { 47 public static void setUpBeforeClass() throws Exception {
56 kryos = KryoPool.newBuilder() 48 kryos = KryoPool.newBuilder()
57 - .register( 49 + .register(KryoPoolUtil.API)
58 - ArrayList.class,
59 - HashMap.class
60 - )
61 - .register(
62 - Device.Type.class,
63 - Link.Type.class
64 -
65 -// ControllerNode.State.class,
66 -// DefaultControllerNode.class,
67 -// MastershipRole.class,
68 -// Port.class,
69 -// Element.class,
70 - )
71 - .register(ConnectPoint.class, new ConnectPointSerializer())
72 - .register(DefaultLink.class, new DefaultLinkSerializer())
73 - .register(DefaultPort.class, new DefaultPortSerializer())
74 - .register(DeviceId.class, new DeviceIdSerializer())
75 .register(ImmutableMap.class, new ImmutableMapSerializer()) 50 .register(ImmutableMap.class, new ImmutableMapSerializer())
76 .register(ImmutableSet.class, new ImmutableSetSerializer()) 51 .register(ImmutableSet.class, new ImmutableSetSerializer())
77 - .register(IpPrefix.class, new IpPrefixSerializer())
78 - .register(LinkKey.class, new LinkKeySerializer())
79 - .register(NodeId.class, new NodeIdSerializer())
80 - .register(PortNumber.class, new PortNumberSerializer())
81 - .register(ProviderId.class, new ProviderIdSerializer())
82 52
83 - .register(DefaultDevice.class)
84 53
85 - .register(URI.class, new URISerializer())
86 54
87 - .register(MastershipRole.class, new MastershipRoleSerializer())
88 - .register(MastershipTerm.class, new MastershipTermSerializer())
89 .build(); 55 .build();
90 } 56 }
91 57
......
...@@ -4,27 +4,15 @@ import org.apache.felix.scr.annotations.Component; ...@@ -4,27 +4,15 @@ import org.apache.felix.scr.annotations.Component;
4 import org.apache.felix.scr.annotations.Service; 4 import org.apache.felix.scr.annotations.Service;
5 import org.onlab.onos.cluster.MastershipTerm; 5 import org.onlab.onos.cluster.MastershipTerm;
6 import org.onlab.onos.net.DeviceId; 6 import org.onlab.onos.net.DeviceId;
7 -import org.onlab.onos.store.ClockService; 7 +import org.onlab.onos.store.ClockProviderService;
8 -import org.onlab.onos.store.Timestamp;
9 8
10 //FIXME: Code clone in onos-core-trivial, onos-core-hz-net 9 //FIXME: Code clone in onos-core-trivial, onos-core-hz-net
11 /** 10 /**
12 - * Dummy implementation of {@link ClockService}. 11 + * Dummy implementation of {@link ClockProviderService}.
13 */ 12 */
14 @Component(immediate = true) 13 @Component(immediate = true)
15 @Service 14 @Service
16 -public class NoOpClockService implements ClockService { 15 +public class NoOpClockProviderService implements ClockProviderService {
17 -
18 - @Override
19 - public Timestamp getTimestamp(DeviceId deviceId) {
20 - return new Timestamp() {
21 -
22 - @Override
23 - public int compareTo(Timestamp o) {
24 - throw new IllegalStateException("Never expected to be used.");
25 - }
26 - };
27 - }
28 16
29 @Override 17 @Override
30 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { 18 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
......
1 +package org.onlab.onos.store.trivial.impl;
2 +
3 +import static org.onlab.onos.net.intent.IntentState.COMPILED;
4 +import static org.slf4j.LoggerFactory.getLogger;
5 +
6 +import java.util.HashMap;
7 +import java.util.List;
8 +import java.util.Map;
9 +
10 +import org.apache.felix.scr.annotations.Activate;
11 +import org.apache.felix.scr.annotations.Component;
12 +import org.apache.felix.scr.annotations.Deactivate;
13 +import org.apache.felix.scr.annotations.Service;
14 +import org.onlab.onos.net.intent.InstallableIntent;
15 +import org.onlab.onos.net.intent.Intent;
16 +import org.onlab.onos.net.intent.IntentEvent;
17 +import org.onlab.onos.net.intent.IntentId;
18 +import org.onlab.onos.net.intent.IntentState;
19 +import org.onlab.onos.net.intent.IntentStore;
20 +import org.onlab.onos.net.intent.IntentStoreDelegate;
21 +import org.onlab.onos.store.AbstractStore;
22 +import org.slf4j.Logger;
23 +
24 +import com.google.common.collect.ImmutableSet;
25 +
26 +@Component(immediate = true)
27 +@Service
28 +public class SimpleIntentStore
29 + extends AbstractStore<IntentEvent, IntentStoreDelegate>
30 + implements IntentStore {
31 +
32 + private final Logger log = getLogger(getClass());
33 + private final Map<IntentId, Intent> intents = new HashMap<>();
34 + private final Map<IntentId, IntentState> states = new HashMap<>();
35 + private final Map<IntentId, List<InstallableIntent>> installable = new HashMap<>();
36 +
37 + @Activate
38 + public void activate() {
39 + log.info("Started");
40 + }
41 +
42 + @Deactivate
43 + public void deactivate() {
44 + log.info("Stopped");
45 + }
46 +
47 + @Override
48 + public IntentEvent createIntent(Intent intent) {
49 + intents.put(intent.getId(), intent);
50 + return this.setState(intent, IntentState.SUBMITTED);
51 + }
52 +
53 + @Override
54 + public IntentEvent removeIntent(IntentId intentId) {
55 + Intent intent = intents.remove(intentId);
56 + installable.remove(intentId);
57 + IntentEvent event = this.setState(intent, IntentState.WITHDRAWN);
58 + states.remove(intentId);
59 + return event;
60 + }
61 +
62 + @Override
63 + public long getIntentCount() {
64 + return intents.size();
65 + }
66 +
67 + @Override
68 + public Iterable<Intent> getIntents() {
69 + return ImmutableSet.copyOf(intents.values());
70 + }
71 +
72 + @Override
73 + public Intent getIntent(IntentId intentId) {
74 + return intents.get(intentId);
75 + }
76 +
77 + @Override
78 + public IntentState getIntentState(IntentId id) {
79 + return states.get(id);
80 + }
81 +
82 + // TODO return dispatch event here... replace with state transition methods
83 + @Override
84 + public IntentEvent setState(Intent intent, IntentState newState) {
85 + IntentId id = intent.getId();
86 + IntentState oldState = states.get(id);
87 + states.put(id, newState);
88 + return new IntentEvent(intent, newState, oldState, System.currentTimeMillis());
89 + }
90 +
91 + @Override
92 + public IntentEvent addInstallableIntents(IntentId intentId, List<InstallableIntent> result) {
93 + installable.put(intentId, result);
94 + return this.setState(intents.get(intentId), COMPILED);
95 + }
96 +
97 + @Override
98 + public List<InstallableIntent> getInstallableIntents(IntentId intentId) {
99 + return installable.get(intentId);
100 + }
101 +
102 + @Override
103 + public void removeInstalledIntents(IntentId intentId) {
104 + installable.remove(intentId);
105 + }
106 +
107 +}
...@@ -32,6 +32,7 @@ import static org.onlab.onos.net.Link.Type.INDIRECT; ...@@ -32,6 +32,7 @@ import static org.onlab.onos.net.Link.Type.INDIRECT;
32 import static org.onlab.onos.net.link.LinkEvent.Type.*; 32 import static org.onlab.onos.net.link.LinkEvent.Type.*;
33 import static org.slf4j.LoggerFactory.getLogger; 33 import static org.slf4j.LoggerFactory.getLogger;
34 34
35 +// TODO: Add support for multiple provider and annotations
35 /** 36 /**
36 * Manages inventory of infrastructure links using trivial in-memory structures 37 * Manages inventory of infrastructure links using trivial in-memory structures
37 * implementation. 38 * implementation.
......
...@@ -480,7 +480,7 @@ ...@@ -480,7 +480,7 @@
480 <group> 480 <group>
481 <title>Core Subsystems</title> 481 <title>Core Subsystems</title>
482 <packages> 482 <packages>
483 - org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.* 483 + org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*:org.onlab.onos.net.intent.impl
484 </packages> 484 </packages>
485 </group> 485 </group>
486 <group> 486 <group>
......
...@@ -113,7 +113,7 @@ public class FlowRuleBuilder { ...@@ -113,7 +113,7 @@ public class FlowRuleBuilder {
113 } 113 }
114 114
115 private TrafficTreatment buildTreatment() { 115 private TrafficTreatment buildTreatment() {
116 - TrafficTreatment.Builder builder = new DefaultTrafficTreatment.Builder(); 116 + TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
117 // If this is a drop rule 117 // If this is a drop rule
118 if (actions.size() == 0) { 118 if (actions.size() == 0) {
119 builder.drop(); 119 builder.drop();
...@@ -198,7 +198,7 @@ public class FlowRuleBuilder { ...@@ -198,7 +198,7 @@ public class FlowRuleBuilder {
198 } 198 }
199 199
200 private TrafficSelector buildSelector() { 200 private TrafficSelector buildSelector() {
201 - TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder(); 201 + TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
202 for (MatchField<?> field : match.getMatchFields()) { 202 for (MatchField<?> field : match.getMatchFields()) {
203 switch (field.id) { 203 switch (field.id) {
204 case IN_PORT: 204 case IN_PORT:
......
...@@ -181,7 +181,7 @@ public class OpenFlowPacketProviderTest { ...@@ -181,7 +181,7 @@ public class OpenFlowPacketProviderTest {
181 } 181 }
182 182
183 private static TrafficTreatment treatment(Instruction ... insts) { 183 private static TrafficTreatment treatment(Instruction ... insts) {
184 - TrafficTreatment.Builder builder = new DefaultTrafficTreatment.Builder(); 184 + TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
185 for (Instruction i : insts) { 185 for (Instruction i : insts) {
186 builder.add(i); 186 builder.add(i);
187 } 187 }
......
...@@ -21,7 +21,7 @@ export PATH="$PATH:." ...@@ -21,7 +21,7 @@ export PATH="$PATH:."
21 # e.g. 'o api', 'o dev', 'o' 21 # e.g. 'o api', 'o dev', 'o'
22 function o { 22 function o {
23 cd $(find $ONOS_ROOT/ -type d | egrep -v '\.git|target' | \ 23 cd $(find $ONOS_ROOT/ -type d | egrep -v '\.git|target' | \
24 - egrep "${1:-$ONOS_ROOT}" | head -n 1) 24 + egrep "${1:-$ONOS_ROOT}" | egrep -v "$ONOS_ROOT/.+/src/" | head -n 1)
25 } 25 }
26 26
27 # Short-hand for 'mvn clean install' for us lazy folk 27 # Short-hand for 'mvn clean install' for us lazy folk
......
...@@ -11,7 +11,7 @@ public class MetricsFeature { ...@@ -11,7 +11,7 @@ public class MetricsFeature {
11 * 11 *
12 * @param newName name of the Feature 12 * @param newName name of the Feature
13 */ 13 */
14 - MetricsFeature(final String newName) { 14 + public MetricsFeature(final String newName) {
15 name = newName; 15 name = newName;
16 } 16 }
17 17
......
...@@ -2,16 +2,43 @@ package org.onlab.netty; ...@@ -2,16 +2,43 @@ package org.onlab.netty;
2 2
3 import java.util.concurrent.TimeUnit; 3 import java.util.concurrent.TimeUnit;
4 4
5 +import org.onlab.metrics.MetricsComponent;
6 +import org.onlab.metrics.MetricsFeature;
7 +import org.onlab.metrics.MetricsManager;
8 +
9 +import com.codahale.metrics.Timer;
10 +
5 public final class SimpleClient { 11 public final class SimpleClient {
6 - private SimpleClient() {} 12 + private SimpleClient() {
13 + }
7 14
8 public static void main(String... args) throws Exception { 15 public static void main(String... args) throws Exception {
9 NettyMessagingService messaging = new TestNettyMessagingService(9081); 16 NettyMessagingService messaging = new TestNettyMessagingService(9081);
17 + MetricsManager metrics = new MetricsManager();
10 messaging.activate(); 18 messaging.activate();
19 + metrics.activate();
20 + MetricsFeature feature = new MetricsFeature("timers");
21 + MetricsComponent component = metrics.registerComponent("NettyMessaging");
22 + Timer sendAsyncTimer = metrics.createTimer(component, feature, "AsyncSender");
23 + final int warmup = 100;
24 + for (int i = 0; i < warmup; i++) {
25 + Timer.Context context = sendAsyncTimer.time();
26 + messaging.sendAsync(new Endpoint("localhost", 8080), "simple", "Hello World");
27 + context.stop();
28 + }
29 + metrics.registerMetric(component, feature, "AsyncTimer", sendAsyncTimer);
11 30
12 - messaging.sendAsync(new Endpoint("localhost", 8080), "simple", "Hello World"); 31 + Timer sendAndReceiveTimer = metrics.createTimer(component, feature, "SendAndReceive");
13 - Response<String> response = messaging.sendAndReceive(new Endpoint("localhost", 8080), "echo", "Hello World"); 32 + final int iterations = 1000000;
14 - System.out.println("Got back:" + response.get(2, TimeUnit.SECONDS)); 33 + for (int i = 0; i < iterations; i++) {
34 + Timer.Context context = sendAndReceiveTimer.time();
35 + Response<String> response = messaging
36 + .sendAndReceive(new Endpoint("localhost", 8080), "echo",
37 + "Hello World");
38 + System.out.println("Got back:" + response.get(2, TimeUnit.SECONDS));
39 + context.stop();
40 + }
41 + metrics.registerMetric(component, feature, "AsyncTimer", sendAndReceiveTimer);
15 } 42 }
16 43
17 public static class TestNettyMessagingService extends NettyMessagingService { 44 public static class TestNettyMessagingService extends NettyMessagingService {
......