Ayaka Koshibe

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

Showing 50 changed files with 1342 additions and 197 deletions
...@@ -3,8 +3,6 @@ package org.onlab.onos.config; ...@@ -3,8 +3,6 @@ package org.onlab.onos.config;
3 import java.util.List; 3 import java.util.List;
4 4
5 import org.codehaus.jackson.annotate.JsonProperty; 5 import org.codehaus.jackson.annotate.JsonProperty;
6 -import org.onlab.packet.IpPrefix;
7 -import org.onlab.packet.MacAddress;
8 6
9 /** 7 /**
10 * Represents a set of addresses bound to a port. 8 * Represents a set of addresses bound to a port.
...@@ -12,8 +10,8 @@ import org.onlab.packet.MacAddress; ...@@ -12,8 +10,8 @@ import org.onlab.packet.MacAddress;
12 public class AddressEntry { 10 public class AddressEntry {
13 private String dpid; 11 private String dpid;
14 private short portNumber; 12 private short portNumber;
15 - private List<IpPrefix> ipAddresses; 13 + private List<String> ipAddresses;
16 - private MacAddress macAddress; 14 + private String macAddress;
17 15
18 public String getDpid() { 16 public String getDpid() {
19 return dpid; 17 return dpid;
...@@ -33,21 +31,21 @@ public class AddressEntry { ...@@ -33,21 +31,21 @@ public class AddressEntry {
33 this.portNumber = portNumber; 31 this.portNumber = portNumber;
34 } 32 }
35 33
36 - public List<IpPrefix> getIpAddresses() { 34 + public List<String> getIpAddresses() {
37 return ipAddresses; 35 return ipAddresses;
38 } 36 }
39 37
40 @JsonProperty("ips") 38 @JsonProperty("ips")
41 - public void setIpAddresses(List<IpPrefix> ipAddresses) { 39 + public void setIpAddresses(List<String> strIps) {
42 - this.ipAddresses = ipAddresses; 40 + this.ipAddresses = strIps;
43 } 41 }
44 42
45 - public MacAddress getMacAddress() { 43 + public String getMacAddress() {
46 return macAddress; 44 return macAddress;
47 } 45 }
48 46
49 @JsonProperty("mac") 47 @JsonProperty("mac")
50 - public void setMacAddress(MacAddress macAddress) { 48 + public void setMacAddress(String macAddress) {
51 this.macAddress = macAddress; 49 this.macAddress = macAddress;
52 } 50 }
53 } 51 }
......
...@@ -5,6 +5,8 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -5,6 +5,8 @@ import static org.slf4j.LoggerFactory.getLogger;
5 import java.io.File; 5 import java.io.File;
6 import java.io.FileNotFoundException; 6 import java.io.FileNotFoundException;
7 import java.io.IOException; 7 import java.io.IOException;
8 +import java.util.HashSet;
9 +import java.util.Set;
8 10
9 import org.apache.felix.scr.annotations.Activate; 11 import org.apache.felix.scr.annotations.Activate;
10 import org.apache.felix.scr.annotations.Component; 12 import org.apache.felix.scr.annotations.Component;
...@@ -17,10 +19,10 @@ import org.onlab.onos.net.DeviceId; ...@@ -17,10 +19,10 @@ import org.onlab.onos.net.DeviceId;
17 import org.onlab.onos.net.PortNumber; 19 import org.onlab.onos.net.PortNumber;
18 import org.onlab.onos.net.host.HostAdminService; 20 import org.onlab.onos.net.host.HostAdminService;
19 import org.onlab.onos.net.host.PortAddresses; 21 import org.onlab.onos.net.host.PortAddresses;
22 +import org.onlab.packet.IpPrefix;
23 +import org.onlab.packet.MacAddress;
20 import org.slf4j.Logger; 24 import org.slf4j.Logger;
21 25
22 -import com.google.common.collect.Sets;
23 -
24 /** 26 /**
25 * Simple configuration module to read in supplementary network configuration 27 * Simple configuration module to read in supplementary network configuration
26 * from a file. 28 * from a file.
...@@ -51,9 +53,29 @@ public class NetworkConfigReader { ...@@ -51,9 +53,29 @@ public class NetworkConfigReader {
51 DeviceId.deviceId(dpidToUri(entry.getDpid())), 53 DeviceId.deviceId(dpidToUri(entry.getDpid())),
52 PortNumber.portNumber(entry.getPortNumber())); 54 PortNumber.portNumber(entry.getPortNumber()));
53 55
54 - PortAddresses addresses = new PortAddresses(cp, 56 + Set<IpPrefix> ipAddresses = new HashSet<IpPrefix>();
55 - Sets.newHashSet(entry.getIpAddresses()), 57 +
58 + for (String strIp : entry.getIpAddresses()) {
59 + try {
60 + IpPrefix address = IpPrefix.valueOf(strIp);
61 + ipAddresses.add(address);
62 + } catch (IllegalArgumentException e) {
63 + log.warn("Bad format for IP address in config: {}", strIp);
64 + }
65 + }
66 +
67 + MacAddress macAddress = null;
68 + if (entry.getMacAddress() != null) {
69 + try {
70 + macAddress = MacAddress.valueOf(entry.getMacAddress());
71 + } catch (IllegalArgumentException e) {
72 + log.warn("Bad format for MAC address in config: {}",
56 entry.getMacAddress()); 73 entry.getMacAddress());
74 + }
75 + }
76 +
77 + PortAddresses addresses = new PortAddresses(cp,
78 + ipAddresses, macAddress);
57 79
58 hostAdminService.bindAddressesToPort(addresses); 80 hostAdminService.bindAddressesToPort(addresses);
59 } 81 }
......
...@@ -38,6 +38,8 @@ import org.slf4j.Logger; ...@@ -38,6 +38,8 @@ import org.slf4j.Logger;
38 @Component(immediate = true) 38 @Component(immediate = true)
39 public class ReactiveForwarding { 39 public class ReactiveForwarding {
40 40
41 + private static final int TIMEOUT = 10;
42 +
41 private final Logger log = getLogger(getClass()); 43 private final Logger log = getLogger(getClass());
42 44
43 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 45 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -192,7 +194,7 @@ public class ReactiveForwarding { ...@@ -192,7 +194,7 @@ public class ReactiveForwarding {
192 treat.setOutput(portNumber); 194 treat.setOutput(portNumber);
193 195
194 FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(), 196 FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(),
195 - builder.build(), treat.build(), 0, appId); 197 + builder.build(), treat.build(), 0, appId, TIMEOUT);
196 198
197 flowRuleService.applyFlowRules(f); 199 flowRuleService.applyFlowRules(f);
198 } 200 }
......
...@@ -27,11 +27,12 @@ public class DefaultFlowRule implements FlowRule { ...@@ -27,11 +27,12 @@ public class DefaultFlowRule implements FlowRule {
27 27
28 private final ApplicationId appId; 28 private final ApplicationId appId;
29 29
30 - private boolean expired; 30 + private final int timeout;
31 31
32 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, 32 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
33 TrafficTreatment treatment, int priority, FlowRuleState state, 33 TrafficTreatment treatment, int priority, FlowRuleState state,
34 - long life, long packets, long bytes, long flowId, boolean expired) { 34 + long life, long packets, long bytes, long flowId, boolean expired,
35 + int timeout) {
35 this.deviceId = deviceId; 36 this.deviceId = deviceId;
36 this.priority = priority; 37 this.priority = priority;
37 this.selector = selector; 38 this.selector = selector;
...@@ -39,26 +40,30 @@ public class DefaultFlowRule implements FlowRule { ...@@ -39,26 +40,30 @@ public class DefaultFlowRule implements FlowRule {
39 this.state = state; 40 this.state = state;
40 this.appId = ApplicationId.valueOf((int) (flowId >> 32)); 41 this.appId = ApplicationId.valueOf((int) (flowId >> 32));
41 this.id = FlowId.valueOf(flowId); 42 this.id = FlowId.valueOf(flowId);
42 - this.expired = expired;
43 this.life = life; 43 this.life = life;
44 this.packets = packets; 44 this.packets = packets;
45 this.bytes = bytes; 45 this.bytes = bytes;
46 this.created = System.currentTimeMillis(); 46 this.created = System.currentTimeMillis();
47 + this.timeout = timeout;
47 } 48 }
48 49
49 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, 50 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
50 - TrafficTreatment treatement, int priority, ApplicationId appId) { 51 + TrafficTreatment treatement, int priority, ApplicationId appId,
51 - this(deviceId, selector, treatement, priority, FlowRuleState.CREATED, appId); 52 + int timeout) {
53 + this(deviceId, selector, treatement, priority,
54 + FlowRuleState.CREATED, appId, timeout);
52 } 55 }
53 56
54 public DefaultFlowRule(FlowRule rule, FlowRuleState state) { 57 public DefaultFlowRule(FlowRule rule, FlowRuleState state) {
55 this(rule.deviceId(), rule.selector(), rule.treatment(), 58 this(rule.deviceId(), rule.selector(), rule.treatment(),
56 - rule.priority(), state, rule.id(), rule.appId()); 59 + rule.priority(), state, rule.id(), rule.appId(),
60 + rule.timeout());
57 } 61 }
58 62
59 private DefaultFlowRule(DeviceId deviceId, 63 private DefaultFlowRule(DeviceId deviceId,
60 TrafficSelector selector, TrafficTreatment treatment, 64 TrafficSelector selector, TrafficTreatment treatment,
61 - int priority, FlowRuleState state, ApplicationId appId) { 65 + int priority, FlowRuleState state, ApplicationId appId,
66 + int timeout) {
62 this.deviceId = deviceId; 67 this.deviceId = deviceId;
63 this.priority = priority; 68 this.priority = priority;
64 this.selector = selector; 69 this.selector = selector;
...@@ -69,13 +74,16 @@ public class DefaultFlowRule implements FlowRule { ...@@ -69,13 +74,16 @@ public class DefaultFlowRule implements FlowRule {
69 this.bytes = 0; 74 this.bytes = 0;
70 this.appId = appId; 75 this.appId = appId;
71 76
77 + this.timeout = timeout;
78 +
72 this.id = FlowId.valueOf((((long) appId().id()) << 32) | (this.hash() & 0xffffffffL)); 79 this.id = FlowId.valueOf((((long) appId().id()) << 32) | (this.hash() & 0xffffffffL));
73 this.created = System.currentTimeMillis(); 80 this.created = System.currentTimeMillis();
74 } 81 }
75 82
76 private DefaultFlowRule(DeviceId deviceId, 83 private DefaultFlowRule(DeviceId deviceId,
77 TrafficSelector selector, TrafficTreatment treatment, 84 TrafficSelector selector, TrafficTreatment treatment,
78 - int priority, FlowRuleState state, FlowId flowId, ApplicationId appId) { 85 + int priority, FlowRuleState state, FlowId flowId, ApplicationId appId,
86 + int timeout) {
79 this.deviceId = deviceId; 87 this.deviceId = deviceId;
80 this.priority = priority; 88 this.priority = priority;
81 this.selector = selector; 89 this.selector = selector;
...@@ -86,6 +94,7 @@ public class DefaultFlowRule implements FlowRule { ...@@ -86,6 +94,7 @@ public class DefaultFlowRule implements FlowRule {
86 this.bytes = 0; 94 this.bytes = 0;
87 this.appId = appId; 95 this.appId = appId;
88 this.id = flowId; 96 this.id = flowId;
97 + this.timeout = timeout;
89 this.created = System.currentTimeMillis(); 98 this.created = System.currentTimeMillis();
90 } 99 }
91 100
...@@ -149,7 +158,7 @@ public class DefaultFlowRule implements FlowRule { ...@@ -149,7 +158,7 @@ public class DefaultFlowRule implements FlowRule {
149 * @see java.lang.Object#equals(java.lang.Object) 158 * @see java.lang.Object#equals(java.lang.Object)
150 */ 159 */
151 public int hashCode() { 160 public int hashCode() {
152 - return Objects.hash(deviceId, id); 161 + return Objects.hash(deviceId, selector, priority);
153 } 162 }
154 163
155 public int hash() { 164 public int hash() {
...@@ -170,7 +179,10 @@ public class DefaultFlowRule implements FlowRule { ...@@ -170,7 +179,10 @@ public class DefaultFlowRule implements FlowRule {
170 if (obj instanceof DefaultFlowRule) { 179 if (obj instanceof DefaultFlowRule) {
171 DefaultFlowRule that = (DefaultFlowRule) obj; 180 DefaultFlowRule that = (DefaultFlowRule) obj;
172 return Objects.equals(deviceId, that.deviceId) && 181 return Objects.equals(deviceId, that.deviceId) &&
173 - Objects.equals(id, that.id); 182 + //Objects.equals(id, that.id) &&
183 + Objects.equals(priority, that.priority) &&
184 + Objects.equals(selector, that.selector);
185 +
174 } 186 }
175 return false; 187 return false;
176 } 188 }
...@@ -181,16 +193,16 @@ public class DefaultFlowRule implements FlowRule { ...@@ -181,16 +193,16 @@ public class DefaultFlowRule implements FlowRule {
181 .add("id", id) 193 .add("id", id)
182 .add("deviceId", deviceId) 194 .add("deviceId", deviceId)
183 .add("priority", priority) 195 .add("priority", priority)
184 - .add("selector", selector) 196 + .add("selector", selector.criteria())
185 - .add("treatment", treatment) 197 + .add("treatment", treatment == null ? "N/A" : treatment.instructions())
186 .add("created", created) 198 .add("created", created)
187 .add("state", state) 199 .add("state", state)
188 .toString(); 200 .toString();
189 } 201 }
190 202
191 @Override 203 @Override
192 - public boolean expired() { 204 + public int timeout() {
193 - return expired; 205 + return timeout > MAX_TIMEOUT ? MAX_TIMEOUT : this.timeout;
194 } 206 }
195 207
196 } 208 }
......
...@@ -3,8 +3,9 @@ package org.onlab.onos.net.flow; ...@@ -3,8 +3,9 @@ package org.onlab.onos.net.flow;
3 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
4 4
5 import java.util.Collections; 5 import java.util.Collections;
6 -import java.util.LinkedList; 6 +import java.util.HashSet;
7 -import java.util.List; 7 +import java.util.Objects;
8 +import java.util.Set;
8 9
9 import org.onlab.onos.net.PortNumber; 10 import org.onlab.onos.net.PortNumber;
10 import org.onlab.onos.net.flow.criteria.Criteria; 11 import org.onlab.onos.net.flow.criteria.Criteria;
...@@ -16,22 +17,42 @@ import org.slf4j.Logger; ...@@ -16,22 +17,42 @@ import org.slf4j.Logger;
16 17
17 public final class DefaultTrafficSelector implements TrafficSelector { 18 public final class DefaultTrafficSelector implements TrafficSelector {
18 19
19 - private final List<Criterion> selector; 20 + private final Set<Criterion> selector;
20 21
21 - private DefaultTrafficSelector(List<Criterion> selector) { 22 + private DefaultTrafficSelector(Set<Criterion> selector) {
22 - this.selector = Collections.unmodifiableList(selector); 23 + this.selector = Collections.unmodifiableSet(selector);
23 } 24 }
24 25
25 @Override 26 @Override
26 - public List<Criterion> criteria() { 27 + public Set<Criterion> criteria() {
27 return selector; 28 return selector;
28 } 29 }
29 30
31 + @Override
32 + public int hashCode() {
33 + return Objects.hash(selector);
34 + }
35 +
36 + @Override
37 + public boolean equals(Object obj) {
38 + if (this == obj) {
39 + return true;
40 + }
41 + if (obj instanceof DefaultTrafficSelector) {
42 + DefaultTrafficSelector that = (DefaultTrafficSelector) obj;
43 + return Objects.equals(selector, that.selector);
44 +
45 + }
46 + return false;
47 + }
48 +
49 +
50 +
30 public static class Builder implements TrafficSelector.Builder { 51 public static class Builder implements TrafficSelector.Builder {
31 52
32 private final Logger log = getLogger(getClass()); 53 private final Logger log = getLogger(getClass());
33 54
34 - private final List<Criterion> selector = new LinkedList<>(); 55 + private final Set<Criterion> selector = new HashSet<>();
35 56
36 @Override 57 @Override
37 public Builder add(Criterion criterion) { 58 public Builder add(Criterion criterion) {
...@@ -39,38 +60,47 @@ public final class DefaultTrafficSelector implements TrafficSelector { ...@@ -39,38 +60,47 @@ public final class DefaultTrafficSelector implements TrafficSelector {
39 return this; 60 return this;
40 } 61 }
41 62
63 + @Override
42 public Builder matchInport(PortNumber port) { 64 public Builder matchInport(PortNumber port) {
43 return add(Criteria.matchInPort(port)); 65 return add(Criteria.matchInPort(port));
44 } 66 }
45 67
68 + @Override
46 public Builder matchEthSrc(MacAddress addr) { 69 public Builder matchEthSrc(MacAddress addr) {
47 return add(Criteria.matchEthSrc(addr)); 70 return add(Criteria.matchEthSrc(addr));
48 } 71 }
49 72
73 + @Override
50 public Builder matchEthDst(MacAddress addr) { 74 public Builder matchEthDst(MacAddress addr) {
51 return add(Criteria.matchEthDst(addr)); 75 return add(Criteria.matchEthDst(addr));
52 } 76 }
53 77
78 + @Override
54 public Builder matchEthType(short ethType) { 79 public Builder matchEthType(short ethType) {
55 return add(Criteria.matchEthType(ethType)); 80 return add(Criteria.matchEthType(ethType));
56 } 81 }
57 82
83 + @Override
58 public Builder matchVlanId(VlanId vlanId) { 84 public Builder matchVlanId(VlanId vlanId) {
59 return add(Criteria.matchVlanId(vlanId)); 85 return add(Criteria.matchVlanId(vlanId));
60 } 86 }
61 87
88 + @Override
62 public Builder matchVlanPcp(Byte vlanPcp) { 89 public Builder matchVlanPcp(Byte vlanPcp) {
63 return add(Criteria.matchVlanPcp(vlanPcp)); 90 return add(Criteria.matchVlanPcp(vlanPcp));
64 } 91 }
65 92
93 + @Override
66 public Builder matchIPProtocol(Byte proto) { 94 public Builder matchIPProtocol(Byte proto) {
67 return add(Criteria.matchIPProtocol(proto)); 95 return add(Criteria.matchIPProtocol(proto));
68 } 96 }
69 97
98 + @Override
70 public Builder matchIPSrc(IpPrefix ip) { 99 public Builder matchIPSrc(IpPrefix ip) {
71 return add(Criteria.matchIPSrc(ip)); 100 return add(Criteria.matchIPSrc(ip));
72 } 101 }
73 102
103 + @Override
74 public Builder matchIPDst(IpPrefix ip) { 104 public Builder matchIPDst(IpPrefix ip) {
75 return add(Criteria.matchIPDst(ip)); 105 return add(Criteria.matchIPDst(ip));
76 } 106 }
......
...@@ -9,6 +9,7 @@ import org.onlab.onos.net.DeviceId; ...@@ -9,6 +9,7 @@ import org.onlab.onos.net.DeviceId;
9 */ 9 */
10 public interface FlowRule { 10 public interface FlowRule {
11 11
12 + static final int MAX_TIMEOUT = 60;
12 13
13 public enum FlowRuleState { 14 public enum FlowRuleState {
14 /** 15 /**
...@@ -112,10 +113,9 @@ public interface FlowRule { ...@@ -112,10 +113,9 @@ public interface FlowRule {
112 long bytes(); 113 long bytes();
113 114
114 /** 115 /**
115 - * Indicates that this flow has expired at the device. 116 + * Returns the timeout for this flow requested by an application.
116 - * 117 + * @return integer value of the timeout
117 - * @return true if it has expired, false otherwise
118 */ 118 */
119 - boolean expired(); 119 + int timeout();
120 120
121 } 121 }
......
...@@ -8,6 +8,8 @@ import org.onlab.onos.net.provider.Provider; ...@@ -8,6 +8,8 @@ import org.onlab.onos.net.provider.Provider;
8 */ 8 */
9 public interface FlowRuleProvider extends Provider { 9 public interface FlowRuleProvider extends Provider {
10 10
11 + static final int POLL_INTERVAL = 5;
12 +
11 /** 13 /**
12 * Instructs the provider to apply the specified flow rules to their 14 * Instructs the provider to apply the specified flow rules to their
13 * respective devices. 15 * respective devices.
......
...@@ -17,27 +17,6 @@ public interface FlowRuleProviderService extends ProviderService<FlowRuleProvide ...@@ -17,27 +17,6 @@ public interface FlowRuleProviderService extends ProviderService<FlowRuleProvide
17 void flowRemoved(FlowRule flowRule); 17 void flowRemoved(FlowRule flowRule);
18 18
19 /** 19 /**
20 - * Signals that a flow rule is missing for some network traffic.
21 - *
22 - * @param flowRule information about traffic in need of flow rule(s)
23 - */
24 - void flowMissing(FlowRule flowRule);
25 -
26 - /**
27 - * Signals that a flow rule is on the switch but not in the store.
28 - *
29 - * @param flowRule the extra flow rule
30 - */
31 - void extraneousFlow(FlowRule flowRule);
32 -
33 - /**
34 - * Signals that a flow rule was indeed added.
35 - *
36 - * @param flowRule the added flow rule
37 - */
38 - void flowAdded(FlowRule flowRule);
39 -
40 - /**
41 * Pushes the collection of flow entries currently applied on the given 20 * Pushes the collection of flow entries currently applied on the given
42 * device. 21 * device.
43 * 22 *
......
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 -import java.util.List; 3 +import java.util.Set;
4 4
5 import org.onlab.onos.net.PortNumber; 5 import org.onlab.onos.net.PortNumber;
6 import org.onlab.onos.net.flow.criteria.Criterion; 6 import org.onlab.onos.net.flow.criteria.Criterion;
...@@ -18,7 +18,7 @@ public interface TrafficSelector { ...@@ -18,7 +18,7 @@ public interface TrafficSelector {
18 * 18 *
19 * @return list of criteria 19 * @return list of criteria
20 */ 20 */
21 - List<Criterion> criteria(); 21 + Set<Criterion> criteria();
22 22
23 /** 23 /**
24 * Builder of traffic selector entities. 24 * Builder of traffic selector entities.
......
...@@ -2,6 +2,8 @@ package org.onlab.onos.net.flow.criteria; ...@@ -2,6 +2,8 @@ package org.onlab.onos.net.flow.criteria;
2 2
3 import static com.google.common.base.MoreObjects.toStringHelper; 3 import static com.google.common.base.MoreObjects.toStringHelper;
4 4
5 +import java.util.Objects;
6 +
5 import org.onlab.onos.net.PortNumber; 7 import org.onlab.onos.net.PortNumber;
6 import org.onlab.onos.net.flow.criteria.Criterion.Type; 8 import org.onlab.onos.net.flow.criteria.Criterion.Type;
7 import org.onlab.packet.IpPrefix; 9 import org.onlab.packet.IpPrefix;
...@@ -137,6 +139,25 @@ public final class Criteria { ...@@ -137,6 +139,25 @@ public final class Criteria {
137 return toStringHelper(type().toString()) 139 return toStringHelper(type().toString())
138 .add("port", port).toString(); 140 .add("port", port).toString();
139 } 141 }
142 +
143 + @Override
144 + public int hashCode() {
145 + return Objects.hash(port);
146 + }
147 +
148 + @Override
149 + public boolean equals(Object obj) {
150 + if (this == obj) {
151 + return true;
152 + }
153 + if (obj instanceof PortCriterion) {
154 + PortCriterion that = (PortCriterion) obj;
155 + return Objects.equals(port, that.port);
156 +
157 + }
158 + return false;
159 + }
160 +
140 } 161 }
141 162
142 163
...@@ -164,6 +185,27 @@ public final class Criteria { ...@@ -164,6 +185,27 @@ public final class Criteria {
164 .add("mac", mac).toString(); 185 .add("mac", mac).toString();
165 } 186 }
166 187
188 + @Override
189 + public int hashCode() {
190 + return Objects.hash(mac, type);
191 + }
192 +
193 + @Override
194 + public boolean equals(Object obj) {
195 + if (this == obj) {
196 + return true;
197 + }
198 + if (obj instanceof EthCriterion) {
199 + EthCriterion that = (EthCriterion) obj;
200 + return Objects.equals(mac, that.mac) &&
201 + Objects.equals(type, that.type);
202 +
203 +
204 + }
205 + return false;
206 + }
207 +
208 +
167 } 209 }
168 210
169 public static final class EthTypeCriterion implements Criterion { 211 public static final class EthTypeCriterion implements Criterion {
...@@ -189,6 +231,25 @@ public final class Criteria { ...@@ -189,6 +231,25 @@ public final class Criteria {
189 .add("ethType", Long.toHexString(ethType)).toString(); 231 .add("ethType", Long.toHexString(ethType)).toString();
190 } 232 }
191 233
234 + @Override
235 + public int hashCode() {
236 + return Objects.hash(ethType);
237 + }
238 +
239 + @Override
240 + public boolean equals(Object obj) {
241 + if (this == obj) {
242 + return true;
243 + }
244 + if (obj instanceof EthTypeCriterion) {
245 + EthTypeCriterion that = (EthTypeCriterion) obj;
246 + return Objects.equals(ethType, that.ethType);
247 +
248 +
249 + }
250 + return false;
251 + }
252 +
192 } 253 }
193 254
194 255
...@@ -217,6 +278,26 @@ public final class Criteria { ...@@ -217,6 +278,26 @@ public final class Criteria {
217 .add("ip", ip).toString(); 278 .add("ip", ip).toString();
218 } 279 }
219 280
281 + @Override
282 + public int hashCode() {
283 + return Objects.hash(ip, type);
284 + }
285 +
286 + @Override
287 + public boolean equals(Object obj) {
288 + if (this == obj) {
289 + return true;
290 + }
291 + if (obj instanceof IPCriterion) {
292 + IPCriterion that = (IPCriterion) obj;
293 + return Objects.equals(ip, that.ip) &&
294 + Objects.equals(type, that.type);
295 +
296 +
297 + }
298 + return false;
299 + }
300 +
220 } 301 }
221 302
222 303
...@@ -243,6 +324,25 @@ public final class Criteria { ...@@ -243,6 +324,25 @@ public final class Criteria {
243 .add("protocol", Long.toHexString(proto)).toString(); 324 .add("protocol", Long.toHexString(proto)).toString();
244 } 325 }
245 326
327 + @Override
328 + public int hashCode() {
329 + return Objects.hash(proto);
330 + }
331 +
332 + @Override
333 + public boolean equals(Object obj) {
334 + if (this == obj) {
335 + return true;
336 + }
337 + if (obj instanceof IPProtocolCriterion) {
338 + IPProtocolCriterion that = (IPProtocolCriterion) obj;
339 + return Objects.equals(proto, that.proto);
340 +
341 +
342 + }
343 + return false;
344 + }
345 +
246 } 346 }
247 347
248 348
...@@ -269,6 +369,25 @@ public final class Criteria { ...@@ -269,6 +369,25 @@ public final class Criteria {
269 .add("pcp", Long.toHexString(vlanPcp)).toString(); 369 .add("pcp", Long.toHexString(vlanPcp)).toString();
270 } 370 }
271 371
372 + @Override
373 + public int hashCode() {
374 + return Objects.hash(vlanPcp);
375 + }
376 +
377 + @Override
378 + public boolean equals(Object obj) {
379 + if (this == obj) {
380 + return true;
381 + }
382 + if (obj instanceof VlanPcpCriterion) {
383 + VlanPcpCriterion that = (VlanPcpCriterion) obj;
384 + return Objects.equals(vlanPcp, that.vlanPcp);
385 +
386 +
387 + }
388 + return false;
389 + }
390 +
272 } 391 }
273 392
274 393
...@@ -296,6 +415,25 @@ public final class Criteria { ...@@ -296,6 +415,25 @@ public final class Criteria {
296 .add("id", vlanId).toString(); 415 .add("id", vlanId).toString();
297 } 416 }
298 417
418 + @Override
419 + public int hashCode() {
420 + return Objects.hash(vlanId);
421 + }
422 +
423 + @Override
424 + public boolean equals(Object obj) {
425 + if (this == obj) {
426 + return true;
427 + }
428 + if (obj instanceof VlanIdCriterion) {
429 + VlanIdCriterion that = (VlanIdCriterion) obj;
430 + return Objects.equals(vlanId, that.vlanId);
431 +
432 +
433 + }
434 + return false;
435 + }
436 +
299 } 437 }
300 438
301 439
......
...@@ -5,6 +5,9 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -5,6 +5,9 @@ import static org.slf4j.LoggerFactory.getLogger;
5 5
6 import java.util.Iterator; 6 import java.util.Iterator;
7 import java.util.List; 7 import java.util.List;
8 +import java.util.Map;
9 +import java.util.concurrent.ConcurrentHashMap;
10 +import java.util.concurrent.atomic.AtomicInteger;
8 11
9 import org.apache.felix.scr.annotations.Activate; 12 import org.apache.felix.scr.annotations.Activate;
10 import org.apache.felix.scr.annotations.Component; 13 import org.apache.felix.scr.annotations.Component;
...@@ -59,6 +62,8 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -59,6 +62,8 @@ implements FlowRuleService, FlowRuleProviderRegistry {
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected DeviceService deviceService; 63 protected DeviceService deviceService;
61 64
65 + private final Map<FlowRule, AtomicInteger> deadRounds = new ConcurrentHashMap<>();
66 +
62 @Activate 67 @Activate
63 public void activate() { 68 public void activate() {
64 store.setDelegate(delegate); 69 store.setDelegate(delegate);
...@@ -84,6 +89,7 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -84,6 +89,7 @@ implements FlowRuleService, FlowRuleProviderRegistry {
84 FlowRule f = flowRules[i]; 89 FlowRule f = flowRules[i];
85 final Device device = deviceService.getDevice(f.deviceId()); 90 final Device device = deviceService.getDevice(f.deviceId());
86 final FlowRuleProvider frp = getProvider(device.providerId()); 91 final FlowRuleProvider frp = getProvider(device.providerId());
92 + deadRounds.put(f, new AtomicInteger(0));
87 store.storeFlowRule(f); 93 store.storeFlowRule(f);
88 frp.applyFlowRule(f); 94 frp.applyFlowRule(f);
89 } 95 }
...@@ -98,6 +104,7 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -98,6 +104,7 @@ implements FlowRuleService, FlowRuleProviderRegistry {
98 f = flowRules[i]; 104 f = flowRules[i];
99 device = deviceService.getDevice(f.deviceId()); 105 device = deviceService.getDevice(f.deviceId());
100 frp = getProvider(device.providerId()); 106 frp = getProvider(device.providerId());
107 + deadRounds.remove(f);
101 store.deleteFlowRule(f); 108 store.deleteFlowRule(f);
102 frp.removeFlowRule(f); 109 frp.removeFlowRule(f);
103 } 110 }
...@@ -161,11 +168,7 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -161,11 +168,7 @@ implements FlowRuleService, FlowRuleProviderRegistry {
161 switch (stored.state()) { 168 switch (stored.state()) {
162 case ADDED: 169 case ADDED:
163 case PENDING_ADD: 170 case PENDING_ADD:
164 - if (flowRule.expired()) {
165 - event = store.removeFlowRule(flowRule);
166 - } else {
167 frp.applyFlowRule(stored); 171 frp.applyFlowRule(stored);
168 - }
169 break; 172 break;
170 case PENDING_REMOVE: 173 case PENDING_REMOVE:
171 case REMOVED: 174 case REMOVED:
...@@ -181,8 +184,8 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -181,8 +184,8 @@ implements FlowRuleService, FlowRuleProviderRegistry {
181 } 184 }
182 } 185 }
183 186
184 - @Override 187 +
185 - public void flowMissing(FlowRule flowRule) { 188 + private void flowMissing(FlowRule flowRule) {
186 checkNotNull(flowRule, FLOW_RULE_NULL); 189 checkNotNull(flowRule, FLOW_RULE_NULL);
187 checkValidity(); 190 checkValidity();
188 Device device = deviceService.getDevice(flowRule.deviceId()); 191 Device device = deviceService.getDevice(flowRule.deviceId());
...@@ -209,19 +212,22 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -209,19 +212,22 @@ implements FlowRuleService, FlowRuleProviderRegistry {
209 212
210 } 213 }
211 214
212 - @Override 215 +
213 - public void extraneousFlow(FlowRule flowRule) { 216 + private void extraneousFlow(FlowRule flowRule) {
214 checkNotNull(flowRule, FLOW_RULE_NULL); 217 checkNotNull(flowRule, FLOW_RULE_NULL);
215 checkValidity(); 218 checkValidity();
216 removeFlowRules(flowRule); 219 removeFlowRules(flowRule);
217 log.debug("Flow {} is on switch but not in store.", flowRule); 220 log.debug("Flow {} is on switch but not in store.", flowRule);
218 } 221 }
219 222
220 - @Override 223 +
221 - public void flowAdded(FlowRule flowRule) { 224 + private void flowAdded(FlowRule flowRule) {
222 checkNotNull(flowRule, FLOW_RULE_NULL); 225 checkNotNull(flowRule, FLOW_RULE_NULL);
223 checkValidity(); 226 checkValidity();
224 227
228 + if (deadRounds.containsKey(flowRule) &&
229 + checkRuleLiveness(flowRule, store.getFlowRule(flowRule))) {
230 +
225 FlowRuleEvent event = store.addOrUpdateFlowRule(flowRule); 231 FlowRuleEvent event = store.addOrUpdateFlowRule(flowRule);
226 if (event == null) { 232 if (event == null) {
227 log.debug("No flow store event generated."); 233 log.debug("No flow store event generated.");
...@@ -229,6 +235,21 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -229,6 +235,21 @@ implements FlowRuleService, FlowRuleProviderRegistry {
229 log.debug("Flow {} {}", flowRule, event.type()); 235 log.debug("Flow {} {}", flowRule, event.type());
230 post(event); 236 post(event);
231 } 237 }
238 + } else {
239 + removeFlowRules(flowRule);
240 + }
241 +
242 + }
243 +
244 + private boolean checkRuleLiveness(FlowRule swRule, FlowRule storedRule) {
245 + int timeout = storedRule.timeout();
246 + if (storedRule.packets() != swRule.packets()) {
247 + deadRounds.get(swRule).set(0);
248 + return true;
249 + }
250 +
251 + return (deadRounds.get(swRule).getAndIncrement() *
252 + FlowRuleProvider.POLL_INTERVAL) <= timeout;
232 253
233 } 254 }
234 255
......
1 package org.onlab.onos.net.host.impl; 1 package org.onlab.onos.net.host.impl;
2 2
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +import static org.slf4j.LoggerFactory.getLogger;
5 +
6 +import java.util.Set;
7 +
3 import org.apache.felix.scr.annotations.Activate; 8 import org.apache.felix.scr.annotations.Activate;
4 import org.apache.felix.scr.annotations.Component; 9 import org.apache.felix.scr.annotations.Component;
5 import org.apache.felix.scr.annotations.Deactivate; 10 import org.apache.felix.scr.annotations.Deactivate;
...@@ -12,6 +17,7 @@ import org.onlab.onos.net.ConnectPoint; ...@@ -12,6 +17,7 @@ import org.onlab.onos.net.ConnectPoint;
12 import org.onlab.onos.net.DeviceId; 17 import org.onlab.onos.net.DeviceId;
13 import org.onlab.onos.net.Host; 18 import org.onlab.onos.net.Host;
14 import org.onlab.onos.net.HostId; 19 import org.onlab.onos.net.HostId;
20 +import org.onlab.onos.net.device.DeviceService;
15 import org.onlab.onos.net.host.HostAdminService; 21 import org.onlab.onos.net.host.HostAdminService;
16 import org.onlab.onos.net.host.HostDescription; 22 import org.onlab.onos.net.host.HostDescription;
17 import org.onlab.onos.net.host.HostEvent; 23 import org.onlab.onos.net.host.HostEvent;
...@@ -23,6 +29,7 @@ import org.onlab.onos.net.host.HostService; ...@@ -23,6 +29,7 @@ import org.onlab.onos.net.host.HostService;
23 import org.onlab.onos.net.host.HostStore; 29 import org.onlab.onos.net.host.HostStore;
24 import org.onlab.onos.net.host.HostStoreDelegate; 30 import org.onlab.onos.net.host.HostStoreDelegate;
25 import org.onlab.onos.net.host.PortAddresses; 31 import org.onlab.onos.net.host.PortAddresses;
32 +import org.onlab.onos.net.packet.PacketService;
26 import org.onlab.onos.net.provider.AbstractProviderRegistry; 33 import org.onlab.onos.net.provider.AbstractProviderRegistry;
27 import org.onlab.onos.net.provider.AbstractProviderService; 34 import org.onlab.onos.net.provider.AbstractProviderService;
28 import org.onlab.packet.IpAddress; 35 import org.onlab.packet.IpAddress;
...@@ -31,11 +38,6 @@ import org.onlab.packet.MacAddress; ...@@ -31,11 +38,6 @@ import org.onlab.packet.MacAddress;
31 import org.onlab.packet.VlanId; 38 import org.onlab.packet.VlanId;
32 import org.slf4j.Logger; 39 import org.slf4j.Logger;
33 40
34 -import java.util.Set;
35 -
36 -import static com.google.common.base.Preconditions.checkNotNull;
37 -import static org.slf4j.LoggerFactory.getLogger;
38 -
39 /** 41 /**
40 * Provides basic implementation of the host SB &amp; NB APIs. 42 * Provides basic implementation of the host SB &amp; NB APIs.
41 */ 43 */
...@@ -59,12 +61,22 @@ public class HostManager ...@@ -59,12 +61,22 @@ public class HostManager
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected EventDeliveryService eventDispatcher; 62 protected EventDeliveryService eventDispatcher;
61 63
64 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 + protected DeviceService deviceService;
66 +
67 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 + protected PacketService packetService;
69 +
70 + private HostMonitor monitor;
62 71
63 @Activate 72 @Activate
64 public void activate() { 73 public void activate() {
74 + log.info("Started");
65 store.setDelegate(delegate); 75 store.setDelegate(delegate);
66 eventDispatcher.addSink(HostEvent.class, listenerRegistry); 76 eventDispatcher.addSink(HostEvent.class, listenerRegistry);
67 - log.info("Started"); 77 +
78 + monitor = new HostMonitor(deviceService, packetService, this);
79 +
68 } 80 }
69 81
70 @Deactivate 82 @Deactivate
...@@ -76,6 +88,8 @@ public class HostManager ...@@ -76,6 +88,8 @@ public class HostManager
76 88
77 @Override 89 @Override
78 protected HostProviderService createProviderService(HostProvider provider) { 90 protected HostProviderService createProviderService(HostProvider provider) {
91 + monitor.registerHostProvider(provider);
92 +
79 return new InternalHostProviderService(provider); 93 return new InternalHostProviderService(provider);
80 } 94 }
81 95
...@@ -126,12 +140,12 @@ public class HostManager ...@@ -126,12 +140,12 @@ public class HostManager
126 140
127 @Override 141 @Override
128 public void startMonitoringIp(IpAddress ip) { 142 public void startMonitoringIp(IpAddress ip) {
129 - // TODO pass through to HostMonitor 143 + monitor.addMonitoringFor(ip);
130 } 144 }
131 145
132 @Override 146 @Override
133 public void stopMonitoringIp(IpAddress ip) { 147 public void stopMonitoringIp(IpAddress ip) {
134 - // TODO pass through to HostMonitor 148 + monitor.stopMonitoring(ip);
135 } 149 }
136 150
137 @Override 151 @Override
......
...@@ -2,10 +2,11 @@ package org.onlab.onos.net.host.impl; ...@@ -2,10 +2,11 @@ package org.onlab.onos.net.host.impl;
2 2
3 import java.nio.ByteBuffer; 3 import java.nio.ByteBuffer;
4 import java.util.ArrayList; 4 import java.util.ArrayList;
5 -import java.util.Collections;
6 import java.util.HashSet; 5 import java.util.HashSet;
7 import java.util.List; 6 import java.util.List;
7 +import java.util.Map;
8 import java.util.Set; 8 import java.util.Set;
9 +import java.util.concurrent.ConcurrentHashMap;
9 import java.util.concurrent.TimeUnit; 10 import java.util.concurrent.TimeUnit;
10 11
11 import org.jboss.netty.util.Timeout; 12 import org.jboss.netty.util.Timeout;
...@@ -21,19 +22,19 @@ import org.onlab.onos.net.flow.TrafficTreatment; ...@@ -21,19 +22,19 @@ import org.onlab.onos.net.flow.TrafficTreatment;
21 import org.onlab.onos.net.flow.instructions.Instruction; 22 import org.onlab.onos.net.flow.instructions.Instruction;
22 import org.onlab.onos.net.flow.instructions.Instructions; 23 import org.onlab.onos.net.flow.instructions.Instructions;
23 import org.onlab.onos.net.host.HostProvider; 24 import org.onlab.onos.net.host.HostProvider;
24 -import org.onlab.onos.net.host.HostService;
25 -import org.onlab.onos.net.host.HostStore;
26 import org.onlab.onos.net.host.PortAddresses; 25 import org.onlab.onos.net.host.PortAddresses;
27 import org.onlab.onos.net.packet.DefaultOutboundPacket; 26 import org.onlab.onos.net.packet.DefaultOutboundPacket;
28 import org.onlab.onos.net.packet.OutboundPacket; 27 import org.onlab.onos.net.packet.OutboundPacket;
29 import org.onlab.onos.net.packet.PacketService; 28 import org.onlab.onos.net.packet.PacketService;
30 -import org.onlab.onos.net.topology.TopologyService; 29 +import org.onlab.onos.net.provider.ProviderId;
31 import org.onlab.packet.ARP; 30 import org.onlab.packet.ARP;
32 import org.onlab.packet.Ethernet; 31 import org.onlab.packet.Ethernet;
33 import org.onlab.packet.IpAddress; 32 import org.onlab.packet.IpAddress;
34 import org.onlab.packet.IpPrefix; 33 import org.onlab.packet.IpPrefix;
35 import org.onlab.packet.MacAddress; 34 import org.onlab.packet.MacAddress;
36 import org.onlab.util.Timer; 35 import org.onlab.util.Timer;
36 +import org.slf4j.Logger;
37 +import org.slf4j.LoggerFactory;
37 38
38 /** 39 /**
39 * Monitors hosts on the dataplane to detect changes in host data. 40 * Monitors hosts on the dataplane to detect changes in host data.
...@@ -43,9 +44,7 @@ import org.onlab.util.Timer; ...@@ -43,9 +44,7 @@ import org.onlab.util.Timer;
43 * probe for hosts that have not yet been detected (specified by IP address). 44 * probe for hosts that have not yet been detected (specified by IP address).
44 */ 45 */
45 public class HostMonitor implements TimerTask { 46 public class HostMonitor implements TimerTask {
46 - 47 + private static final Logger log = LoggerFactory.getLogger(HostMonitor.class);
47 - private static final byte[] DEFAULT_MAC_ADDRESS =
48 - MacAddress.valueOf("00:00:00:00:00:01").getAddress();
49 48
50 private static final byte[] ZERO_MAC_ADDRESS = 49 private static final byte[] ZERO_MAC_ADDRESS =
51 MacAddress.valueOf("00:00:00:00:00:00").getAddress(); 50 MacAddress.valueOf("00:00:00:00:00:00").getAddress();
...@@ -54,59 +53,77 @@ public class HostMonitor implements TimerTask { ...@@ -54,59 +53,77 @@ public class HostMonitor implements TimerTask {
54 private static final byte[] BROADCAST_MAC = 53 private static final byte[] BROADCAST_MAC =
55 MacAddress.valueOf("ff:ff:ff:ff:ff:ff").getAddress(); 54 MacAddress.valueOf("ff:ff:ff:ff:ff:ff").getAddress();
56 55
57 - private final HostService hostService; 56 + private DeviceService deviceService;
58 - private final TopologyService topologyService; 57 + private PacketService packetService;
59 - private final DeviceService deviceService; 58 + private HostManager hostManager;
60 - private final HostProvider hostProvider;
61 - private final PacketService packetService;
62 - private final HostStore hostStore;
63 59
64 private final Set<IpAddress> monitoredAddresses; 60 private final Set<IpAddress> monitoredAddresses;
65 61
62 + private final Map<ProviderId, HostProvider> hostProviders;
63 +
66 private final long probeRate; 64 private final long probeRate;
67 65
68 private final Timeout timeout; 66 private final Timeout timeout;
69 67
70 - public HostMonitor(HostService hostService, TopologyService topologyService, 68 + public HostMonitor(
71 DeviceService deviceService, 69 DeviceService deviceService,
72 - HostProvider hostProvider, PacketService packetService, 70 + PacketService packetService,
73 - HostStore hostStore) { 71 + HostManager hostService) {
74 - this.hostService = hostService; 72 +
75 - this.topologyService = topologyService;
76 this.deviceService = deviceService; 73 this.deviceService = deviceService;
77 - this.hostProvider = hostProvider;
78 this.packetService = packetService; 74 this.packetService = packetService;
79 - this.hostStore = hostStore; 75 + this.hostManager = hostService;
80 76
81 monitoredAddresses = new HashSet<>(); 77 monitoredAddresses = new HashSet<>();
78 + hostProviders = new ConcurrentHashMap<>();
82 79
83 probeRate = 30000; // milliseconds 80 probeRate = 30000; // milliseconds
84 81
85 timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS); 82 timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS);
83 +
84 + addDefaultAddresses();
86 } 85 }
87 86
88 - public void addMonitoringFor(IpAddress ip) { 87 + private void addDefaultAddresses() {
88 + //monitoredAddresses.add(IpAddress.valueOf("10.0.0.1"));
89 + }
90 +
91 + void addMonitoringFor(IpAddress ip) {
89 monitoredAddresses.add(ip); 92 monitoredAddresses.add(ip);
90 } 93 }
91 94
92 - public void stopMonitoring(IpAddress ip) { 95 + void stopMonitoring(IpAddress ip) {
93 monitoredAddresses.remove(ip); 96 monitoredAddresses.remove(ip);
94 } 97 }
95 98
96 - public void shutdown() { 99 + void shutdown() {
97 timeout.cancel(); 100 timeout.cancel();
98 } 101 }
99 102
103 + void registerHostProvider(HostProvider provider) {
104 + hostProviders.put(provider.id(), provider);
105 + }
106 +
107 + void unregisterHostProvider(HostProvider provider) {
108 + // TODO find out how to call this
109 + }
110 +
100 @Override 111 @Override
101 public void run(Timeout timeout) throws Exception { 112 public void run(Timeout timeout) throws Exception {
102 for (IpAddress ip : monitoredAddresses) { 113 for (IpAddress ip : monitoredAddresses) {
103 - Set<Host> hosts = Collections.emptySet(); //TODO hostService.getHostsByIp(ip); 114 + // TODO have to convert right now because the HostService API uses IpPrefix
115 + IpPrefix prefix = IpPrefix.valueOf(ip.toOctets());
116 +
117 + Set<Host> hosts = hostManager.getHostsByIp(prefix);
104 118
105 if (hosts.isEmpty()) { 119 if (hosts.isEmpty()) {
106 sendArpRequest(ip); 120 sendArpRequest(ip);
107 } else { 121 } else {
108 for (Host host : hosts) { 122 for (Host host : hosts) {
109 - hostProvider.triggerProbe(host); 123 + HostProvider provider = hostProviders.get(host.providerId());
124 + if (provider != null) {
125 + provider.triggerProbe(host);
126 + }
110 } 127 }
111 } 128 }
112 } 129 }
...@@ -120,29 +137,26 @@ public class HostMonitor implements TimerTask { ...@@ -120,29 +137,26 @@ public class HostMonitor implements TimerTask {
120 * @param targetIp IP address to ARP for 137 * @param targetIp IP address to ARP for
121 */ 138 */
122 private void sendArpRequest(IpAddress targetIp) { 139 private void sendArpRequest(IpAddress targetIp) {
123 -
124 // Find ports with an IP address in the target's subnet and sent ARP 140 // Find ports with an IP address in the target's subnet and sent ARP
125 // probes out those ports. 141 // probes out those ports.
126 for (Device device : deviceService.getDevices()) { 142 for (Device device : deviceService.getDevices()) {
127 for (Port port : deviceService.getPorts(device.id())) { 143 for (Port port : deviceService.getPorts(device.id())) {
128 ConnectPoint cp = new ConnectPoint(device.id(), port.number()); 144 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
129 - PortAddresses addresses = hostStore.getAddressBindingsForPort(cp); 145 + PortAddresses addresses = hostManager.getAddressBindingsForPort(cp);
130 146
131 - /*for (IpPrefix prefix : addresses.ips()) { 147 + for (IpPrefix prefix : addresses.ips()) {
132 if (prefix.contains(targetIp)) { 148 if (prefix.contains(targetIp)) {
133 - sendProbe(device.id(), port, addresses, targetIp); 149 + sendProbe(device.id(), port, targetIp,
150 + prefix.toIpAddress(), addresses.mac());
151 + }
134 } 152 }
135 - }*/
136 } 153 }
137 } 154 }
138 -
139 - // TODO case where no address was found.
140 - // Broadcast out internal edge ports?
141 } 155 }
142 156
143 - private void sendProbe(DeviceId deviceId, Port port, PortAddresses portAddresses, 157 + private void sendProbe(DeviceId deviceId, Port port, IpAddress targetIp,
144 - IpAddress targetIp) { 158 + IpAddress sourceIp, MacAddress sourceMac) {
145 - Ethernet arpPacket = createArpFor(targetIp, portAddresses); 159 + Ethernet arpPacket = buildArpRequest(targetIp, sourceIp, sourceMac);
146 160
147 List<Instruction> instructions = new ArrayList<>(); 161 List<Instruction> instructions = new ArrayList<>();
148 instructions.add(Instructions.createOutput(port.number())); 162 instructions.add(Instructions.createOutput(port.number()));
...@@ -158,30 +172,25 @@ public class HostMonitor implements TimerTask { ...@@ -158,30 +172,25 @@ public class HostMonitor implements TimerTask {
158 packetService.emit(outboundPacket); 172 packetService.emit(outboundPacket);
159 } 173 }
160 174
161 - private Ethernet createArpFor(IpAddress targetIp, PortAddresses portAddresses) { 175 + private Ethernet buildArpRequest(IpAddress targetIp, IpAddress sourceIp,
176 + MacAddress sourceMac) {
162 177
163 ARP arp = new ARP(); 178 ARP arp = new ARP();
164 arp.setHardwareType(ARP.HW_TYPE_ETHERNET) 179 arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
165 .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH) 180 .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
166 .setProtocolType(ARP.PROTO_TYPE_IP) 181 .setProtocolType(ARP.PROTO_TYPE_IP)
167 - .setProtocolAddressLength((byte) IpPrefix.INET_LEN); 182 + .setProtocolAddressLength((byte) IpPrefix.INET_LEN)
168 - 183 + .setOpCode(ARP.OP_REQUEST);
169 - byte[] sourceMacAddress;
170 - if (portAddresses.mac() == null) {
171 - sourceMacAddress = DEFAULT_MAC_ADDRESS;
172 - } else {
173 - sourceMacAddress = portAddresses.mac().getAddress();
174 - }
175 184
176 - arp.setSenderHardwareAddress(sourceMacAddress) 185 + arp.setSenderHardwareAddress(sourceMac.getAddress())
177 - //TODO .setSenderProtocolAddress(portAddresses.ips().toOctets()) 186 + .setSenderProtocolAddress(sourceIp.toOctets())
178 .setTargetHardwareAddress(ZERO_MAC_ADDRESS) 187 .setTargetHardwareAddress(ZERO_MAC_ADDRESS)
179 .setTargetProtocolAddress(targetIp.toOctets()); 188 .setTargetProtocolAddress(targetIp.toOctets());
180 189
181 Ethernet ethernet = new Ethernet(); 190 Ethernet ethernet = new Ethernet();
182 ethernet.setEtherType(Ethernet.TYPE_ARP) 191 ethernet.setEtherType(Ethernet.TYPE_ARP)
183 .setDestinationMACAddress(BROADCAST_MAC) 192 .setDestinationMACAddress(BROADCAST_MAC)
184 - .setSourceMACAddress(sourceMacAddress) 193 + .setSourceMACAddress(sourceMac.getAddress())
185 .setPayload(arp); 194 .setPayload(arp);
186 195
187 return ethernet; 196 return ethernet;
......
...@@ -9,7 +9,9 @@ import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; ...@@ -9,7 +9,9 @@ import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
9 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED; 9 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
10 10
11 import java.util.ArrayList; 11 import java.util.ArrayList;
12 +import java.util.Collections;
12 import java.util.List; 13 import java.util.List;
14 +import java.util.Set;
13 15
14 import org.junit.After; 16 import org.junit.After;
15 import org.junit.Before; 17 import org.junit.Before;
...@@ -42,6 +44,7 @@ import org.onlab.onos.net.provider.AbstractProvider; ...@@ -42,6 +44,7 @@ import org.onlab.onos.net.provider.AbstractProvider;
42 import org.onlab.onos.net.provider.ProviderId; 44 import org.onlab.onos.net.provider.ProviderId;
43 import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore; 45 import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
44 46
47 +import com.google.common.collect.ImmutableList;
45 import com.google.common.collect.Lists; 48 import com.google.common.collect.Lists;
46 import com.google.common.collect.Sets; 49 import com.google.common.collect.Sets;
47 50
...@@ -52,6 +55,7 @@ public class FlowRuleManagerTest { ...@@ -52,6 +55,7 @@ public class FlowRuleManagerTest {
52 55
53 private static final ProviderId PID = new ProviderId("of", "foo"); 56 private static final ProviderId PID = new ProviderId("of", "foo");
54 private static final DeviceId DID = DeviceId.deviceId("of:001"); 57 private static final DeviceId DID = DeviceId.deviceId("of:001");
58 + private static final int TIMEOUT = 10;
55 private static final Device DEV = new DefaultDevice( 59 private static final Device DEV = new DefaultDevice(
56 PID, DID, Type.SWITCH, "", "", "", ""); 60 PID, DID, Type.SWITCH, "", "", "", "");
57 61
...@@ -96,7 +100,7 @@ public class FlowRuleManagerTest { ...@@ -96,7 +100,7 @@ public class FlowRuleManagerTest {
96 private FlowRule flowRule(int tsval, int trval) { 100 private FlowRule flowRule(int tsval, int trval) {
97 TestSelector ts = new TestSelector(tsval); 101 TestSelector ts = new TestSelector(tsval);
98 TestTreatment tr = new TestTreatment(trval); 102 TestTreatment tr = new TestTreatment(trval);
99 - return new DefaultFlowRule(DID, ts, tr, 0, appId); 103 + return new DefaultFlowRule(DID, ts, tr, 0, appId, TIMEOUT);
100 } 104 }
101 105
102 private FlowRule flowRule(FlowRule rule, FlowRuleState state) { 106 private FlowRule flowRule(FlowRule rule, FlowRuleState state) {
...@@ -105,7 +109,8 @@ public class FlowRuleManagerTest { ...@@ -105,7 +109,8 @@ public class FlowRuleManagerTest {
105 109
106 private FlowRule addFlowRule(int hval) { 110 private FlowRule addFlowRule(int hval) {
107 FlowRule rule = flowRule(hval, hval); 111 FlowRule rule = flowRule(hval, hval);
108 - providerService.flowAdded(rule); 112 + service.applyFlowRules(rule);
113 +
109 assertNotNull("rule should be found", service.getFlowEntries(DID)); 114 assertNotNull("rule should be found", service.getFlowEntries(DID));
110 return rule; 115 return rule;
111 } 116 }
...@@ -135,13 +140,18 @@ public class FlowRuleManagerTest { ...@@ -135,13 +140,18 @@ public class FlowRuleManagerTest {
135 public void getFlowEntries() { 140 public void getFlowEntries() {
136 assertTrue("store should be empty", 141 assertTrue("store should be empty",
137 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty()); 142 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
138 - addFlowRule(1); 143 + FlowRule f1 = addFlowRule(1);
139 - addFlowRule(2); 144 + FlowRule f2 = addFlowRule(2);
145 +
140 assertEquals("2 rules should exist", 2, flowCount()); 146 assertEquals("2 rules should exist", 2, flowCount());
147 +
148 + providerService.pushFlowMetrics(DID, ImmutableList.of(f1, f2));
141 validateEvents(RULE_ADDED, RULE_ADDED); 149 validateEvents(RULE_ADDED, RULE_ADDED);
142 150
143 addFlowRule(1); 151 addFlowRule(1);
144 assertEquals("should still be 2 rules", 2, flowCount()); 152 assertEquals("should still be 2 rules", 2, flowCount());
153 +
154 + providerService.pushFlowMetrics(DID, ImmutableList.of(f1));
145 validateEvents(RULE_UPDATED); 155 validateEvents(RULE_UPDATED);
146 } 156 }
147 157
...@@ -179,8 +189,10 @@ public class FlowRuleManagerTest { ...@@ -179,8 +189,10 @@ public class FlowRuleManagerTest {
179 public void removeFlowRules() { 189 public void removeFlowRules() {
180 FlowRule f1 = addFlowRule(1); 190 FlowRule f1 = addFlowRule(1);
181 FlowRule f2 = addFlowRule(2); 191 FlowRule f2 = addFlowRule(2);
182 - addFlowRule(3); 192 + FlowRule f3 = addFlowRule(3);
183 assertEquals("3 rules should exist", 3, flowCount()); 193 assertEquals("3 rules should exist", 3, flowCount());
194 +
195 + providerService.pushFlowMetrics(DID, ImmutableList.of(f1, f2, f3));
184 validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED); 196 validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED);
185 197
186 FlowRule rem1 = flowRule(f1, FlowRuleState.REMOVED); 198 FlowRule rem1 = flowRule(f1, FlowRuleState.REMOVED);
...@@ -200,8 +212,9 @@ public class FlowRuleManagerTest { ...@@ -200,8 +212,9 @@ public class FlowRuleManagerTest {
200 @Test 212 @Test
201 public void flowRemoved() { 213 public void flowRemoved() {
202 FlowRule f1 = addFlowRule(1); 214 FlowRule f1 = addFlowRule(1);
215 + FlowRule f2 = addFlowRule(2);
216 + providerService.pushFlowMetrics(f1.deviceId(), ImmutableList.of(f1, f2));
203 service.removeFlowRules(f1); 217 service.removeFlowRules(f1);
204 - addFlowRule(2);
205 FlowRule rem1 = flowRule(f1, FlowRuleState.REMOVED); 218 FlowRule rem1 = flowRule(f1, FlowRuleState.REMOVED);
206 providerService.flowRemoved(rem1); 219 providerService.flowRemoved(rem1);
207 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED); 220 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
...@@ -209,9 +222,11 @@ public class FlowRuleManagerTest { ...@@ -209,9 +222,11 @@ public class FlowRuleManagerTest {
209 providerService.flowRemoved(rem1); 222 providerService.flowRemoved(rem1);
210 validateEvents(); 223 validateEvents();
211 224
212 - FlowRule f3 = flowRule(flowRule(3, 3), FlowRuleState.ADDED); 225 + FlowRule f3 = flowRule(3, 3);
213 - providerService.flowAdded(f3); 226 + service.applyFlowRules(f3);
227 + providerService.pushFlowMetrics(f3.deviceId(), Collections.singletonList(f3));
214 validateEvents(RULE_ADDED); 228 validateEvents(RULE_ADDED);
229 +
215 providerService.flowRemoved(f3); 230 providerService.flowRemoved(f3);
216 validateEvents(); 231 validateEvents();
217 } 232 }
...@@ -223,9 +238,10 @@ public class FlowRuleManagerTest { ...@@ -223,9 +238,10 @@ public class FlowRuleManagerTest {
223 FlowRule f3 = flowRule(3, 3); 238 FlowRule f3 = flowRule(3, 3);
224 239
225 240
241 +
242 + mgr.applyFlowRules(f1, f2, f3);
226 FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED); 243 FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
227 FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED); 244 FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
228 - mgr.applyFlowRules(f1, f2, f3);
229 245
230 providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2)); 246 providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2));
231 247
...@@ -233,7 +249,7 @@ public class FlowRuleManagerTest { ...@@ -233,7 +249,7 @@ public class FlowRuleManagerTest {
233 validateState(FlowRuleState.PENDING_ADD, FlowRuleState.ADDED, 249 validateState(FlowRuleState.PENDING_ADD, FlowRuleState.ADDED,
234 FlowRuleState.ADDED)); 250 FlowRuleState.ADDED));
235 251
236 - validateEvents(RULE_UPDATED, RULE_UPDATED); 252 + validateEvents(RULE_ADDED, RULE_ADDED);
237 } 253 }
238 254
239 @Test 255 @Test
...@@ -241,15 +257,15 @@ public class FlowRuleManagerTest { ...@@ -241,15 +257,15 @@ public class FlowRuleManagerTest {
241 FlowRule f1 = flowRule(1, 1); 257 FlowRule f1 = flowRule(1, 1);
242 FlowRule f2 = flowRule(2, 2); 258 FlowRule f2 = flowRule(2, 2);
243 FlowRule f3 = flowRule(3, 3); 259 FlowRule f3 = flowRule(3, 3);
260 + mgr.applyFlowRules(f1, f2);
244 261
245 FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED); 262 FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
246 FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED); 263 FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
247 FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED); 264 FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
248 - mgr.applyFlowRules(f1, f2);
249 265
250 providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2, updatedF3)); 266 providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2, updatedF3));
251 267
252 - validateEvents(RULE_UPDATED, RULE_UPDATED); 268 + validateEvents(RULE_ADDED, RULE_ADDED);
253 269
254 } 270 }
255 271
...@@ -271,7 +287,7 @@ public class FlowRuleManagerTest { ...@@ -271,7 +287,7 @@ public class FlowRuleManagerTest {
271 287
272 providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2)); 288 providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2));
273 289
274 - validateEvents(RULE_UPDATED, RULE_UPDATED, RULE_REMOVED); 290 + validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
275 291
276 } 292 }
277 293
...@@ -386,7 +402,7 @@ public class FlowRuleManagerTest { ...@@ -386,7 +402,7 @@ public class FlowRuleManagerTest {
386 } 402 }
387 403
388 @Override 404 @Override
389 - public List<Criterion> criteria() { 405 + public Set<Criterion> criteria() {
390 return null; 406 return null;
391 } 407 }
392 408
......
...@@ -20,7 +20,7 @@ import org.onlab.onos.cluster.DefaultControllerNode; ...@@ -20,7 +20,7 @@ import org.onlab.onos.cluster.DefaultControllerNode;
20 import org.onlab.onos.cluster.NodeId; 20 import org.onlab.onos.cluster.NodeId;
21 import org.onlab.onos.store.AbstractStore; 21 import org.onlab.onos.store.AbstractStore;
22 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationAdminService; 22 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationAdminService;
23 -import org.onlab.onos.store.cluster.messaging.impl.OnosClusterCommunicationManager; 23 +import org.onlab.onos.store.cluster.messaging.impl.ClusterCommunicationManager;
24 import org.onlab.packet.IpPrefix; 24 import org.onlab.packet.IpPrefix;
25 import org.slf4j.Logger; 25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory; 26 import org.slf4j.LoggerFactory;
...@@ -50,7 +50,7 @@ public class DistributedClusterStore ...@@ -50,7 +50,7 @@ public class DistributedClusterStore
50 private final Map<NodeId, State> states = new ConcurrentHashMap<>(); 50 private final Map<NodeId, State> states = new ConcurrentHashMap<>();
51 private final Cache<NodeId, ControllerNode> livenessCache = CacheBuilder.newBuilder() 51 private final Cache<NodeId, ControllerNode> livenessCache = CacheBuilder.newBuilder()
52 .maximumSize(1000) 52 .maximumSize(1000)
53 - .expireAfterWrite(OnosClusterCommunicationManager.HEART_BEAT_INTERVAL_MILLIS * 3, TimeUnit.MILLISECONDS) 53 + .expireAfterWrite(ClusterCommunicationManager.HEART_BEAT_INTERVAL_MILLIS * 3, TimeUnit.MILLISECONDS)
54 .removalListener(new LivenessCacheRemovalListener()).build(); 54 .removalListener(new LivenessCacheRemovalListener()).build();
55 55
56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
......
1 package org.onlab.onos.store.cluster.messaging; 1 package org.onlab.onos.store.cluster.messaging;
2 2
3 +/**
4 + * Interface for handling cluster messages.
5 + */
3 public interface ClusterMessageHandler { 6 public interface ClusterMessageHandler {
7 +
8 + /**
9 + * Handles/Processes the cluster message.
10 + * @param message cluster message.
11 + */
4 public void handle(ClusterMessage message); 12 public void handle(ClusterMessage message);
5 } 13 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -2,6 +2,8 @@ package org.onlab.onos.store.cluster.messaging; ...@@ -2,6 +2,8 @@ package org.onlab.onos.store.cluster.messaging;
2 2
3 /** 3 /**
4 * Representation of a message subject. 4 * Representation of a message subject.
5 + * Cluster messages have associated subjects that dictate how they get handled
6 + * on the receiving side.
5 */ 7 */
6 public class MessageSubject { 8 public class MessageSubject {
7 9
......
1 -package org.onlab.onos.store.cluster.messaging;
2 -
3 -import org.onlab.onos.cluster.NodeId;
4 -
5 -/**
6 - * Represents a message consumer.
7 - */
8 -public interface MessageSubscriber {
9 -
10 - /**
11 - * Receives the specified cluster message.
12 - *
13 - * @param message message to be received
14 - * @param fromNodeId node from which the message was received
15 - */
16 - void receive(Object messagePayload, NodeId fromNodeId);
17 -
18 -}
...@@ -32,7 +32,7 @@ import org.slf4j.LoggerFactory; ...@@ -32,7 +32,7 @@ import org.slf4j.LoggerFactory;
32 32
33 @Component(immediate = true) 33 @Component(immediate = true)
34 @Service 34 @Service
35 -public class OnosClusterCommunicationManager 35 +public class ClusterCommunicationManager
36 implements ClusterCommunicationService, ClusterCommunicationAdminService { 36 implements ClusterCommunicationService, ClusterCommunicationAdminService {
37 37
38 private final Logger log = LoggerFactory.getLogger(getClass()); 38 private final Logger log = LoggerFactory.getLogger(getClass());
......
...@@ -6,7 +6,7 @@ import org.junit.Ignore; ...@@ -6,7 +6,7 @@ import org.junit.Ignore;
6 import org.junit.Test; 6 import org.junit.Test;
7 import org.onlab.onos.cluster.DefaultControllerNode; 7 import org.onlab.onos.cluster.DefaultControllerNode;
8 import org.onlab.onos.cluster.NodeId; 8 import org.onlab.onos.cluster.NodeId;
9 -import org.onlab.onos.store.cluster.messaging.impl.OnosClusterCommunicationManager; 9 +import org.onlab.onos.store.cluster.messaging.impl.ClusterCommunicationManager;
10 import org.onlab.netty.NettyMessagingService; 10 import org.onlab.netty.NettyMessagingService;
11 import org.onlab.packet.IpPrefix; 11 import org.onlab.packet.IpPrefix;
12 12
...@@ -29,8 +29,8 @@ public class ClusterCommunicationManagerTest { ...@@ -29,8 +29,8 @@ public class ClusterCommunicationManagerTest {
29 29
30 private static final IpPrefix IP = IpPrefix.valueOf("127.0.0.1"); 30 private static final IpPrefix IP = IpPrefix.valueOf("127.0.0.1");
31 31
32 - private OnosClusterCommunicationManager ccm1; 32 + private ClusterCommunicationManager ccm1;
33 - private OnosClusterCommunicationManager ccm2; 33 + private ClusterCommunicationManager ccm2;
34 34
35 private TestDelegate cnd1 = new TestDelegate(); 35 private TestDelegate cnd1 = new TestDelegate();
36 private TestDelegate cnd2 = new TestDelegate(); 36 private TestDelegate cnd2 = new TestDelegate();
...@@ -46,11 +46,11 @@ public class ClusterCommunicationManagerTest { ...@@ -46,11 +46,11 @@ public class ClusterCommunicationManagerTest {
46 NettyMessagingService messagingService = new NettyMessagingService(); 46 NettyMessagingService messagingService = new NettyMessagingService();
47 messagingService.activate(); 47 messagingService.activate();
48 48
49 - ccm1 = new OnosClusterCommunicationManager(); 49 + ccm1 = new ClusterCommunicationManager();
50 // ccm1.serializationService = messageSerializer; 50 // ccm1.serializationService = messageSerializer;
51 ccm1.activate(); 51 ccm1.activate();
52 52
53 - ccm2 = new OnosClusterCommunicationManager(); 53 + ccm2 = new ClusterCommunicationManager();
54 // ccm2.serializationService = messageSerializer; 54 // ccm2.serializationService = messageSerializer;
55 ccm2.activate(); 55 ccm2.activate();
56 56
......
1 package org.onlab.onos.store.trivial.impl; 1 package org.onlab.onos.store.trivial.impl;
2 2
3 -import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
4 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; 3 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
5 import static org.slf4j.LoggerFactory.getLogger; 4 import static org.slf4j.LoggerFactory.getLogger;
6 5
...@@ -116,18 +115,21 @@ public class SimpleFlowRuleStore ...@@ -116,18 +115,21 @@ public class SimpleFlowRuleStore
116 DeviceId did = rule.deviceId(); 115 DeviceId did = rule.deviceId();
117 116
118 // check if this new rule is an update to an existing entry 117 // check if this new rule is an update to an existing entry
119 - if (flowEntries.containsEntry(did, rule)) { 118 + FlowRule stored = getFlowRule(rule);
120 - //synchronized (flowEntries) { 119 + if (stored != null) {
121 // Multimaps support duplicates so we have to remove our rule 120 // Multimaps support duplicates so we have to remove our rule
122 // and replace it with the current version. 121 // and replace it with the current version.
123 flowEntries.remove(did, rule); 122 flowEntries.remove(did, rule);
124 flowEntries.put(did, rule); 123 flowEntries.put(did, rule);
125 - //} 124 +
125 + if (stored.state() == FlowRuleState.PENDING_ADD) {
126 + return new FlowRuleEvent(Type.RULE_ADDED, rule);
127 + }
126 return new FlowRuleEvent(Type.RULE_UPDATED, rule); 128 return new FlowRuleEvent(Type.RULE_UPDATED, rule);
127 } 129 }
128 130
129 flowEntries.put(did, rule); 131 flowEntries.put(did, rule);
130 - return new FlowRuleEvent(RULE_ADDED, rule); 132 + return null;
131 } 133 }
132 134
133 @Override 135 @Override
...@@ -140,11 +142,4 @@ public class SimpleFlowRuleStore ...@@ -140,11 +142,4 @@ public class SimpleFlowRuleStore
140 } 142 }
141 //} 143 //}
142 } 144 }
143 -
144 -
145 -
146 -
147 -
148 -
149 -
150 } 145 }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
11 <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> 11 <bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
12 12
13 <bundle>mvn:com.hazelcast/hazelcast/3.3</bundle> 13 <bundle>mvn:com.hazelcast/hazelcast/3.3</bundle>
14 - <bundle>mvn:com.codahale.metrics/metrics-core/3.0.2</bundle> 14 + <bundle>mvn:io.dropwizard.metrics/metrics-core/3.1.0</bundle>
15 <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle> 15 <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle>
16 16
17 <bundle>mvn:com.esotericsoftware.kryo/kryo/2.24.0</bundle> 17 <bundle>mvn:com.esotericsoftware.kryo/kryo/2.24.0</bundle>
......
...@@ -169,7 +169,12 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -169,7 +169,12 @@ public class OpenFlowControllerImpl implements OpenFlowController {
169 169
170 @Override 170 @Override
171 public void setRole(Dpid dpid, RoleState role) { 171 public void setRole(Dpid dpid, RoleState role) {
172 - getSwitch(dpid).setRole(role); 172 + final OpenFlowSwitch sw = getSwitch(dpid);
173 + if (sw == null) {
174 + log.debug("Switch not connected. Ignoring setRole({}, {})", dpid, role);
175 + return;
176 + }
177 + sw.setRole(role);
173 } 178 }
174 179
175 /** 180 /**
......
...@@ -248,6 +248,11 @@ ...@@ -248,6 +248,11 @@
248 <classifier>tests</classifier> 248 <classifier>tests</classifier>
249 <scope>test</scope> 249 <scope>test</scope>
250 </dependency> 250 </dependency>
251 + <dependency>
252 + <groupId>commons-pool</groupId>
253 + <artifactId>commons-pool</artifactId>
254 + <version>1.6</version>
255 + </dependency>
251 </dependencies> 256 </dependencies>
252 </dependencyManagement> 257 </dependencyManagement>
253 258
......
...@@ -77,7 +77,6 @@ public class FlowModBuilder { ...@@ -77,7 +77,6 @@ public class FlowModBuilder {
77 .setCookie(U64.of(cookie.value())) 77 .setCookie(U64.of(cookie.value()))
78 .setBufferId(OFBufferId.NO_BUFFER) 78 .setBufferId(OFBufferId.NO_BUFFER)
79 .setActions(actions) 79 .setActions(actions)
80 - .setIdleTimeout(10)
81 .setMatch(match) 80 .setMatch(match)
82 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) 81 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
83 .setPriority(priority) 82 .setPriority(priority)
......
...@@ -71,7 +71,7 @@ public class FlowRuleBuilder { ...@@ -71,7 +71,7 @@ public class FlowRuleBuilder {
71 buildSelector(), buildTreatment(), stat.getPriority(), 71 buildSelector(), buildTreatment(), stat.getPriority(),
72 FlowRuleState.ADDED, stat.getDurationNsec() / 1000000, 72 FlowRuleState.ADDED, stat.getDurationNsec() / 1000000,
73 stat.getPacketCount().getValue(), stat.getByteCount().getValue(), 73 stat.getPacketCount().getValue(), stat.getByteCount().getValue(),
74 - stat.getCookie().getValue(), false); 74 + stat.getCookie().getValue(), false, stat.getIdleTimeout());
75 } else { 75 } else {
76 // TODO: revisit potentially. 76 // TODO: revisit potentially.
77 return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)), 77 return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
...@@ -79,7 +79,8 @@ public class FlowRuleBuilder { ...@@ -79,7 +79,8 @@ public class FlowRuleBuilder {
79 FlowRuleState.REMOVED, removed.getDurationNsec() / 1000000, 79 FlowRuleState.REMOVED, removed.getDurationNsec() / 1000000,
80 removed.getPacketCount().getValue(), removed.getByteCount().getValue(), 80 removed.getPacketCount().getValue(), removed.getByteCount().getValue(),
81 removed.getCookie().getValue(), 81 removed.getCookie().getValue(),
82 - removed.getReason() == OFFlowRemovedReason.IDLE_TIMEOUT.ordinal()); 82 + removed.getReason() == OFFlowRemovedReason.IDLE_TIMEOUT.ordinal(),
83 + stat.getIdleTimeout());
83 } 84 }
84 } 85 }
85 86
......
...@@ -127,7 +127,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -127,7 +127,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
127 127
128 @Override 128 @Override
129 public void switchAdded(Dpid dpid) { 129 public void switchAdded(Dpid dpid) {
130 - FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), 5); 130 + FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), POLL_INTERVAL);
131 fsc.start(); 131 fsc.start();
132 collectors.put(dpid, fsc); 132 collectors.put(dpid, fsc);
133 } 133 }
......
...@@ -176,7 +176,7 @@ ...@@ -176,7 +176,7 @@
176 </module> 176 </module>
177 177
178 <module name="ParameterNumber"> 178 <module name="ParameterNumber">
179 - <property name="max" value="10"/> 179 + <property name="max" value="15"/>
180 <property name="tokens" value="CTOR_DEF"/> 180 <property name="tokens" value="CTOR_DEF"/>
181 </module> 181 </module>
182 <!-- Checks for whitespace --> 182 <!-- Checks for whitespace -->
......
...@@ -56,9 +56,13 @@ ...@@ -56,9 +56,13 @@
56 <artifactId>objenesis</artifactId> 56 <artifactId>objenesis</artifactId>
57 </dependency> 57 </dependency>
58 <dependency> 58 <dependency>
59 - <groupId>com.codahale.metrics</groupId> 59 + <groupId>io.dropwizard.metrics</groupId>
60 <artifactId>metrics-core</artifactId> 60 <artifactId>metrics-core</artifactId>
61 - <version>3.0.2</version> 61 + <version>3.1.0</version>
62 + </dependency>
63 + <dependency>
64 + <groupId>org.apache.felix</groupId>
65 + <artifactId>org.apache.felix.scr.annotations</artifactId>
62 </dependency> 66 </dependency>
63 </dependencies> 67 </dependencies>
64 68
......
1 package org.onlab.metrics; 1 package org.onlab.metrics;
2 2
3 +import java.io.File;
4 +import java.util.Locale;
3 import java.util.Map; 5 import java.util.Map;
4 import java.util.concurrent.ConcurrentHashMap; 6 import java.util.concurrent.ConcurrentHashMap;
5 import java.util.concurrent.ConcurrentMap; 7 import java.util.concurrent.ConcurrentMap;
8 +import java.util.concurrent.TimeUnit;
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;
6 13
7 import com.codahale.metrics.Counter; 14 import com.codahale.metrics.Counter;
15 +import com.codahale.metrics.CsvReporter;
8 import com.codahale.metrics.Gauge; 16 import com.codahale.metrics.Gauge;
9 import com.codahale.metrics.Histogram; 17 import com.codahale.metrics.Histogram;
10 import com.codahale.metrics.Meter; 18 import com.codahale.metrics.Meter;
...@@ -45,24 +53,44 @@ import com.codahale.metrics.Timer; ...@@ -45,24 +53,44 @@ import com.codahale.metrics.Timer;
45 * </code> 53 * </code>
46 * </pre> 54 * </pre>
47 */ 55 */
56 +@Component(immediate = true)
48 public final class MetricsManager implements MetricsService { 57 public final class MetricsManager implements MetricsService {
49 58
50 /** 59 /**
51 * Registry to hold the Components defined in the system. 60 * Registry to hold the Components defined in the system.
52 */ 61 */
53 - private ConcurrentMap<String, MetricsComponent> componentsRegistry = 62 + private ConcurrentMap<String, MetricsComponent> componentsRegistry;
54 - new ConcurrentHashMap<>();
55 63
56 /** 64 /**
57 * Registry for the Metrics objects created in the system. 65 * Registry for the Metrics objects created in the system.
58 */ 66 */
59 - private final MetricRegistry metricsRegistry = new MetricRegistry(); 67 + private final MetricRegistry metricsRegistry;
60 68
61 /** 69 /**
62 - * Hide constructor. The only way to get the registry is through the 70 + * Default Reporter for this metrics manager.
63 - * singleton getter.
64 */ 71 */
65 - private MetricsManager() {} 72 + private final CsvReporter reporter;
73 +
74 + public MetricsManager() {
75 + this.componentsRegistry = new ConcurrentHashMap<>();
76 + this.metricsRegistry = new MetricRegistry();
77 +
78 + this.reporter = CsvReporter.forRegistry(metricsRegistry)
79 + .formatFor(Locale.US)
80 + .convertRatesTo(TimeUnit.SECONDS)
81 + .convertDurationsTo(TimeUnit.MICROSECONDS)
82 + .build(new File("/tmp/"));
83 +
84 + reporter.start(10, TimeUnit.SECONDS);
85 + }
86 +
87 + @Activate
88 + public void activate() {
89 + }
90 +
91 + @Deactivate
92 + public void deactivate() {
93 + }
66 94
67 /** 95 /**
68 * Registers a component. 96 * Registers a component.
......
...@@ -250,6 +250,17 @@ public final class IpPrefix { ...@@ -250,6 +250,17 @@ public final class IpPrefix {
250 return new IpPrefix(version, host, netmask); 250 return new IpPrefix(version, host, netmask);
251 } 251 }
252 252
253 + /**
254 + * Returns an IpAddress of the bytes contained in this prefix.
255 + * FIXME this is a hack for now and only works because IpPrefix doesn't
256 + * mask the input bytes on creation.
257 + *
258 + * @return the IpAddress
259 + */
260 + public IpAddress toIpAddress() {
261 + return IpAddress.valueOf(octets);
262 + }
263 +
253 public boolean isMasked() { 264 public boolean isMasked() {
254 return mask() != 0; 265 return mask() != 0;
255 } 266 }
...@@ -278,6 +289,17 @@ public final class IpPrefix { ...@@ -278,6 +289,17 @@ public final class IpPrefix {
278 return false; 289 return false;
279 } 290 }
280 291
292 + public boolean contains(IpAddress address) {
293 + // Need to get the network address because prefixes aren't automatically
294 + // masked on creation
295 + IpPrefix meMasked = network();
296 +
297 + IpPrefix otherMasked =
298 + IpPrefix.valueOf(address.octets, netmask).network();
299 +
300 + return Arrays.equals(meMasked.octets, otherMasked.octets);
301 + }
302 +
281 @Override 303 @Override
282 public int hashCode() { 304 public int hashCode() {
283 final int prime = 31; 305 final int prime = 31;
...@@ -303,6 +325,7 @@ public final class IpPrefix { ...@@ -303,6 +325,7 @@ public final class IpPrefix {
303 if (netmask != other.netmask) { 325 if (netmask != other.netmask) {
304 return false; 326 return false;
305 } 327 }
328 + // TODO not quite right until we mask the input
306 if (!Arrays.equals(octets, other.octets)) { 329 if (!Arrays.equals(octets, other.octets)) {
307 return false; 330 return false;
308 } 331 }
......
...@@ -76,7 +76,7 @@ public class IpPrefixTest { ...@@ -76,7 +76,7 @@ public class IpPrefixTest {
76 } 76 }
77 77
78 @Test 78 @Test
79 - public void testContains() { 79 + public void testContainsIpPrefix() {
80 IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31); 80 IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31);
81 IpPrefix slash32 = IpPrefix.valueOf(BYTES1, 32); 81 IpPrefix slash32 = IpPrefix.valueOf(BYTES1, 32);
82 IpPrefix differentSlash32 = IpPrefix.valueOf(BYTES2, 32); 82 IpPrefix differentSlash32 = IpPrefix.valueOf(BYTES2, 32);
...@@ -96,4 +96,17 @@ public class IpPrefixTest { ...@@ -96,4 +96,17 @@ public class IpPrefixTest {
96 assertTrue(slash8.contains(slash31)); 96 assertTrue(slash8.contains(slash31));
97 assertFalse(slash31.contains(slash8)); 97 assertFalse(slash31.contains(slash8));
98 } 98 }
99 +
100 + @Test
101 + public void testContainsIpAddress() {
102 + IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31);
103 + IpAddress slash32 = IpAddress.valueOf(BYTES1, 32);
104 +
105 + assertTrue(slash31.contains(slash32));
106 +
107 + IpPrefix intf = IpPrefix.valueOf("192.168.10.101/24");
108 + IpAddress addr = IpAddress.valueOf("192.168.10.1");
109 +
110 + assertTrue(intf.contains(addr));
111 + }
99 } 112 }
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
42 <dependency> 42 <dependency>
43 <groupId>commons-pool</groupId> 43 <groupId>commons-pool</groupId>
44 <artifactId>commons-pool</artifactId> 44 <artifactId>commons-pool</artifactId>
45 - <version>1.6</version>
46 </dependency> 45 </dependency>
47 </dependencies> 46 </dependencies>
48 47
......
1 +package org.onlab.netty;
2 +
3 +import java.util.concurrent.TimeUnit;
4 +import java.util.concurrent.TimeoutException;
5 +
6 +/**
7 + * An asynchronous response.
8 + * This class provides a base implementation of Response, with methods to retrieve the
9 + * result and query to see if the result is ready. The result can only be retrieved when
10 + * it is ready and the get methods will block if the result is not ready yet.
11 + * @param <T> type of response.
12 + */
13 +public class AsyncResponse<T> implements Response<T> {
14 +
15 + private T value;
16 + private boolean done = false;
17 + private final long start = System.nanoTime();
18 +
19 + @Override
20 + public T get(long timeout, TimeUnit tu) throws TimeoutException {
21 + timeout = tu.toNanos(timeout);
22 + boolean interrupted = false;
23 + try {
24 + synchronized (this) {
25 + while (!done) {
26 + try {
27 + long timeRemaining = timeout - (System.nanoTime() - start);
28 + if (timeRemaining <= 0) {
29 + throw new TimeoutException("Operation timed out.");
30 + }
31 + TimeUnit.NANOSECONDS.timedWait(this, timeRemaining);
32 + } catch (InterruptedException e) {
33 + interrupted = true;
34 + }
35 + }
36 + }
37 + } finally {
38 + if (interrupted) {
39 + Thread.currentThread().interrupt();
40 + }
41 + }
42 + return value;
43 + }
44 +
45 + @Override
46 + public T get() throws InterruptedException {
47 + throw new UnsupportedOperationException();
48 + }
49 +
50 + @Override
51 + public boolean isReady() {
52 + return done;
53 + }
54 +
55 + /**
56 + * Sets response value and unblocks any thread blocking on the response to become
57 + * available.
58 + * @param data response data.
59 + */
60 + @SuppressWarnings("unchecked")
61 + public synchronized void setResponse(Object data) {
62 + if (!done) {
63 + done = true;
64 + value = (T) data;
65 + this.notifyAll();
66 + }
67 + }
68 +}
1 +package org.onlab.netty;
2 +
3 +import java.io.IOException;
4 +
5 +/**
6 + * Message handler that echos the message back to the sender.
7 + */
8 +public class EchoHandler implements MessageHandler {
9 +
10 + @Override
11 + public void handle(Message message) throws IOException {
12 + System.out.println("Received: " + message.payload() + ". Echoing it back to the sender.");
13 + message.respond(message.payload());
14 + }
15 +}
1 +package org.onlab.netty;
2 +
3 +/**
4 + * Representation of a TCP/UDP communication end point.
5 + */
6 +public class Endpoint {
7 +
8 + private final int port;
9 + private final String host;
10 +
11 + public Endpoint(String host, int port) {
12 + this.host = host;
13 + this.port = port;
14 + }
15 +
16 + public String host() {
17 + return host;
18 + }
19 +
20 + public int port() {
21 + return port;
22 + }
23 +
24 + @Override
25 + public String toString() {
26 + return "Endpoint [port=" + port + ", host=" + host + "]";
27 + }
28 +
29 + @Override
30 + public int hashCode() {
31 + final int prime = 31;
32 + int result = 1;
33 + result = prime * result + ((host == null) ? 0 : host.hashCode());
34 + result = prime * result + port;
35 + return result;
36 + }
37 +
38 + @Override
39 + public boolean equals(Object obj) {
40 + if (this == obj) {
41 + return true;
42 + }
43 + if (obj == null) {
44 + return false;
45 + }
46 + if (getClass() != obj.getClass()) {
47 + return false;
48 + }
49 + Endpoint other = (Endpoint) obj;
50 + if (host == null) {
51 + if (other.host != null) {
52 + return false;
53 + }
54 + } else if (!host.equals(other.host)) {
55 + return false;
56 + }
57 + if (port != other.port) {
58 + return false;
59 + }
60 + return true;
61 + }
62 +}
1 +package org.onlab.netty;
2 +
3 +import java.io.IOException;
4 +
5 +/**
6 + * Internal message representation with additional attributes
7 + * for supporting, synchronous request/reply behavior.
8 + */
9 +public final class InternalMessage implements Message {
10 +
11 + private long id;
12 + private Endpoint sender;
13 + private String type;
14 + private Object payload;
15 + private transient NettyMessagingService messagingService;
16 + public static final String REPLY_MESSAGE_TYPE = "NETTY_MESSAGIG_REQUEST_REPLY";
17 +
18 + // Must be created using the Builder.
19 + private InternalMessage() {}
20 +
21 + public long id() {
22 + return id;
23 + }
24 +
25 + public String type() {
26 + return type;
27 + }
28 +
29 + public Endpoint sender() {
30 + return sender;
31 + }
32 +
33 + @Override
34 + public Object payload() {
35 + return payload;
36 + }
37 +
38 + @Override
39 + public void respond(Object data) throws IOException {
40 + Builder builder = new Builder(messagingService);
41 + InternalMessage message = builder.withId(this.id)
42 + // FIXME: Sender should be messagingService.localEp.
43 + .withSender(this.sender)
44 + .withPayload(data)
45 + .withType(REPLY_MESSAGE_TYPE)
46 + .build();
47 + messagingService.sendAsync(sender, message);
48 + }
49 +
50 +
51 + /**
52 + * Builder for InternalMessages.
53 + */
54 + public static class Builder {
55 + private InternalMessage message;
56 +
57 + public Builder(NettyMessagingService messagingService) {
58 + message = new InternalMessage();
59 + message.messagingService = messagingService;
60 + }
61 +
62 + public Builder withId(long id) {
63 + message.id = id;
64 + return this;
65 + }
66 +
67 + public Builder withType(String type) {
68 + message.type = type;
69 + return this;
70 + }
71 +
72 + public Builder withSender(Endpoint sender) {
73 + message.sender = sender;
74 + return this;
75 + }
76 + public Builder withPayload(Object payload) {
77 + message.payload = payload;
78 + return this;
79 + }
80 +
81 + public InternalMessage build() {
82 + return message;
83 + }
84 + }
85 +}
1 +package org.onlab.netty;
2 +
3 +import org.onlab.util.KryoPool;
4 +import org.slf4j.Logger;
5 +import org.slf4j.LoggerFactory;
6 +
7 +import java.util.ArrayList;
8 +import java.util.HashMap;
9 +
10 +/**
11 + * Kryo Serializer.
12 + */
13 +public class KryoSerializer implements Serializer {
14 +
15 + private final Logger log = LoggerFactory.getLogger(getClass());
16 +
17 + private KryoPool serializerPool;
18 +
19 + public KryoSerializer() {
20 + setupKryoPool();
21 + }
22 +
23 + /**
24 + * Sets up the common serialzers pool.
25 + */
26 + protected void setupKryoPool() {
27 + // FIXME Slice out types used in common to separate pool/namespace.
28 + serializerPool = KryoPool.newBuilder()
29 + .register(ArrayList.class,
30 + HashMap.class,
31 + ArrayList.class
32 + )
33 + .build()
34 + .populate(1);
35 + }
36 +
37 +
38 + @Override
39 + public Object decode(byte[] data) {
40 + return serializerPool.deserialize(data);
41 + }
42 +
43 + @Override
44 + public byte[] encode(Object payload) {
45 + return serializerPool.serialize(payload);
46 + }
47 +}
1 +package org.onlab.netty;
2 +
3 +/**
4 + * A MessageHandler that simply logs the information.
5 + */
6 +public class LoggingHandler implements MessageHandler {
7 +
8 + @Override
9 + public void handle(Message message) {
10 + System.out.println("Received: " + message.payload());
11 + }
12 +}
1 +package org.onlab.netty;
2 +
3 +import java.io.IOException;
4 +
5 +/**
6 + * A unit of communication.
7 + * Has a payload. Also supports a feature to respond back to the sender.
8 + */
9 +public interface Message {
10 +
11 + /**
12 + * Returns the payload of this message.
13 + * @return message payload.
14 + */
15 + public Object payload();
16 +
17 + /**
18 + * Sends a reply back to the sender of this messge.
19 + * @param data payload of the response.
20 + * @throws IOException if there is a communication error.
21 + */
22 + public void respond(Object data) throws IOException;
23 +}
1 +package org.onlab.netty;
2 +
3 +import java.util.Arrays;
4 +import java.util.List;
5 +
6 +import static com.google.common.base.Preconditions.checkState;
7 +
8 +import io.netty.buffer.ByteBuf;
9 +import io.netty.channel.ChannelHandlerContext;
10 +import io.netty.handler.codec.ByteToMessageDecoder;
11 +
12 +/**
13 + * Decode bytes into a InternalMessage.
14 + */
15 +public class MessageDecoder extends ByteToMessageDecoder {
16 +
17 + private final NettyMessagingService messagingService;
18 + private final Serializer serializer;
19 +
20 + public MessageDecoder(NettyMessagingService messagingService, Serializer serializer) {
21 + this.messagingService = messagingService;
22 + this.serializer = serializer;
23 + }
24 +
25 + @Override
26 + protected void decode(ChannelHandlerContext context, ByteBuf in,
27 + List<Object> messages) throws Exception {
28 +
29 + byte[] preamble = in.readBytes(MessageEncoder.PREAMBLE.length).array();
30 + checkState(Arrays.equals(MessageEncoder.PREAMBLE, preamble), "Message has wrong preamble");
31 +
32 + // read message Id.
33 + long id = in.readLong();
34 +
35 + // read message type; first read size and then bytes.
36 + String type = new String(in.readBytes(in.readInt()).array());
37 +
38 + // read sender host name; first read size and then bytes.
39 + String host = new String(in.readBytes(in.readInt()).array());
40 +
41 + // read sender port.
42 + int port = in.readInt();
43 +
44 + Endpoint sender = new Endpoint(host, port);
45 +
46 + // read message payload; first read size and then bytes.
47 + Object payload = serializer.decode(in.readBytes(in.readInt()).array());
48 +
49 + InternalMessage message = new InternalMessage.Builder(messagingService)
50 + .withId(id)
51 + .withSender(sender)
52 + .withType(type)
53 + .withPayload(payload)
54 + .build();
55 +
56 + messages.add(message);
57 + }
58 +}
1 +package org.onlab.netty;
2 +
3 +import io.netty.buffer.ByteBuf;
4 +import io.netty.channel.ChannelHandlerContext;
5 +import io.netty.handler.codec.MessageToByteEncoder;
6 +
7 +/**
8 + * Encode InternalMessage out into a byte buffer.
9 + */
10 +public class MessageEncoder extends MessageToByteEncoder<InternalMessage> {
11 +
12 + // onosiscool in ascii
13 + public static final byte[] PREAMBLE = "onosiscool".getBytes();
14 +
15 + private final Serializer serializer;
16 +
17 + public MessageEncoder(Serializer serializer) {
18 + this.serializer = serializer;
19 + }
20 +
21 + @Override
22 + protected void encode(ChannelHandlerContext context, InternalMessage message,
23 + ByteBuf out) throws Exception {
24 +
25 + // write preamble
26 + out.writeBytes(PREAMBLE);
27 +
28 + // write id
29 + out.writeLong(message.id());
30 +
31 + // write type length
32 + out.writeInt(message.type().length());
33 +
34 + // write type
35 + out.writeBytes(message.type().getBytes());
36 +
37 + // write sender host name size
38 + out.writeInt(message.sender().host().length());
39 +
40 + // write sender host name.
41 + out.writeBytes(message.sender().host().getBytes());
42 +
43 + // write port
44 + out.writeInt(message.sender().port());
45 +
46 + try {
47 + serializer.encode(message.payload());
48 + } catch (Exception e) {
49 + e.printStackTrace();
50 + }
51 +
52 + byte[] payload = serializer.encode(message.payload());
53 +
54 + // write payload length.
55 + out.writeInt(payload.length);
56 +
57 + // write payload bytes
58 + out.writeBytes(payload);
59 + }
60 +}
1 +package org.onlab.netty;
2 +
3 +import java.io.IOException;
4 +
5 +/**
6 + * Handler for a message.
7 + */
8 +public interface MessageHandler {
9 +
10 + /**
11 + * Handles the message.
12 + * @param message message.
13 + * @throws IOException.
14 + */
15 + public void handle(Message message) throws IOException;
16 +}
1 +package org.onlab.netty;
2 +
3 +import java.io.IOException;
4 +
5 +/**
6 + * Interface for low level messaging primitives.
7 + */
8 +public interface MessagingService {
9 + /**
10 + * Sends a message asynchronously to the specified communication end point.
11 + * The message is specified using the type and payload.
12 + * @param ep end point to send the message to.
13 + * @param type type of message.
14 + * @param payload message payload.
15 + * @throws IOException
16 + */
17 + public void sendAsync(Endpoint ep, String type, Object payload) throws IOException;
18 +
19 + /**
20 + * Sends a message synchronously and waits for a response.
21 + * @param ep end point to send the message to.
22 + * @param type type of message.
23 + * @param payload message payload.
24 + * @return a response future
25 + * @throws IOException
26 + */
27 + public <T> Response<T> sendAndReceive(Endpoint ep, String type, Object payload) throws IOException;
28 +
29 + /**
30 + * Registers a new message handler for message type.
31 + * @param type message type.
32 + * @param handler message handler
33 + */
34 + public void registerHandler(String type, MessageHandler handler);
35 +
36 + /**
37 + * Unregister current handler, if one exists for message type.
38 + * @param type message type
39 + */
40 + public void unregisterHandler(String type);
41 +}
1 +package org.onlab.netty;
2 +
3 +import java.io.IOException;
4 +import java.net.UnknownHostException;
5 +import java.util.concurrent.ConcurrentHashMap;
6 +import java.util.concurrent.ConcurrentMap;
7 +import java.util.concurrent.TimeUnit;
8 +
9 +import io.netty.bootstrap.Bootstrap;
10 +import io.netty.bootstrap.ServerBootstrap;
11 +import io.netty.buffer.PooledByteBufAllocator;
12 +import io.netty.channel.Channel;
13 +import io.netty.channel.ChannelFuture;
14 +import io.netty.channel.ChannelHandlerContext;
15 +import io.netty.channel.ChannelInitializer;
16 +import io.netty.channel.ChannelOption;
17 +import io.netty.channel.EventLoopGroup;
18 +import io.netty.channel.SimpleChannelInboundHandler;
19 +import io.netty.channel.nio.NioEventLoopGroup;
20 +import io.netty.channel.socket.SocketChannel;
21 +import io.netty.channel.socket.nio.NioServerSocketChannel;
22 +import io.netty.channel.socket.nio.NioSocketChannel;
23 +
24 +import org.apache.commons.lang.math.RandomUtils;
25 +import org.apache.commons.pool.KeyedObjectPool;
26 +import org.apache.commons.pool.KeyedPoolableObjectFactory;
27 +import org.apache.commons.pool.impl.GenericKeyedObjectPool;
28 +import org.slf4j.Logger;
29 +import org.slf4j.LoggerFactory;
30 +
31 +import com.google.common.cache.Cache;
32 +import com.google.common.cache.CacheBuilder;
33 +
34 +/**
35 + * A Netty based implementation of MessagingService.
36 + */
37 +public class NettyMessagingService implements MessagingService {
38 +
39 + private final Logger log = LoggerFactory.getLogger(getClass());
40 +
41 + private KeyedObjectPool<Endpoint, Channel> channels =
42 + new GenericKeyedObjectPool<Endpoint, Channel>(new OnosCommunicationChannelFactory());
43 + private final int port;
44 + private final EventLoopGroup bossGroup = new NioEventLoopGroup();
45 + private final EventLoopGroup workerGroup = new NioEventLoopGroup();
46 + private final ConcurrentMap<String, MessageHandler> handlers = new ConcurrentHashMap<>();
47 + private Cache<Long, AsyncResponse<?>> responseFutures;
48 + private final Endpoint localEp;
49 +
50 + protected Serializer serializer;
51 +
52 + public NettyMessagingService() {
53 + // TODO: Default port should be configurable.
54 + this(8080);
55 + }
56 +
57 + // FIXME: Constructor should not throw exceptions.
58 + public NettyMessagingService(int port) {
59 + this.port = port;
60 + try {
61 + localEp = new Endpoint(java.net.InetAddress.getLocalHost().getHostName(), port);
62 + } catch (UnknownHostException e) {
63 + // bailing out.
64 + throw new RuntimeException(e);
65 + }
66 + }
67 +
68 + public void activate() throws Exception {
69 + responseFutures = CacheBuilder.newBuilder()
70 + .maximumSize(100000)
71 + .weakValues()
72 + // TODO: Once the entry expires, notify blocking threads (if any).
73 + .expireAfterWrite(10, TimeUnit.MINUTES)
74 + .build();
75 + startAcceptingConnections();
76 + }
77 +
78 + public void deactivate() throws Exception {
79 + channels.close();
80 + bossGroup.shutdownGracefully();
81 + workerGroup.shutdownGracefully();
82 + }
83 +
84 + @Override
85 + public void sendAsync(Endpoint ep, String type, Object payload) throws IOException {
86 + InternalMessage message = new InternalMessage.Builder(this)
87 + .withId(RandomUtils.nextLong())
88 + .withSender(localEp)
89 + .withType(type)
90 + .withPayload(payload)
91 + .build();
92 + sendAsync(ep, message);
93 + }
94 +
95 + protected void sendAsync(Endpoint ep, InternalMessage message) throws IOException {
96 + Channel channel = null;
97 + try {
98 + channel = channels.borrowObject(ep);
99 + channel.eventLoop().execute(new WriteTask(channel, message));
100 + } catch (Exception e) {
101 + throw new IOException(e);
102 + } finally {
103 + try {
104 + channels.returnObject(ep, channel);
105 + } catch (Exception e) {
106 + log.warn("Error returning object back to the pool", e);
107 + // ignored.
108 + }
109 + }
110 + }
111 +
112 + @Override
113 + public <T> Response<T> sendAndReceive(Endpoint ep, String type, Object payload)
114 + throws IOException {
115 + AsyncResponse<T> futureResponse = new AsyncResponse<T>();
116 + Long messageId = RandomUtils.nextLong();
117 + responseFutures.put(messageId, futureResponse);
118 + InternalMessage message = new InternalMessage.Builder(this)
119 + .withId(messageId)
120 + .withSender(localEp)
121 + .withType(type)
122 + .withPayload(payload)
123 + .build();
124 + sendAsync(ep, message);
125 + return futureResponse;
126 + }
127 +
128 + @Override
129 + public void registerHandler(String type, MessageHandler handler) {
130 + // TODO: Is this the right semantics for handler registration?
131 + handlers.putIfAbsent(type, handler);
132 + }
133 +
134 + public void unregisterHandler(String type) {
135 + handlers.remove(type);
136 + }
137 +
138 + private MessageHandler getMessageHandler(String type) {
139 + return handlers.get(type);
140 + }
141 +
142 + private void startAcceptingConnections() throws InterruptedException {
143 + ServerBootstrap b = new ServerBootstrap();
144 + b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
145 + b.group(bossGroup, workerGroup)
146 + .channel(NioServerSocketChannel.class)
147 + .childHandler(new OnosCommunicationChannelInitializer())
148 + .option(ChannelOption.SO_BACKLOG, 128)
149 + .childOption(ChannelOption.SO_KEEPALIVE, true);
150 +
151 + // Bind and start to accept incoming connections.
152 + b.bind(port).sync();
153 + }
154 +
155 + private class OnosCommunicationChannelFactory
156 + implements KeyedPoolableObjectFactory<Endpoint, Channel> {
157 +
158 + @Override
159 + public void activateObject(Endpoint endpoint, Channel channel)
160 + throws Exception {
161 + }
162 +
163 + @Override
164 + public void destroyObject(Endpoint ep, Channel channel) throws Exception {
165 + channel.close();
166 + }
167 +
168 + @Override
169 + public Channel makeObject(Endpoint ep) throws Exception {
170 + Bootstrap b = new Bootstrap();
171 + b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
172 + b.group(workerGroup);
173 + // TODO: Make this faster:
174 + // http://normanmaurer.me/presentations/2014-facebook-eng-netty/slides.html#37.0
175 + b.channel(NioSocketChannel.class);
176 + b.option(ChannelOption.SO_KEEPALIVE, true);
177 + b.handler(new OnosCommunicationChannelInitializer());
178 +
179 + // Start the client.
180 + ChannelFuture f = b.connect(ep.host(), ep.port()).sync();
181 + return f.channel();
182 + }
183 +
184 + @Override
185 + public void passivateObject(Endpoint ep, Channel channel)
186 + throws Exception {
187 + }
188 +
189 + @Override
190 + public boolean validateObject(Endpoint ep, Channel channel) {
191 + return channel.isOpen();
192 + }
193 + }
194 +
195 + private class OnosCommunicationChannelInitializer extends ChannelInitializer<SocketChannel> {
196 +
197 + @Override
198 + protected void initChannel(SocketChannel channel) throws Exception {
199 + channel.pipeline()
200 + .addLast(new MessageEncoder(serializer))
201 + .addLast(new MessageDecoder(NettyMessagingService.this, serializer))
202 + .addLast(new NettyMessagingService.InboundMessageDispatcher());
203 + }
204 + }
205 +
206 + private class WriteTask implements Runnable {
207 +
208 + private final Object message;
209 + private final Channel channel;
210 +
211 + public WriteTask(Channel channel, Object message) {
212 + this.message = message;
213 + this.channel = channel;
214 + }
215 +
216 + @Override
217 + public void run() {
218 + channel.writeAndFlush(message);
219 + }
220 + }
221 +
222 + private class InboundMessageDispatcher extends SimpleChannelInboundHandler<InternalMessage> {
223 +
224 + @Override
225 + protected void channelRead0(ChannelHandlerContext ctx, InternalMessage message) throws Exception {
226 + String type = message.type();
227 + if (type.equals(InternalMessage.REPLY_MESSAGE_TYPE)) {
228 + try {
229 + AsyncResponse<?> futureResponse =
230 + NettyMessagingService.this.responseFutures.getIfPresent(message.id());
231 + if (futureResponse != null) {
232 + futureResponse.setResponse(message.payload());
233 + }
234 + log.warn("Received a reply. But was unable to locate the request handle");
235 + } finally {
236 + NettyMessagingService.this.responseFutures.invalidate(message.id());
237 + }
238 + return;
239 + }
240 + MessageHandler handler = NettyMessagingService.this.getMessageHandler(type);
241 + handler.handle(message);
242 + }
243 + }
244 +}
1 +package org.onlab.netty;
2 +
3 +import java.util.concurrent.TimeUnit;
4 +import java.util.concurrent.TimeoutException;
5 +
6 +/**
7 + * Response object returned when making synchronous requests.
8 + * Can you used to check is a response is ready and/or wait for a response
9 + * to become available.
10 + *
11 + * @param <T> type of response.
12 + */
13 +public interface Response<T> {
14 +
15 + /**
16 + * Gets the response waiting for a designated timeout period.
17 + * @param timeout timeout period (since request was sent out)
18 + * @param tu unit of time.
19 + * @return response
20 + * @throws TimeoutException if the timeout expires before the response arrives.
21 + */
22 + public T get(long timeout, TimeUnit tu) throws TimeoutException;
23 +
24 + /**
25 + * Gets the response waiting for indefinite timeout period.
26 + * @return response
27 + * @throws InterruptedException if the thread is interrupted before the response arrives.
28 + */
29 + public T get() throws InterruptedException;
30 +
31 + /**
32 + * Checks if the response is ready without blocking.
33 + * @return true if response is ready, false otherwise.
34 + */
35 + public boolean isReady();
36 +}
1 +package org.onlab.netty;
2 +
3 +/**
4 + * Interface for encoding/decoding message payloads.
5 + */
6 +public interface Serializer {
7 +
8 + /**
9 + * Decodes the specified byte array to a POJO.
10 + *
11 + * @param data byte array.
12 + * @return POJO
13 + */
14 + Object decode(byte[] data);
15 +
16 + /**
17 + * Encodes the specified POJO into a byte array.
18 + *
19 + * @param data POJO to be encoded
20 + * @return byte array.
21 + */
22 + byte[] encode(Object message);
23 +
24 +}
1 +package org.onlab.netty;
2 +
3 +import java.util.concurrent.TimeUnit;
4 +
5 +public final class SimpleClient {
6 + private SimpleClient() {}
7 +
8 + public static void main(String... args) throws Exception {
9 + NettyMessagingService messaging = new TestNettyMessagingService(9081);
10 + messaging.activate();
11 +
12 + messaging.sendAsync(new Endpoint("localhost", 8080), "simple", "Hello World");
13 + Response<String> response = messaging.sendAndReceive(new Endpoint("localhost", 8080), "echo", "Hello World");
14 + System.out.println("Got back:" + response.get(2, TimeUnit.SECONDS));
15 + }
16 +
17 + public static class TestNettyMessagingService extends NettyMessagingService {
18 + public TestNettyMessagingService(int port) throws Exception {
19 + super(port);
20 + Serializer serializer = new KryoSerializer();
21 + this.serializer = serializer;
22 + }
23 + }
24 +}
1 +package org.onlab.netty;
2 +
3 +public final class SimpleServer {
4 + private SimpleServer() {}
5 +
6 + public static void main(String... args) throws Exception {
7 + NettyMessagingService server = new TestNettyMessagingService();
8 + server.activate();
9 + server.registerHandler("simple", new LoggingHandler());
10 + server.registerHandler("echo", new EchoHandler());
11 + }
12 +
13 + public static class TestNettyMessagingService extends NettyMessagingService {
14 + protected TestNettyMessagingService() {
15 + Serializer serializer = new KryoSerializer();
16 + this.serializer = serializer;
17 + }
18 + }
19 +}
1 +/**
2 + * Asynchronous messaging APIs implemented using the Netty framework.
3 + */
4 +package org.onlab.netty;
...\ No newline at end of file ...\ No newline at end of file