Praseed Balakrishnan

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

Showing 94 changed files with 3398 additions and 845 deletions
...@@ -5,8 +5,6 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -5,8 +5,6 @@ import static org.slf4j.LoggerFactory.getLogger;
5 import java.util.LinkedList; 5 import java.util.LinkedList;
6 import java.util.List; 6 import java.util.List;
7 7
8 -import com.codahale.metrics.Gauge;
9 -import com.codahale.metrics.Meter;
10 import com.google.common.collect.ImmutableList; 8 import com.google.common.collect.ImmutableList;
11 import org.apache.felix.scr.annotations.Activate; 9 import org.apache.felix.scr.annotations.Activate;
12 import org.apache.felix.scr.annotations.Component; 10 import org.apache.felix.scr.annotations.Component;
...@@ -14,8 +12,7 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -14,8 +12,7 @@ import org.apache.felix.scr.annotations.Deactivate;
14 import org.apache.felix.scr.annotations.Reference; 12 import org.apache.felix.scr.annotations.Reference;
15 import org.apache.felix.scr.annotations.ReferenceCardinality; 13 import org.apache.felix.scr.annotations.ReferenceCardinality;
16 import org.apache.felix.scr.annotations.Service; 14 import org.apache.felix.scr.annotations.Service;
17 -import org.onlab.metrics.MetricsComponent; 15 +import org.onlab.metrics.EventMetric;
18 -import org.onlab.metrics.MetricsFeature;
19 import org.onlab.metrics.MetricsService; 16 import org.onlab.metrics.MetricsService;
20 import org.onlab.onos.net.intent.IntentEvent; 17 import org.onlab.onos.net.intent.IntentEvent;
21 import org.onlab.onos.net.intent.IntentListener; 18 import org.onlab.onos.net.intent.IntentListener;
...@@ -33,56 +30,32 @@ public class IntentMetrics implements IntentMetricsService, ...@@ -33,56 +30,32 @@ public class IntentMetrics implements IntentMetricsService,
33 30
34 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 31 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
35 protected IntentService intentService; 32 protected IntentService intentService;
33 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
34 + protected MetricsService metricsService;
35 +
36 private LinkedList<IntentEvent> lastEvents = new LinkedList<>(); 36 private LinkedList<IntentEvent> lastEvents = new LinkedList<>();
37 private static final int LAST_EVENTS_MAX_N = 100; 37 private static final int LAST_EVENTS_MAX_N = 100;
38 38
39 // 39 //
40 // Metrics 40 // Metrics
41 // 41 //
42 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
43 - protected MetricsService metricsService;
44 - //
45 private static final String COMPONENT_NAME = "Intent"; 42 private static final String COMPONENT_NAME = "Intent";
46 private static final String FEATURE_SUBMITTED_NAME = "Submitted"; 43 private static final String FEATURE_SUBMITTED_NAME = "Submitted";
47 private static final String FEATURE_INSTALLED_NAME = "Installed"; 44 private static final String FEATURE_INSTALLED_NAME = "Installed";
48 private static final String FEATURE_WITHDRAW_REQUESTED_NAME = 45 private static final String FEATURE_WITHDRAW_REQUESTED_NAME =
49 "WithdrawRequested"; 46 "WithdrawRequested";
50 private static final String FEATURE_WITHDRAWN_NAME = "Withdrawn"; 47 private static final String FEATURE_WITHDRAWN_NAME = "Withdrawn";
51 - private static final String GAUGE_TIMESTAMP_NAME = "Timestamp.EpochMs";
52 - private static final String METER_RATE_NAME = "Rate";
53 // 48 //
54 - private MetricsComponent metricsComponent; 49 + // Event metrics:
55 - private MetricsFeature metricsFeatureSubmitted; 50 + // - Intent Submitted API operation
56 - private MetricsFeature metricsFeatureInstalled; 51 + // - Intent Installed operation completion
57 - private MetricsFeature metricsFeatureWithdrawRequested; 52 + // - Intent Withdraw Requested API operation
58 - private MetricsFeature metricsFeatureWithdrawn; 53 + // - Intent Withdrawn operation completion
59 // 54 //
60 - // Timestamps: 55 + private EventMetric intentSubmittedEventMetric;
61 - // - Intent Submitted API operation (ms from the Epoch) 56 + private EventMetric intentInstalledEventMetric;
62 - // - Intent Installed operation completion (ms from the Epoch) 57 + private EventMetric intentWithdrawRequestedEventMetric;
63 - // - Intent Withdraw Requested API operation (ms from the Epoch) 58 + private EventMetric intentWithdrawnEventMetric;
64 - // - Intent Withdrawn operation completion (ms from the Epoch)
65 - //
66 - private volatile long intentSubmittedTimestampEpochMs = 0;
67 - private volatile long intentInstalledTimestampEpochMs = 0;
68 - private volatile long intentWithdrawRequestedTimestampEpochMs = 0;
69 - private volatile long intentWithdrawnTimestampEpochMs = 0;
70 - //
71 - private Gauge<Long> intentSubmittedTimestampEpochMsGauge;
72 - private Gauge<Long> intentInstalledTimestampEpochMsGauge;
73 - private Gauge<Long> intentWithdrawRequestedTimestampEpochMsGauge;
74 - private Gauge<Long> intentWithdrawnTimestampEpochMsGauge;
75 - //
76 - // Rate meters:
77 - // - Rate of the Submitted Intent API operations
78 - // - Rate of the Installed Intent operations
79 - // - Rate of the Withdrawn Requested Intent API operations
80 - // - Rate of the Withdrawn Intent operations
81 - //
82 - private Meter intentSubmittedRateMeter;
83 - private Meter intentInstalledRateMeter;
84 - private Meter intentWithdrawRequestedRateMeter;
85 - private Meter intentWithdrawnRateMeter;
86 59
87 @Activate 60 @Activate
88 protected void activate() { 61 protected void activate() {
...@@ -108,43 +81,23 @@ public class IntentMetrics implements IntentMetricsService, ...@@ -108,43 +81,23 @@ public class IntentMetrics implements IntentMetricsService,
108 } 81 }
109 82
110 @Override 83 @Override
111 - public Gauge<Long> intentSubmittedTimestampEpochMsGauge() { 84 + public EventMetric intentSubmittedEventMetric() {
112 - return intentSubmittedTimestampEpochMsGauge; 85 + return intentSubmittedEventMetric;
113 - }
114 -
115 - @Override
116 - public Gauge<Long> intentInstalledTimestampEpochMsGauge() {
117 - return intentInstalledTimestampEpochMsGauge;
118 - }
119 -
120 - @Override
121 - public Gauge<Long> intentWithdrawRequestedTimestampEpochMsGauge() {
122 - return intentWithdrawRequestedTimestampEpochMsGauge;
123 - }
124 -
125 - @Override
126 - public Gauge<Long> intentWithdrawnTimestampEpochMsGauge() {
127 - return intentWithdrawnTimestampEpochMsGauge;
128 - }
129 -
130 - @Override
131 - public Meter intentSubmittedRateMeter() {
132 - return intentSubmittedRateMeter;
133 } 86 }
134 87
135 @Override 88 @Override
136 - public Meter intentInstalledRateMeter() { 89 + public EventMetric intentInstalledEventMetric() {
137 - return intentInstalledRateMeter; 90 + return intentInstalledEventMetric;
138 } 91 }
139 92
140 @Override 93 @Override
141 - public Meter intentWithdrawRequestedRateMeter() { 94 + public EventMetric intentWithdrawRequestedEventMetric() {
142 - return intentWithdrawRequestedRateMeter; 95 + return intentWithdrawRequestedEventMetric;
143 } 96 }
144 97
145 @Override 98 @Override
146 - public Meter intentWithdrawnRateMeter() { 99 + public EventMetric intentWithdrawnEventMetric() {
147 - return intentWithdrawnRateMeter; 100 + return intentWithdrawnEventMetric;
148 } 101 }
149 102
150 @Override 103 @Override
...@@ -156,26 +109,21 @@ public class IntentMetrics implements IntentMetricsService, ...@@ -156,26 +109,21 @@ public class IntentMetrics implements IntentMetricsService,
156 // 109 //
157 switch (event.type()) { 110 switch (event.type()) {
158 case SUBMITTED: 111 case SUBMITTED:
159 - intentSubmittedTimestampEpochMs = System.currentTimeMillis(); 112 + intentSubmittedEventMetric.eventReceived();
160 - intentSubmittedRateMeter.mark(1);
161 break; 113 break;
162 case INSTALLED: 114 case INSTALLED:
163 - intentInstalledTimestampEpochMs = System.currentTimeMillis(); 115 + intentInstalledEventMetric.eventReceived();
164 - intentInstalledRateMeter.mark(1);
165 break; 116 break;
166 case FAILED: 117 case FAILED:
167 // TODO: Just ignore? 118 // TODO: Just ignore?
168 break; 119 break;
169 /* 120 /*
170 case WITHDRAW_REQUESTED: 121 case WITHDRAW_REQUESTED:
171 - intentWithdrawRequestedTimestampEpochMs = 122 + intentWithdrawRequestedEventMetric.eventReceived();
172 - System.currentTimeMillis();
173 - intentWithdrawRequestedRateMeter.mark(1);
174 break; 123 break;
175 */ 124 */
176 case WITHDRAWN: 125 case WITHDRAWN:
177 - intentWithdrawnTimestampEpochMs = System.currentTimeMillis(); 126 + intentWithdrawnEventMetric.eventReceived();
178 - intentWithdrawnRateMeter.mark(1);
179 break; 127 break;
180 default: 128 default:
181 break; 129 break;
...@@ -199,10 +147,6 @@ public class IntentMetrics implements IntentMetricsService, ...@@ -199,10 +147,6 @@ public class IntentMetrics implements IntentMetricsService,
199 */ 147 */
200 private void clear() { 148 private void clear() {
201 synchronized (lastEvents) { 149 synchronized (lastEvents) {
202 - intentSubmittedTimestampEpochMs = 0;
203 - intentInstalledTimestampEpochMs = 0;
204 - intentWithdrawRequestedTimestampEpochMs = 0;
205 - intentWithdrawnTimestampEpochMs = 0;
206 lastEvents.clear(); 150 lastEvents.clear();
207 } 151 }
208 } 152 }
...@@ -211,109 +155,32 @@ public class IntentMetrics implements IntentMetricsService, ...@@ -211,109 +155,32 @@ public class IntentMetrics implements IntentMetricsService,
211 * Registers the metrics. 155 * Registers the metrics.
212 */ 156 */
213 private void registerMetrics() { 157 private void registerMetrics() {
214 - metricsComponent = metricsService.registerComponent(COMPONENT_NAME); 158 + intentSubmittedEventMetric =
215 - // 159 + new EventMetric(metricsService, COMPONENT_NAME,
216 - metricsFeatureSubmitted = 160 + FEATURE_SUBMITTED_NAME);
217 - metricsComponent.registerFeature(FEATURE_SUBMITTED_NAME); 161 + intentInstalledEventMetric =
218 - metricsFeatureInstalled = 162 + new EventMetric(metricsService, COMPONENT_NAME,
219 - metricsComponent.registerFeature(FEATURE_INSTALLED_NAME); 163 + FEATURE_INSTALLED_NAME);
220 - metricsFeatureWithdrawRequested = 164 + intentWithdrawRequestedEventMetric =
221 - metricsComponent.registerFeature(FEATURE_WITHDRAW_REQUESTED_NAME); 165 + new EventMetric(metricsService, COMPONENT_NAME,
222 - metricsFeatureWithdrawn = 166 + FEATURE_WITHDRAW_REQUESTED_NAME);
223 - metricsComponent.registerFeature(FEATURE_WITHDRAWN_NAME); 167 + intentWithdrawnEventMetric =
224 - // 168 + new EventMetric(metricsService, COMPONENT_NAME,
225 - intentSubmittedTimestampEpochMsGauge = 169 + FEATURE_WITHDRAWN_NAME);
226 - metricsService.registerMetric(metricsComponent, 170 +
227 - metricsFeatureSubmitted, 171 + intentSubmittedEventMetric.registerMetrics();
228 - GAUGE_TIMESTAMP_NAME, 172 + intentInstalledEventMetric.registerMetrics();
229 - new Gauge<Long>() { 173 + intentWithdrawRequestedEventMetric.registerMetrics();
230 - @Override 174 + intentWithdrawnEventMetric.registerMetrics();
231 - public Long getValue() {
232 - return intentSubmittedTimestampEpochMs;
233 - }
234 - });
235 - //
236 - intentInstalledTimestampEpochMsGauge =
237 - metricsService.registerMetric(metricsComponent,
238 - metricsFeatureInstalled,
239 - GAUGE_TIMESTAMP_NAME,
240 - new Gauge<Long>() {
241 - @Override
242 - public Long getValue() {
243 - return intentInstalledTimestampEpochMs;
244 - }
245 - });
246 - //
247 - intentWithdrawRequestedTimestampEpochMsGauge =
248 - metricsService.registerMetric(metricsComponent,
249 - metricsFeatureWithdrawRequested,
250 - GAUGE_TIMESTAMP_NAME,
251 - new Gauge<Long>() {
252 - @Override
253 - public Long getValue() {
254 - return intentWithdrawRequestedTimestampEpochMs;
255 - }
256 - });
257 - //
258 - intentWithdrawnTimestampEpochMsGauge =
259 - metricsService.registerMetric(metricsComponent,
260 - metricsFeatureWithdrawn,
261 - GAUGE_TIMESTAMP_NAME,
262 - new Gauge<Long>() {
263 - @Override
264 - public Long getValue() {
265 - return intentWithdrawnTimestampEpochMs;
266 - }
267 - });
268 - //
269 - intentSubmittedRateMeter =
270 - metricsService.createMeter(metricsComponent,
271 - metricsFeatureSubmitted,
272 - METER_RATE_NAME);
273 - //
274 - intentInstalledRateMeter =
275 - metricsService.createMeter(metricsComponent,
276 - metricsFeatureInstalled,
277 - METER_RATE_NAME);
278 - //
279 - intentWithdrawRequestedRateMeter =
280 - metricsService.createMeter(metricsComponent,
281 - metricsFeatureWithdrawRequested,
282 - METER_RATE_NAME);
283 - //
284 - intentWithdrawnRateMeter =
285 - metricsService.createMeter(metricsComponent,
286 - metricsFeatureWithdrawn,
287 - METER_RATE_NAME);
288 } 175 }
289 176
290 /** 177 /**
291 * Removes the metrics. 178 * Removes the metrics.
292 */ 179 */
293 private void removeMetrics() { 180 private void removeMetrics() {
294 - metricsService.removeMetric(metricsComponent, 181 + intentSubmittedEventMetric.removeMetrics();
295 - metricsFeatureSubmitted, 182 + intentInstalledEventMetric.removeMetrics();
296 - GAUGE_TIMESTAMP_NAME); 183 + intentWithdrawRequestedEventMetric.removeMetrics();
297 - metricsService.removeMetric(metricsComponent, 184 + intentWithdrawnEventMetric.removeMetrics();
298 - metricsFeatureInstalled,
299 - GAUGE_TIMESTAMP_NAME);
300 - metricsService.removeMetric(metricsComponent,
301 - metricsFeatureWithdrawRequested,
302 - GAUGE_TIMESTAMP_NAME);
303 - metricsService.removeMetric(metricsComponent,
304 - metricsFeatureWithdrawn,
305 - GAUGE_TIMESTAMP_NAME);
306 - metricsService.removeMetric(metricsComponent,
307 - metricsFeatureSubmitted,
308 - METER_RATE_NAME);
309 - metricsService.removeMetric(metricsComponent,
310 - metricsFeatureInstalled,
311 - METER_RATE_NAME);
312 - metricsService.removeMetric(metricsComponent,
313 - metricsFeatureWithdrawRequested,
314 - METER_RATE_NAME);
315 - metricsService.removeMetric(metricsComponent,
316 - metricsFeatureWithdrawn,
317 - METER_RATE_NAME);
318 } 185 }
319 } 186 }
......
1 package org.onlab.onos.metrics.intent; 1 package org.onlab.onos.metrics.intent;
2 2
3 import java.util.List; 3 import java.util.List;
4 - 4 +import org.onlab.metrics.EventMetric;
5 -import com.codahale.metrics.Gauge;
6 -import com.codahale.metrics.Meter;
7 import org.onlab.onos.net.intent.IntentEvent; 5 import org.onlab.onos.net.intent.IntentEvent;
8 6
9 /** 7 /**
...@@ -18,68 +16,32 @@ public interface IntentMetricsService { ...@@ -18,68 +16,32 @@ public interface IntentMetricsService {
18 public List<IntentEvent> getEvents(); 16 public List<IntentEvent> getEvents();
19 17
20 /** 18 /**
21 - * Gets the Metrics' Gauge for the intent SUBMITTED event timestamp 19 + * Gets the Event Metric for the intent SUBMITTED events.
22 - * (ms from the epoch).
23 * 20 *
24 - * @return the Metrics' Gauge for the intent SUBMITTED event timestamp 21 + * @return the Event Metric for the intent SUBMITTED events.
25 - * (ms from the epoch)
26 */ 22 */
27 - public Gauge<Long> intentSubmittedTimestampEpochMsGauge(); 23 + public EventMetric intentSubmittedEventMetric();
28 24
29 /** 25 /**
30 - * Gets the Metrics' Gauge for the intent INSTALLED event timestamp 26 + * Gets the Event Metric for the intent INSTALLED events.
31 - * (ms from the epoch).
32 * 27 *
33 - * @return the Metrics' Gauge for the intent INSTALLED event timestamp 28 + * @return the Event Metric for the intent INSTALLED events.
34 - * (ms from the epoch)
35 */ 29 */
36 - public Gauge<Long> intentInstalledTimestampEpochMsGauge(); 30 + public EventMetric intentInstalledEventMetric();
37 31
38 /** 32 /**
39 - * Gets the Metrics' Gauge for the intent WITHDRAW_REQUESTED event 33 + * Gets the Event Metric for the intent WITHDRAW_REQUESTED events.
40 - * timestamp (ms from the epoch).
41 * 34 *
42 * TODO: This intent event is not implemented yet. 35 * TODO: This intent event is not implemented yet.
43 * 36 *
44 - * @return the Metrics' Gauge for the intent WITHDRAW_REQUESTED event 37 + * @return the Event Metric for the intent WITHDRAW_REQUESTED events.
45 - * timestamp (ms from the epoch)
46 - */
47 - public Gauge<Long> intentWithdrawRequestedTimestampEpochMsGauge();
48 -
49 - /**
50 - * Gets the Metrics' Gauge for the intent WITHDRAWN event timestamp
51 - * (ms from the epoch).
52 - *
53 - * @return the Metrics' Gauge for the intent WITHDRAWN event timestamp
54 - * (ms from the epoch)
55 - */
56 - public Gauge<Long> intentWithdrawnTimestampEpochMsGauge();
57 -
58 - /**
59 - * Gets the Metrics' Meter for the submitted intents event rate.
60 - *
61 - * @return the Metrics' Meter for the submitted intents event rate
62 - */
63 - public Meter intentSubmittedRateMeter();
64 -
65 - /**
66 - * Gets the Metrics' Meter for the installed intents event rate.
67 - *
68 - * @return the Metrics' Meter for the installed intent event rate
69 - */
70 - public Meter intentInstalledRateMeter();
71 -
72 - /**
73 - * Gets the Metrics' Meter for the withdraw requested intents event rate.
74 - *
75 - * @return the Metrics' Meter for the withdraw requested intents event rate
76 */ 38 */
77 - public Meter intentWithdrawRequestedRateMeter(); 39 + public EventMetric intentWithdrawRequestedEventMetric();
78 40
79 /** 41 /**
80 - * Gets the Metrics' Meter for the withdraw completed intents event rate. 42 + * Gets the Event Metric for the intent WITHDRAWN events.
81 * 43 *
82 - * @return the Metrics' Meter for the withdraw completed intents event rate 44 + * @return the Event Metric for the intent WITHDRAWN events.
83 */ 45 */
84 - public Meter intentWithdrawnRateMeter(); 46 + public EventMetric intentWithdrawnEventMetric();
85 } 47 }
......
...@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode; ...@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode;
11 import com.fasterxml.jackson.databind.ObjectMapper; 11 import com.fasterxml.jackson.databind.ObjectMapper;
12 import com.fasterxml.jackson.databind.node.ObjectNode; 12 import com.fasterxml.jackson.databind.node.ObjectNode;
13 import org.apache.karaf.shell.commands.Command; 13 import org.apache.karaf.shell.commands.Command;
14 +import org.onlab.metrics.EventMetric;
14 import org.onlab.onos.cli.AbstractShellCommand; 15 import org.onlab.onos.cli.AbstractShellCommand;
15 import org.onlab.onos.metrics.intent.IntentMetricsService; 16 import org.onlab.onos.metrics.intent.IntentMetricsService;
16 17
...@@ -29,8 +30,6 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand { ...@@ -29,8 +30,6 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
29 @Override 30 @Override
30 protected void execute() { 31 protected void execute() {
31 IntentMetricsService service = get(IntentMetricsService.class); 32 IntentMetricsService service = get(IntentMetricsService.class);
32 - Gauge<Long> gauge;
33 - Meter meter;
34 33
35 if (outputJson()) { 34 if (outputJson()) {
36 ObjectMapper mapper = new ObjectMapper() 35 ObjectMapper mapper = new ObjectMapper()
...@@ -38,49 +37,49 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand { ...@@ -38,49 +37,49 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
38 TimeUnit.MILLISECONDS, 37 TimeUnit.MILLISECONDS,
39 false)); 38 false));
40 ObjectNode result = mapper.createObjectNode(); 39 ObjectNode result = mapper.createObjectNode();
41 - // 40 + result = json(mapper, result, "intentSubmitted",
42 - gauge = service.intentSubmittedTimestampEpochMsGauge(); 41 + service.intentSubmittedEventMetric());
43 - result.put("intentSubmittedTimestamp", json(mapper, gauge)); 42 + result = json(mapper, result, "intentInstalled",
44 - gauge = service.intentInstalledTimestampEpochMsGauge(); 43 + service.intentInstalledEventMetric());
45 - result.put("intentInstalledTimestamp", json(mapper, gauge)); 44 + result = json(mapper, result, "intentWithdrawRequested",
46 - gauge = service.intentWithdrawRequestedTimestampEpochMsGauge(); 45 + service.intentWithdrawRequestedEventMetric());
47 - result.put("intentWithdrawRequestedTimestamp", 46 + result = json(mapper, result, "intentWithdrawn",
48 - json(mapper, gauge)); 47 + service.intentWithdrawnEventMetric());
49 - gauge = service.intentWithdrawnTimestampEpochMsGauge();
50 - result.put("intentWithdrawnTimestamp", json(mapper, gauge));
51 - //
52 - meter = service.intentSubmittedRateMeter();
53 - result.put("intentSubmittedRate", json(mapper, meter));
54 - meter = service.intentInstalledRateMeter();
55 - result.put("intentInstalledRate", json(mapper, meter));
56 - meter = service.intentWithdrawRequestedRateMeter();
57 - result.put("intentWithdrawRequestedRate", json(mapper, meter));
58 - meter = service.intentWithdrawnRateMeter();
59 - result.put("intentWithdrawnRate", json(mapper, meter));
60 - //
61 print("%s", result); 48 print("%s", result);
62 } else { 49 } else {
63 - gauge = service.intentSubmittedTimestampEpochMsGauge(); 50 + printEventMetric("Submitted",
64 - printGauge("Submitted", gauge); 51 + service.intentSubmittedEventMetric());
65 - gauge = service.intentInstalledTimestampEpochMsGauge(); 52 + printEventMetric("Installed",
66 - printGauge("Installed", gauge); 53 + service.intentInstalledEventMetric());
67 - gauge = service.intentWithdrawRequestedTimestampEpochMsGauge(); 54 + printEventMetric("Withdraw Requested",
68 - printGauge("Withdraw Requested", gauge); 55 + service.intentWithdrawRequestedEventMetric());
69 - gauge = service.intentWithdrawnTimestampEpochMsGauge(); 56 + printEventMetric("Withdrawn",
70 - printGauge("Withdrawn", gauge); 57 + service.intentWithdrawnEventMetric());
71 - //
72 - meter = service.intentSubmittedRateMeter();
73 - printMeter("Submitted", meter);
74 - meter = service.intentInstalledRateMeter();
75 - printMeter("Installed", meter);
76 - meter = service.intentWithdrawRequestedRateMeter();
77 - printMeter("Withdraw Requested", meter);
78 - meter = service.intentWithdrawnRateMeter();
79 - printMeter("Withdrawn", meter);
80 } 58 }
81 } 59 }
82 60
83 /** 61 /**
62 + * Produces JSON node for an Event Metric.
63 + *
64 + * @param mapper the JSON object mapper to use
65 + * @param objectNode the JSON object node to use
66 + * @param propertyPrefix the property prefix to use
67 + * @param eventMetric the Event Metric with the data
68 + * @return JSON object node for the Event Metric
69 + */
70 + private ObjectNode json(ObjectMapper mapper, ObjectNode objectNode,
71 + String propertyPrefix, EventMetric eventMetric) {
72 + String gaugeName = propertyPrefix + "Timestamp";
73 + String meterName = propertyPrefix + "Rate";
74 + Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
75 + Meter meter = eventMetric.eventRateMeter();
76 +
77 + objectNode.put(gaugeName, json(mapper, gauge));
78 + objectNode.put(meterName, json(mapper, meter));
79 + return objectNode;
80 + }
81 +
82 + /**
84 * Produces JSON node for an Object. 83 * Produces JSON node for an Object.
85 * 84 *
86 * @param mapper the JSON object mapper to use 85 * @param mapper the JSON object mapper to use
...@@ -94,8 +93,8 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand { ...@@ -94,8 +93,8 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
94 // 93 //
95 try { 94 try {
96 final String objectJson = mapper.writeValueAsString(object); 95 final String objectJson = mapper.writeValueAsString(object);
97 - JsonNode objectNode = mapper.readTree(objectJson); 96 + JsonNode jsonNode = mapper.readTree(objectJson);
98 - return objectNode; 97 + return jsonNode;
99 } catch (JsonProcessingException e) { 98 } catch (JsonProcessingException e) {
100 log.error("Error writing value as JSON string", e); 99 log.error("Error writing value as JSON string", e);
101 } catch (IOException e) { 100 } catch (IOException e) {
...@@ -105,28 +104,26 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand { ...@@ -105,28 +104,26 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
105 } 104 }
106 105
107 /** 106 /**
108 - * Prints a Gauge. 107 + * Prints an Event Metric.
109 * 108 *
110 * @param operationStr the string with the intent operation to print 109 * @param operationStr the string with the intent operation to print
111 - * @param gauge the Gauge to print 110 + * @param eventMetric the Event Metric to print
112 */ 111 */
113 - private void printGauge(String operationStr, Gauge<Long> gauge) { 112 + private void printEventMetric(String operationStr,
113 + EventMetric eventMetric) {
114 + Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
115 + Meter meter = eventMetric.eventRateMeter();
116 + TimeUnit rateUnit = TimeUnit.SECONDS;
117 + double rateFactor = rateUnit.toSeconds(1);
118 +
119 + // Print the Gauge
114 print(FORMAT_GAUGE, operationStr, gauge.getValue()); 120 print(FORMAT_GAUGE, operationStr, gauge.getValue());
115 - }
116 121
117 - /** 122 + // Print the Meter
118 - * Prints a Meter. 123 + print(FORMAT_METER, operationStr, meter.getCount(),
119 - * 124 + meter.getMeanRate() * rateFactor,
120 - * @param operationStr the string with the intent operation to print 125 + meter.getOneMinuteRate() * rateFactor,
121 - * @param meter the Meter to print 126 + meter.getFiveMinuteRate() * rateFactor,
122 - */ 127 + meter.getFifteenMinuteRate() * rateFactor);
123 - private void printMeter(String operationStr, Meter meter) {
124 - TimeUnit rateUnit = TimeUnit.SECONDS;
125 - double rateFactor = rateUnit.toSeconds(1);
126 - print(FORMAT_METER, operationStr, meter.getCount(),
127 - meter.getMeanRate() * rateFactor,
128 - meter.getOneMinuteRate() * rateFactor,
129 - meter.getFiveMinuteRate() * rateFactor,
130 - meter.getFifteenMinuteRate() * rateFactor);
131 } 128 }
132 } 129 }
......
...@@ -5,8 +5,6 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -5,8 +5,6 @@ import static org.slf4j.LoggerFactory.getLogger;
5 import java.util.LinkedList; 5 import java.util.LinkedList;
6 import java.util.List; 6 import java.util.List;
7 7
8 -import com.codahale.metrics.Gauge;
9 -import com.codahale.metrics.Meter;
10 import com.google.common.collect.ImmutableList; 8 import com.google.common.collect.ImmutableList;
11 import org.apache.felix.scr.annotations.Activate; 9 import org.apache.felix.scr.annotations.Activate;
12 import org.apache.felix.scr.annotations.Component; 10 import org.apache.felix.scr.annotations.Component;
...@@ -14,8 +12,7 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -14,8 +12,7 @@ import org.apache.felix.scr.annotations.Deactivate;
14 import org.apache.felix.scr.annotations.Reference; 12 import org.apache.felix.scr.annotations.Reference;
15 import org.apache.felix.scr.annotations.ReferenceCardinality; 13 import org.apache.felix.scr.annotations.ReferenceCardinality;
16 import org.apache.felix.scr.annotations.Service; 14 import org.apache.felix.scr.annotations.Service;
17 -import org.onlab.metrics.MetricsComponent; 15 +import org.onlab.metrics.EventMetric;
18 -import org.onlab.metrics.MetricsFeature;
19 import org.onlab.metrics.MetricsService; 16 import org.onlab.metrics.MetricsService;
20 import org.onlab.onos.event.Event; 17 import org.onlab.onos.event.Event;
21 import org.onlab.onos.net.device.DeviceEvent; 18 import org.onlab.onos.net.device.DeviceEvent;
...@@ -48,6 +45,8 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -48,6 +45,8 @@ public class TopologyMetrics implements TopologyMetricsService {
48 protected LinkService linkService; 45 protected LinkService linkService;
49 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 46 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 protected TopologyService topologyService; 47 protected TopologyService topologyService;
48 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
49 + protected MetricsService metricsService;
51 50
52 private LinkedList<Event> lastEvents = new LinkedList<>(); 51 private LinkedList<Event> lastEvents = new LinkedList<>();
53 private static final int LAST_EVENTS_MAX_N = 100; 52 private static final int LAST_EVENTS_MAX_N = 100;
...@@ -61,22 +60,22 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -61,22 +60,22 @@ public class TopologyMetrics implements TopologyMetricsService {
61 // 60 //
62 // Metrics 61 // Metrics
63 // 62 //
64 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 - protected MetricsService metricsService;
66 - //
67 private static final String COMPONENT_NAME = "Topology"; 63 private static final String COMPONENT_NAME = "Topology";
68 - private static final String FEATURE_NAME = "EventNotification"; 64 + private static final String FEATURE_DEVICE_NAME = "DeviceEvent";
69 - private static final String GAUGE_NAME = "LastEventTimestamp.EpochMs"; 65 + private static final String FEATURE_HOST_NAME = "HostEvent";
70 - private static final String METER_NAME = "EventRate"; 66 + private static final String FEATURE_LINK_NAME = "LinkEvent";
67 + private static final String FEATURE_GRAPH_NAME = "GraphEvent";
71 // 68 //
72 - private MetricsComponent metricsComponent; 69 + // Event metrics:
73 - private MetricsFeature metricsFeatureEventNotification; 70 + // - Device events
71 + // - Host events
72 + // - Link events
73 + // - Topology Graph events
74 // 74 //
75 - // Timestamp of the last Topology event (ms from the Epoch) 75 + private EventMetric topologyDeviceEventMetric;
76 - private volatile long lastEventTimestampEpochMs = 0; 76 + private EventMetric topologyHostEventMetric;
77 - private Gauge<Long> lastEventTimestampEpochMsGauge; 77 + private EventMetric topologyLinkEventMetric;
78 - // Rate of the Topology events published to the Topology listeners 78 + private EventMetric topologyGraphEventMetric;
79 - private Meter eventRateMeter;
80 79
81 @Activate 80 @Activate
82 protected void activate() { 81 protected void activate() {
...@@ -113,27 +112,34 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -113,27 +112,34 @@ public class TopologyMetrics implements TopologyMetricsService {
113 } 112 }
114 113
115 @Override 114 @Override
116 - public Gauge<Long> lastEventTimestampEpochMsGauge() { 115 + public EventMetric topologyDeviceEventMetric() {
117 - return lastEventTimestampEpochMsGauge; 116 + return topologyDeviceEventMetric;
117 + }
118 +
119 + @Override
120 + public EventMetric topologyHostEventMetric() {
121 + return topologyHostEventMetric;
118 } 122 }
119 123
120 @Override 124 @Override
121 - public Meter eventRateMeter() { 125 + public EventMetric topologyLinkEventMetric() {
122 - return eventRateMeter; 126 + return topologyLinkEventMetric;
127 + }
128 +
129 + @Override
130 + public EventMetric topologyGraphEventMetric() {
131 + return topologyGraphEventMetric;
123 } 132 }
124 133
125 /** 134 /**
126 * Records an event. 135 * Records an event.
127 * 136 *
128 * @param event the event to record 137 * @param event the event to record
129 - * @param updateEventRateMeter if true, update the Event Rate Meter 138 + * @param eventMetric the Event Metric to use
130 */ 139 */
131 - private void recordEvent(Event event, boolean updateEventRateMeter) { 140 + private void recordEvent(Event event, EventMetric eventMetric) {
132 synchronized (lastEvents) { 141 synchronized (lastEvents) {
133 - lastEventTimestampEpochMs = System.currentTimeMillis(); 142 + eventMetric.eventReceived();
134 - if (updateEventRateMeter) {
135 - eventRateMeter.mark(1);
136 - }
137 143
138 // 144 //
139 // Keep only the last N events, where N = LAST_EVENTS_MAX_N 145 // Keep only the last N events, where N = LAST_EVENTS_MAX_N
...@@ -151,7 +157,7 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -151,7 +157,7 @@ public class TopologyMetrics implements TopologyMetricsService {
151 private class InnerDeviceListener implements DeviceListener { 157 private class InnerDeviceListener implements DeviceListener {
152 @Override 158 @Override
153 public void event(DeviceEvent event) { 159 public void event(DeviceEvent event) {
154 - recordEvent(event, true); 160 + recordEvent(event, topologyDeviceEventMetric);
155 log.debug("Device Event: time = {} type = {} event = {}", 161 log.debug("Device Event: time = {} type = {} event = {}",
156 event.time(), event.type(), event); 162 event.time(), event.type(), event);
157 } 163 }
...@@ -163,7 +169,7 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -163,7 +169,7 @@ public class TopologyMetrics implements TopologyMetricsService {
163 private class InnerHostListener implements HostListener { 169 private class InnerHostListener implements HostListener {
164 @Override 170 @Override
165 public void event(HostEvent event) { 171 public void event(HostEvent event) {
166 - recordEvent(event, true); 172 + recordEvent(event, topologyHostEventMetric);
167 log.debug("Host Event: time = {} type = {} event = {}", 173 log.debug("Host Event: time = {} type = {} event = {}",
168 event.time(), event.type(), event); 174 event.time(), event.type(), event);
169 } 175 }
...@@ -175,7 +181,7 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -175,7 +181,7 @@ public class TopologyMetrics implements TopologyMetricsService {
175 private class InnerLinkListener implements LinkListener { 181 private class InnerLinkListener implements LinkListener {
176 @Override 182 @Override
177 public void event(LinkEvent event) { 183 public void event(LinkEvent event) {
178 - recordEvent(event, true); 184 + recordEvent(event, topologyLinkEventMetric);
179 log.debug("Link Event: time = {} type = {} event = {}", 185 log.debug("Link Event: time = {} type = {} event = {}",
180 event.time(), event.type(), event); 186 event.time(), event.type(), event);
181 } 187 }
...@@ -187,11 +193,7 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -187,11 +193,7 @@ public class TopologyMetrics implements TopologyMetricsService {
187 private class InnerTopologyListener implements TopologyListener { 193 private class InnerTopologyListener implements TopologyListener {
188 @Override 194 @Override
189 public void event(TopologyEvent event) { 195 public void event(TopologyEvent event) {
190 - // 196 + recordEvent(event, topologyGraphEventMetric);
191 - // NOTE: Don't update the eventRateMeter, because the real
192 - // events are already captured/counted.
193 - //
194 - recordEvent(event, false);
195 log.debug("Topology Event: time = {} type = {} event = {}", 197 log.debug("Topology Event: time = {} type = {} event = {}",
196 event.time(), event.type(), event); 198 event.time(), event.type(), event);
197 for (Event reason : event.reasons()) { 199 for (Event reason : event.reasons()) {
...@@ -206,7 +208,6 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -206,7 +208,6 @@ public class TopologyMetrics implements TopologyMetricsService {
206 */ 208 */
207 private void clear() { 209 private void clear() {
208 synchronized (lastEvents) { 210 synchronized (lastEvents) {
209 - lastEventTimestampEpochMs = 0;
210 lastEvents.clear(); 211 lastEvents.clear();
211 } 212 }
212 } 213 }
...@@ -215,35 +216,32 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -215,35 +216,32 @@ public class TopologyMetrics implements TopologyMetricsService {
215 * Registers the metrics. 216 * Registers the metrics.
216 */ 217 */
217 private void registerMetrics() { 218 private void registerMetrics() {
218 - metricsComponent = metricsService.registerComponent(COMPONENT_NAME); 219 + topologyDeviceEventMetric =
219 - metricsFeatureEventNotification = 220 + new EventMetric(metricsService, COMPONENT_NAME,
220 - metricsComponent.registerFeature(FEATURE_NAME); 221 + FEATURE_DEVICE_NAME);
221 - lastEventTimestampEpochMsGauge = 222 + topologyHostEventMetric =
222 - metricsService.registerMetric(metricsComponent, 223 + new EventMetric(metricsService, COMPONENT_NAME,
223 - metricsFeatureEventNotification, 224 + FEATURE_HOST_NAME);
224 - GAUGE_NAME, 225 + topologyLinkEventMetric =
225 - new Gauge<Long>() { 226 + new EventMetric(metricsService, COMPONENT_NAME,
226 - @Override 227 + FEATURE_LINK_NAME);
227 - public Long getValue() { 228 + topologyGraphEventMetric =
228 - return lastEventTimestampEpochMs; 229 + new EventMetric(metricsService, COMPONENT_NAME,
229 - } 230 + FEATURE_GRAPH_NAME);
230 - }); 231 +
231 - eventRateMeter = 232 + topologyDeviceEventMetric.registerMetrics();
232 - metricsService.createMeter(metricsComponent, 233 + topologyHostEventMetric.registerMetrics();
233 - metricsFeatureEventNotification, 234 + topologyLinkEventMetric.registerMetrics();
234 - METER_NAME); 235 + topologyGraphEventMetric.registerMetrics();
235 -
236 } 236 }
237 237
238 /** 238 /**
239 * Removes the metrics. 239 * Removes the metrics.
240 */ 240 */
241 private void removeMetrics() { 241 private void removeMetrics() {
242 - metricsService.removeMetric(metricsComponent, 242 + topologyDeviceEventMetric.removeMetrics();
243 - metricsFeatureEventNotification, 243 + topologyHostEventMetric.removeMetrics();
244 - GAUGE_NAME); 244 + topologyLinkEventMetric.removeMetrics();
245 - metricsService.removeMetric(metricsComponent, 245 + topologyGraphEventMetric.removeMetrics();
246 - metricsFeatureEventNotification,
247 - METER_NAME);
248 } 246 }
249 } 247 }
......
1 package org.onlab.onos.metrics.topology; 1 package org.onlab.onos.metrics.topology;
2 2
3 import java.util.List; 3 import java.util.List;
4 - 4 +import org.onlab.metrics.EventMetric;
5 -import com.codahale.metrics.Gauge;
6 -import com.codahale.metrics.Meter;
7 import org.onlab.onos.event.Event; 5 import org.onlab.onos.event.Event;
8 6
9 /** 7 /**
...@@ -18,18 +16,30 @@ public interface TopologyMetricsService { ...@@ -18,18 +16,30 @@ public interface TopologyMetricsService {
18 public List<Event> getEvents(); 16 public List<Event> getEvents();
19 17
20 /** 18 /**
21 - * Gets the Metrics' Gauge for the last topology event timestamp 19 + * Gets the Event Metric for the Device Events.
22 - * (ms from the epoch). 20 + *
21 + * @return the Event Metric for the Device Events.
22 + */
23 + public EventMetric topologyDeviceEventMetric();
24 +
25 + /**
26 + * Gets the Event Metric for the Host Events.
27 + *
28 + * @return the Event Metric for the Host Events.
29 + */
30 + public EventMetric topologyHostEventMetric();
31 +
32 + /**
33 + * Gets the Event Metric for the Link Events.
23 * 34 *
24 - * @return the Metrics' Gauge for the last topology event timestamp 35 + * @return the Event Metric for the Link Events.
25 - * (ms from the epoch)
26 */ 36 */
27 - public Gauge<Long> lastEventTimestampEpochMsGauge(); 37 + public EventMetric topologyLinkEventMetric();
28 38
29 /** 39 /**
30 - * Gets the Metrics' Meter for the topology events rate. 40 + * Gets the Event Metric for the Topology Graph Events.
31 * 41 *
32 - * @return the Metrics' Meter for the topology events rate 42 + * @return the Event Metric for the Topology Graph Events.
33 */ 43 */
34 - public Meter eventRateMeter(); 44 + public EventMetric topologyGraphEventMetric();
35 } 45 }
......
...@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode; ...@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode;
11 import com.fasterxml.jackson.databind.ObjectMapper; 11 import com.fasterxml.jackson.databind.ObjectMapper;
12 import com.fasterxml.jackson.databind.node.ObjectNode; 12 import com.fasterxml.jackson.databind.node.ObjectNode;
13 import org.apache.karaf.shell.commands.Command; 13 import org.apache.karaf.shell.commands.Command;
14 +import org.onlab.metrics.EventMetric;
14 import org.onlab.onos.cli.AbstractShellCommand; 15 import org.onlab.onos.cli.AbstractShellCommand;
15 import org.onlab.onos.metrics.topology.TopologyMetricsService; 16 import org.onlab.onos.metrics.topology.TopologyMetricsService;
16 17
...@@ -22,15 +23,13 @@ import org.onlab.onos.metrics.topology.TopologyMetricsService; ...@@ -22,15 +23,13 @@ import org.onlab.onos.metrics.topology.TopologyMetricsService;
22 public class TopologyEventsMetricsCommand extends AbstractShellCommand { 23 public class TopologyEventsMetricsCommand extends AbstractShellCommand {
23 24
24 private static final String FORMAT_GAUGE = 25 private static final String FORMAT_GAUGE =
25 - "Last Topology Event Timestamp (ms from epoch)=%d"; 26 + "Topology %s Event Timestamp (ms from epoch)=%d";
26 private static final String FORMAT_METER = 27 private static final String FORMAT_METER =
27 - "Topology Events count=%d rate(events/sec) mean=%f m1=%f m5=%f m15=%f"; 28 + "Topology %s Events count=%d rate(events/sec) mean=%f m1=%f m5=%f m15=%f";
28 29
29 @Override 30 @Override
30 protected void execute() { 31 protected void execute() {
31 TopologyMetricsService service = get(TopologyMetricsService.class); 32 TopologyMetricsService service = get(TopologyMetricsService.class);
32 - Gauge<Long> gauge = service.lastEventTimestampEpochMsGauge();
33 - Meter meter = service.eventRateMeter();
34 33
35 if (outputJson()) { 34 if (outputJson()) {
36 ObjectMapper mapper = new ObjectMapper() 35 ObjectMapper mapper = new ObjectMapper()
...@@ -38,32 +37,89 @@ public class TopologyEventsMetricsCommand extends AbstractShellCommand { ...@@ -38,32 +37,89 @@ public class TopologyEventsMetricsCommand extends AbstractShellCommand {
38 TimeUnit.MILLISECONDS, 37 TimeUnit.MILLISECONDS,
39 false)); 38 false));
40 ObjectNode result = mapper.createObjectNode(); 39 ObjectNode result = mapper.createObjectNode();
41 - try { 40 + result = json(mapper, result, "topologyDeviceEvent",
42 - // 41 + service.topologyDeviceEventMetric());
43 - // NOTE: The API for custom serializers is incomplete, 42 + result = json(mapper, result, "topologyHostEvent",
44 - // hence we have to parse the JSON string to create JsonNode. 43 + service.topologyHostEventMetric());
45 - // 44 + result = json(mapper, result, "topologyLinkEvent",
46 - final String gaugeJson = mapper.writeValueAsString(gauge); 45 + service.topologyLinkEventMetric());
47 - final String meterJson = mapper.writeValueAsString(meter); 46 + result = json(mapper, result, "topologyGraphEvent",
48 - JsonNode gaugeNode = mapper.readTree(gaugeJson); 47 + service.topologyGraphEventMetric());
49 - JsonNode meterNode = mapper.readTree(meterJson);
50 - result.put("lastTopologyEventTimestamp", gaugeNode);
51 - result.put("topologyEventRate", meterNode);
52 - } catch (JsonProcessingException e) {
53 - log.error("Error writing value as JSON string", e);
54 - } catch (IOException e) {
55 - log.error("Error writing value as JSON string", e);
56 - }
57 print("%s", result); 48 print("%s", result);
58 } else { 49 } else {
59 - TimeUnit rateUnit = TimeUnit.SECONDS; 50 + printEventMetric("Device", service.topologyDeviceEventMetric());
60 - double rateFactor = rateUnit.toSeconds(1); 51 + printEventMetric("Host", service.topologyHostEventMetric());
61 - print(FORMAT_GAUGE, gauge.getValue()); 52 + printEventMetric("Link", service.topologyLinkEventMetric());
62 - print(FORMAT_METER, meter.getCount(), 53 + printEventMetric("Graph", service.topologyGraphEventMetric());
63 - meter.getMeanRate() * rateFactor,
64 - meter.getOneMinuteRate() * rateFactor,
65 - meter.getFiveMinuteRate() * rateFactor,
66 - meter.getFifteenMinuteRate() * rateFactor);
67 } 54 }
68 } 55 }
56 +
57 + /**
58 + * Produces JSON node for an Event Metric.
59 + *
60 + * @param mapper the JSON object mapper to use
61 + * @param objectNode the JSON object node to use
62 + * @param propertyPrefix the property prefix to use
63 + * @param eventMetric the Event Metric with the data
64 + * @return JSON object node for the Event Metric
65 + */
66 + private ObjectNode json(ObjectMapper mapper, ObjectNode objectNode,
67 + String propertyPrefix, EventMetric eventMetric) {
68 + String gaugeName = propertyPrefix + "Timestamp";
69 + String meterName = propertyPrefix + "Rate";
70 + Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
71 + Meter meter = eventMetric.eventRateMeter();
72 +
73 + objectNode.put(gaugeName, json(mapper, gauge));
74 + objectNode.put(meterName, json(mapper, meter));
75 + return objectNode;
76 + }
77 +
78 + /**
79 + * Produces JSON node for an Object.
80 + *
81 + * @param mapper the JSON object mapper to use
82 + * @param object the Object with the data
83 + * @return JSON node for the Object
84 + */
85 + private JsonNode json(ObjectMapper mapper, Object object) {
86 + //
87 + // NOTE: The API for custom serializers is incomplete,
88 + // hence we have to parse the JSON string to create JsonNode.
89 + //
90 + try {
91 + final String objectJson = mapper.writeValueAsString(object);
92 + JsonNode jsonNode = mapper.readTree(objectJson);
93 + return jsonNode;
94 + } catch (JsonProcessingException e) {
95 + log.error("Error writing value as JSON string", e);
96 + } catch (IOException e) {
97 + log.error("Error writing value as JSON string", e);
98 + }
99 + return null;
100 + }
101 +
102 + /**
103 + * Prints an Event Metric.
104 + *
105 + * @param operationStr the string with the intent operation to print
106 + * @param eventMetric the Event Metric to print
107 + */
108 + private void printEventMetric(String operationStr,
109 + EventMetric eventMetric) {
110 + Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
111 + Meter meter = eventMetric.eventRateMeter();
112 + TimeUnit rateUnit = TimeUnit.SECONDS;
113 + double rateFactor = rateUnit.toSeconds(1);
114 +
115 + // Print the Gauge
116 + print(FORMAT_GAUGE, operationStr, gauge.getValue());
117 +
118 + // Print the Meter
119 + print(FORMAT_METER, operationStr, meter.getCount(),
120 + meter.getMeanRate() * rateFactor,
121 + meter.getOneMinuteRate() * rateFactor,
122 + meter.getFiveMinuteRate() * rateFactor,
123 + meter.getFifteenMinuteRate() * rateFactor);
124 + }
69 } 125 }
......
1 +package org.onlab.onos.optical.provisioner;
2 +
3 +import java.util.ArrayList;
4 +import java.util.HashMap;
5 +import java.util.Iterator;
6 +import java.util.Map;
7 +import java.util.Map.Entry;
8 +import java.util.Set;
9 +
10 +import org.apache.felix.scr.annotations.Activate;
11 +import org.apache.felix.scr.annotations.Component;
12 +import org.apache.felix.scr.annotations.Deactivate;
13 +import org.apache.felix.scr.annotations.Reference;
14 +import org.apache.felix.scr.annotations.ReferenceCardinality;
15 +import org.onlab.onos.ApplicationId;
16 +import org.onlab.onos.CoreService;
17 +import org.onlab.onos.net.ConnectPoint;
18 +import org.onlab.onos.net.Link;
19 +import org.onlab.onos.net.Path;
20 +import org.onlab.onos.net.device.DeviceService;
21 +import org.onlab.onos.net.intent.Intent;
22 +import org.onlab.onos.net.intent.IntentEvent;
23 +import org.onlab.onos.net.intent.IntentExtensionService;
24 +import org.onlab.onos.net.intent.IntentListener;
25 +import org.onlab.onos.net.intent.IntentService;
26 +import org.onlab.onos.net.intent.OpticalConnectivityIntent;
27 +import org.onlab.onos.net.intent.PointToPointIntent;
28 +import org.onlab.onos.net.link.LinkService;
29 +import org.onlab.onos.net.resource.LinkResourceService;
30 +import org.onlab.onos.net.topology.LinkWeight;
31 +import org.onlab.onos.net.topology.Topology;
32 +import org.onlab.onos.net.topology.TopologyEdge;
33 +
34 +import org.onlab.onos.net.topology.TopologyService;
35 +import org.slf4j.Logger;
36 +import org.slf4j.LoggerFactory;
37 +
38 +/**
39 + * OpticalPathProvisioner listens event notifications from the Intent F/W.
40 + * It generates one or more opticalConnectivityIntent(s) and submits (or withdraws) to Intent F/W
41 + * for adding/releasing capacity at the packet layer.
42 + *
43 + */
44 +
45 +@Component(immediate = true)
46 +public class OpticalPathProvisioner {
47 +
48 + protected static final Logger log = LoggerFactory
49 + .getLogger(OpticalPathProvisioner.class);
50 +
51 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
52 + private IntentService intentService;
53 +
54 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
55 + private IntentExtensionService intentExtensionService;
56 +
57 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 + protected LinkService linkService;
59 +
60 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 + protected DeviceService deviceService;
62 +
63 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 + protected TopologyService topologyService;
65 +
66 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 + protected CoreService coreService;
68 +
69 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 + protected LinkResourceService resourceService;
71 +
72 + private ApplicationId appId;
73 +
74 + //protected <IntentId> intentIdGenerator;
75 +
76 + private final InternalOpticalPathProvisioner pathProvisioner = new InternalOpticalPathProvisioner();
77 +
78 + @Activate
79 + protected void activate() {
80 + intentService.addListener(pathProvisioner);
81 + appId = coreService.registerApplication("org.onlab.onos.optical");
82 + log.info("Starting optical path provisoning...");
83 + }
84 +
85 + @Deactivate
86 + protected void deactivate() {
87 + intentService.removeListener(pathProvisioner);
88 + }
89 +
90 + public class InternalOpticalPathProvisioner implements IntentListener {
91 + @Override
92 + public void event(IntentEvent event) {
93 + switch (event.type()) {
94 + case SUBMITTED:
95 + break;
96 + case INSTALLED:
97 + break;
98 + case FAILED:
99 + log.info("intent {} failed, calling optical path provisioning APP.", event.subject());
100 + setuplightpath(event.subject());
101 + break;
102 + case WITHDRAWN:
103 + log.info("intent {} withdrawn.", event.subject());
104 + teardownLightpath(event.subject());
105 + break;
106 + default:
107 + break;
108 + }
109 + }
110 +
111 + private void setuplightpath(Intent intent) {
112 + // TODO: considering user policies and optical reach
113 + if (!intent.equals(PointToPointIntent.class)) {
114 + return;
115 + }
116 +
117 + PointToPointIntent pktIntent = (PointToPointIntent) intent;
118 + if (pktIntent.ingressPoint() == null || pktIntent.egressPoint() == null) {
119 + return;
120 + }
121 +
122 + Topology topology = topologyService.currentTopology();
123 +
124 + LinkWeight weight = new LinkWeight() {
125 + @Override
126 + public double weight(TopologyEdge edge) {
127 + boolean isOptical = false;
128 + String t = edge.link().annotations().value("linkType");
129 + if (t.equals("WDM")) {
130 + isOptical = true;
131 + }
132 + if (isOptical) {
133 + return 1000; // optical links
134 + } else {
135 + return 10; // packet links
136 + }
137 + }
138 + };
139 +
140 + Set<Path> paths = topologyService.getPaths(topology,
141 + pktIntent.ingressPoint().deviceId(),
142 + pktIntent.egressPoint().deviceId(),
143 + weight);
144 +
145 + if (paths.isEmpty()) {
146 + return;
147 + }
148 +
149 + ConnectPoint srcWdmPoint = null;
150 + ConnectPoint dstWdmPoint = null;
151 + Iterator<Path> itrPath = paths.iterator();
152 + Path firstPath = itrPath.next();
153 + log.info(firstPath.toString());
154 +
155 + ArrayList<Map<ConnectPoint, ConnectPoint>> connectionList = new ArrayList<>();
156 +
157 + Iterator<Link> itrLink = firstPath.links().iterator();
158 + while (itrLink.hasNext()) {
159 + Link link1 = itrLink.next();
160 + if (!isOpticalLink(link1)) {
161 + continue;
162 + } else {
163 + srcWdmPoint = link1.dst();
164 + dstWdmPoint = srcWdmPoint;
165 + }
166 +
167 + while (true) {
168 +
169 + if (itrLink.hasNext()) {
170 + Link link2 = itrLink.next();
171 + dstWdmPoint = link2.src();
172 + } else {
173 + break;
174 + }
175 +
176 + if (itrLink.hasNext()) {
177 + Link link3 = itrLink.next();
178 + if (!isOpticalLink(link3)) {
179 + break;
180 + }
181 + } else {
182 + break;
183 + }
184 + }
185 +
186 + Map<ConnectPoint, ConnectPoint> pair =
187 + new HashMap<ConnectPoint, ConnectPoint>();
188 + pair.put(srcWdmPoint, dstWdmPoint);
189 +
190 + connectionList.add(pair);
191 + }
192 +
193 + for (Map<ConnectPoint, ConnectPoint> map : connectionList) {
194 + for (Entry<ConnectPoint, ConnectPoint> entry : map.entrySet()) {
195 +
196 + ConnectPoint src = entry.getKey();
197 + ConnectPoint dst = entry.getValue();
198 +
199 + Intent opticalIntent = new OpticalConnectivityIntent(appId,
200 + srcWdmPoint,
201 + dstWdmPoint);
202 +
203 + intentService.submit(opticalIntent);
204 +
205 + log.info(opticalIntent.toString());
206 + }
207 + }
208 +
209 + }
210 +
211 + private boolean isOpticalLink(Link link) {
212 + boolean isOptical = false;
213 + String t = link.annotations().value("linkType");
214 + if (t.equals("WDM") || t.equals("PktOptLink")) {
215 + isOptical = true;
216 + }
217 + return isOptical;
218 + }
219 +
220 + private void teardownLightpath(Intent intent) {
221 + // TODO: tear down the idle lightpath if the utilization is close to zero.
222 + }
223 +
224 + }
225 +
226 +}
1 +package org.onlab.onos.optical.testapp;
2 +
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import java.util.HashMap;
6 +import java.util.Map;
7 +
8 +import org.apache.felix.scr.annotations.Activate;
9 +import org.apache.felix.scr.annotations.Deactivate;
10 +import org.apache.felix.scr.annotations.Reference;
11 +import org.apache.felix.scr.annotations.ReferenceCardinality;
12 +import org.onlab.onos.ApplicationId;
13 +import org.onlab.onos.CoreService;
14 +import org.onlab.onos.net.Device;
15 +import org.onlab.onos.net.DeviceId;
16 +import org.onlab.onos.net.PortNumber;
17 +import org.onlab.onos.net.device.DeviceEvent;
18 +import org.onlab.onos.net.device.DeviceListener;
19 +import org.onlab.onos.net.device.DeviceService;
20 +import org.onlab.onos.net.flow.DefaultFlowRule;
21 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
22 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
23 +import org.onlab.onos.net.flow.FlowRule;
24 +import org.onlab.onos.net.flow.FlowRuleService;
25 +import org.onlab.onos.net.flow.TrafficSelector;
26 +import org.onlab.onos.net.flow.TrafficTreatment;
27 +import org.slf4j.Logger;
28 +
29 +/**
30 + * Sample reactive forwarding application.
31 + */
32 +//@Component(immediate = true)
33 +public class LambdaForwarding {
34 +
35 + private final Logger log = getLogger(getClass());
36 +
37 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
38 + protected FlowRuleService flowRuleService;
39 +
40 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
41 + protected CoreService coreService;
42 +
43 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
44 + protected DeviceService deviceService;
45 +
46 + private ApplicationId appId;
47 +
48 + private final InternalDeviceListener listener = new InternalDeviceListener();
49 +
50 + private final Map<DeviceId, Integer> uglyMap = new HashMap<>();
51 +
52 + @Activate
53 + public void activate() {
54 + appId = coreService.registerApplication("org.onlab.onos.fwd");
55 +
56 + uglyMap.put(DeviceId.deviceId("of:0000ffffffffff01"), 1);
57 + uglyMap.put(DeviceId.deviceId("of:0000ffffffffff02"), 2);
58 + uglyMap.put(DeviceId.deviceId("of:0000ffffffffff03"), 3);
59 +
60 + deviceService.addListener(listener);
61 +
62 + for (Device d : deviceService.getDevices()) {
63 + pushRules(d);
64 + }
65 +
66 +
67 + log.info("Started with Application ID {}", appId.id());
68 + }
69 +
70 + @Deactivate
71 + public void deactivate() {
72 + flowRuleService.removeFlowRulesById(appId);
73 +
74 + log.info("Stopped");
75 + }
76 +
77 +
78 + private void pushRules(Device device) {
79 +
80 + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
81 + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
82 + int inport;
83 + int outport;
84 + short lambda = 10;
85 + byte sigType = 1;
86 + Integer switchNumber = uglyMap.get(device.id());
87 + if (switchNumber == null) {
88 + return;
89 + }
90 +
91 + switch (switchNumber) {
92 + case 1:
93 + inport = 10;
94 + outport = 20;
95 + sbuilder.matchInport(PortNumber.portNumber(inport));
96 + tbuilder.setOutput(PortNumber.portNumber(outport)).setLambda(lambda);
97 + break;
98 + case 2:
99 + inport = 21;
100 + outport = 11;
101 + sbuilder.matchLambda(lambda).
102 + matchInport(PortNumber.portNumber(inport)); // match sigtype
103 + tbuilder.setOutput(PortNumber.portNumber(outport));
104 + break;
105 + case 3:
106 + inport = 30;
107 + outport = 31;
108 + sbuilder.matchLambda(lambda).
109 + matchInport(PortNumber.portNumber(inport));
110 + tbuilder.setOutput(PortNumber.portNumber(outport)).setLambda(lambda);
111 + break;
112 + default:
113 + }
114 +
115 + TrafficTreatment treatement = tbuilder.build();
116 + TrafficSelector selector = sbuilder.build();
117 +
118 + FlowRule f = new DefaultFlowRule(device.id(), selector,
119 + treatement, 100, appId, 600, false);
120 +
121 + flowRuleService.applyFlowRules(f);
122 +
123 +
124 +
125 + }
126 +
127 + public class InternalDeviceListener implements DeviceListener {
128 +
129 + @Override
130 + public void event(DeviceEvent event) {
131 + switch (event.type()) {
132 + case DEVICE_ADDED:
133 + pushRules(event.subject());
134 + break;
135 + case DEVICE_AVAILABILITY_CHANGED:
136 + break;
137 + case DEVICE_MASTERSHIP_CHANGED:
138 + break;
139 + case DEVICE_REMOVED:
140 + break;
141 + case DEVICE_SUSPENDED:
142 + break;
143 + case DEVICE_UPDATED:
144 + break;
145 + case PORT_ADDED:
146 + break;
147 + case PORT_REMOVED:
148 + break;
149 + case PORT_UPDATED:
150 + break;
151 + default:
152 + break;
153 +
154 + }
155 +
156 + }
157 +
158 + }
159 +
160 +
161 +}
162 +
163 +
...@@ -14,6 +14,16 @@ ...@@ -14,6 +14,16 @@
14 "attachmentDpid" : "00:00:00:00:00:00:00:a2", 14 "attachmentDpid" : "00:00:00:00:00:00:00:a2",
15 "attachmentPort" : "1", 15 "attachmentPort" : "1",
16 "ipAddress" : "192.168.30.1" 16 "ipAddress" : "192.168.30.1"
17 + },
18 + {
19 + "attachmentDpid" : "00:00:00:00:00:00:00:a6",
20 + "attachmentPort" : "1",
21 + "ipAddress" : "192.168.40.1"
22 + },
23 + {
24 + "attachmentDpid" : "00:00:00:00:00:00:00:a4",
25 + "attachmentPort" : "4",
26 + "ipAddress" : "192.168.60.1"
17 } 27 }
18 ], 28 ],
19 "bgpSpeakers" : [ 29 "bgpSpeakers" : [
......
1 +/*
2 + * Licensed to the Apache Software Foundation (ASF) under one
3 + * or more contributor license agreements. See the NOTICE file
4 + * distributed with this work for additional information
5 + * regarding copyright ownership. The ASF licenses this file
6 + * to you under the Apache License, Version 2.0 (the
7 + * "License"); you may not use this file except in compliance
8 + * with the License. You may obtain a copy of the License at
9 + *
10 + * http://www.apache.org/licenses/LICENSE-2.0
11 + *
12 + * Unless required by applicable law or agreed to in writing,
13 + * software distributed under the License is distributed on an
14 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 + * KIND, either express or implied. See the License for the
16 + * specific language governing permissions and limitations
17 + * under the License.
18 + */
19 +package org.onlab.onos.cli.net;
20 +
21 +import static org.onlab.onos.net.DeviceId.deviceId;
22 +import static org.onlab.onos.net.PortNumber.portNumber;
23 +
24 +import org.apache.karaf.shell.commands.Argument;
25 +import org.apache.karaf.shell.commands.Command;
26 +import org.onlab.onos.net.ConnectPoint;
27 +import org.onlab.onos.net.DeviceId;
28 +import org.onlab.onos.net.PortNumber;
29 +import org.onlab.onos.net.intent.Intent;
30 +import org.onlab.onos.net.intent.IntentService;
31 +import org.onlab.onos.net.intent.OpticalConnectivityIntent;
32 +
33 +/**
34 + * Installs optical connectivity intents.
35 + */
36 +@Command(scope = "onos", name = "add-optical-intent",
37 + description = "Installs optical connectivity intent")
38 +public class AddOpticalIntentCommand extends ConnectivityIntentCommand {
39 +
40 + @Argument(index = 0, name = "ingressDevice",
41 + description = "Ingress Device/Port Description",
42 + required = true, multiValued = false)
43 + String ingressDeviceString = null;
44 +
45 + @Argument(index = 1, name = "egressDevice",
46 + description = "Egress Device/Port Description",
47 + required = true, multiValued = false)
48 + String egressDeviceString = null;
49 +
50 + @Override
51 + protected void execute() {
52 + IntentService service = get(IntentService.class);
53 +
54 + DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString));
55 + PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString));
56 + ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
57 +
58 + DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString));
59 + PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString));
60 + ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
61 +
62 + Intent intent = new OpticalConnectivityIntent(appId(), ingress, egress);
63 + service.submit(intent);
64 + }
65 +
66 + /**
67 + * Extracts the port number portion of the ConnectPoint.
68 + *
69 + * @param deviceString string representing the device/port
70 + * @return port number as a string, empty string if the port is not found
71 + */
72 + private String getPortNumber(String deviceString) {
73 + int slash = deviceString.indexOf('/');
74 + if (slash <= 0) {
75 + return "";
76 + }
77 + return deviceString.substring(slash + 1, deviceString.length());
78 + }
79 +
80 + /**
81 + * Extracts the device ID portion of the ConnectPoint.
82 + *
83 + * @param deviceString string representing the device/port
84 + * @return device ID string
85 + */
86 + private String getDeviceId(String deviceString) {
87 + int slash = deviceString.indexOf('/');
88 + if (slash <= 0) {
89 + return "";
90 + }
91 + return deviceString.substring(0, slash);
92 + }
93 +}
...@@ -119,6 +119,14 @@ ...@@ -119,6 +119,14 @@
119 </optional-completers> 119 </optional-completers>
120 </command> 120 </command>
121 <command> 121 <command>
122 + <action class="org.onlab.onos.cli.net.AddOpticalIntentCommand"/>
123 + <completers>
124 + <ref component-id="connectPointCompleter"/>
125 + <ref component-id="connectPointCompleter"/>
126 + <null/>
127 + </completers>
128 + </command>
129 + <command>
122 <action class="org.onlab.onos.cli.net.GetStatistics"/> 130 <action class="org.onlab.onos.cli.net.GetStatistics"/>
123 <completers> 131 <completers>
124 <ref component-id="connectPointCompleter"/> 132 <ref component-id="connectPointCompleter"/>
......
1 +/*
2 + * Licensed to the Apache Software Foundation (ASF) under one
3 + * or more contributor license agreements. See the NOTICE file
4 + * distributed with this work for additional information
5 + * regarding copyright ownership. The ASF licenses this file
6 + * to you under the Apache License, Version 2.0 (the
7 + * "License"); you may not use this file except in compliance
8 + * with the License. You may obtain a copy of the License at
9 + *
10 + * http://www.apache.org/licenses/LICENSE-2.0
11 + *
12 + * Unless required by applicable law or agreed to in writing,
13 + * software distributed under the License is distributed on an
14 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 + * KIND, either express or implied. See the License for the
16 + * specific language governing permissions and limitations
17 + * under the License.
18 + */
19 +package org.onlab.onos.codec;
20 +
21 +import java.util.Set;
22 +
23 +/**
24 + * Service for registering and retrieving JSON codecs for various entities.
25 + */
26 +public interface CodecService {
27 +
28 + /**
29 + * Returns the set of classes with currently registered codecs.
30 + *
31 + * @return set of entity classes
32 + */
33 + Set<Class<?>> getCodecs();
34 +
35 + /**
36 + * Returns the JSON codec for the specified entity class.
37 + *
38 + * @param entityClass entity class
39 + * @return JSON codec; null if no codec available for the class
40 + */
41 + JsonCodec getCodec(Class<?> entityClass);
42 +
43 + /**
44 + * Registers the specified JSON codec for the given entity class.
45 + *
46 + * @param entityClass entity class
47 + * @param codec JSON codec
48 + */
49 + void registerCodec(Class<?> entityClass, JsonCodec codec);
50 +
51 + /**
52 + * Unregisters the JSON codec for the specified entity class.
53 + *
54 + * @param entityClass entity class
55 + */
56 + void unregisterCodec(Class<?> entityClass);
57 +
58 +}
1 +/*
2 + * Licensed to the Apache Software Foundation (ASF) under one
3 + * or more contributor license agreements. See the NOTICE file
4 + * distributed with this work for additional information
5 + * regarding copyright ownership. The ASF licenses this file
6 + * to you under the Apache License, Version 2.0 (the
7 + * "License"); you may not use this file except in compliance
8 + * with the License. You may obtain a copy of the License at
9 + *
10 + * http://www.apache.org/licenses/LICENSE-2.0
11 + *
12 + * Unless required by applicable law or agreed to in writing,
13 + * software distributed under the License is distributed on an
14 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 + * KIND, either express or implied. See the License for the
16 + * specific language governing permissions and limitations
17 + * under the License.
18 + */
19 +package org.onlab.onos.codec;
20 +
21 +import com.fasterxml.jackson.databind.JsonNode;
22 +import com.fasterxml.jackson.databind.ObjectMapper;
23 +import com.fasterxml.jackson.databind.node.ArrayNode;
24 +import com.fasterxml.jackson.databind.node.ObjectNode;
25 +
26 +import java.util.ArrayList;
27 +import java.util.List;
28 +
29 +/**
30 + * Abstraction of a codec capable for encoding/decoding arbitrary objects to/from JSON.
31 + */
32 +public abstract class JsonCodec<T> {
33 +
34 + /**
35 + * Encodes the specified entity into JSON.
36 + *
37 + * @param entity entity to encode
38 + * @param mapper object mapper
39 + * @return JSON node
40 + * @throws java.lang.UnsupportedOperationException if the codec does not
41 + * support encode operations
42 + */
43 + public abstract ObjectNode encode(T entity, ObjectMapper mapper);
44 +
45 + /**
46 + * Decodes the specified entity from JSON.
47 + *
48 + * @param json JSON to decode
49 + * @return decoded entity
50 + * @throws java.lang.UnsupportedOperationException if the codec does not
51 + * support decode operations
52 + */
53 + public abstract T decode(ObjectNode json);
54 +
55 + /**
56 + * Encodes the collection of the specified entities.
57 + *
58 + * @param entities collection of entities to encode
59 + * @param mapper object mapper
60 + * @return JSON array
61 + * @throws java.lang.UnsupportedOperationException if the codec does not
62 + * support encode operations
63 + */
64 + public ArrayNode encode(Iterable<T> entities, ObjectMapper mapper) {
65 + ArrayNode result = mapper.createArrayNode();
66 + for (T entity : entities) {
67 + result.add(encode(entity, mapper));
68 + }
69 + return result;
70 + }
71 +
72 + /**
73 + * Decodes the specified JSON array into a collection of entities.
74 + *
75 + * @param json JSON array to decode
76 + * @return collection of decoded entities
77 + * @throws java.lang.UnsupportedOperationException if the codec does not
78 + * support decode operations
79 + */
80 + public List<T> decode(ArrayNode json) {
81 + List<T> result = new ArrayList<>();
82 + for (JsonNode node : json) {
83 + result.add(decode((ObjectNode) node));
84 + }
85 + return result;
86 + }
87 +
88 +}
1 +/*
2 + * Licensed to the Apache Software Foundation (ASF) under one
3 + * or more contributor license agreements. See the NOTICE file
4 + * distributed with this work for additional information
5 + * regarding copyright ownership. The ASF licenses this file
6 + * to you under the Apache License, Version 2.0 (the
7 + * "License"); you may not use this file except in compliance
8 + * with the License. You may obtain a copy of the License at
9 + *
10 + * http://www.apache.org/licenses/LICENSE-2.0
11 + *
12 + * Unless required by applicable law or agreed to in writing,
13 + * software distributed under the License is distributed on an
14 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 + * KIND, either express or implied. See the License for the
16 + * specific language governing permissions and limitations
17 + * under the License.
18 + */
19 +
20 +/**
21 + * Base JSON codec abstraction and a service for tracking various JSON codecs.
22 + */
23 +package org.onlab.onos.codec;
...\ No newline at end of file ...\ No newline at end of file
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
18 */ 18 */
19 package org.onlab.onos.net.flow; 19 package org.onlab.onos.net.flow;
20 20
21 -import java.util.List; 21 +import java.util.Set;
22 22
23 /** 23 /**
24 * Interface capturing the result of a batch operation. 24 * Interface capturing the result of a batch operation.
...@@ -33,9 +33,9 @@ public interface BatchOperationResult<T> { ...@@ -33,9 +33,9 @@ public interface BatchOperationResult<T> {
33 boolean isSuccess(); 33 boolean isSuccess();
34 34
35 /** 35 /**
36 - * Obtains a list of items which failed. 36 + * Obtains a set of items which failed.
37 - * @return a list of failures 37 + * @return a set of failures
38 */ 38 */
39 - List<T> failedItems(); 39 + Set<T> failedItems();
40 40
41 } 41 }
......
...@@ -18,19 +18,19 @@ ...@@ -18,19 +18,19 @@
18 */ 18 */
19 package org.onlab.onos.net.flow; 19 package org.onlab.onos.net.flow;
20 20
21 -import java.util.List; 21 +import java.util.Set;
22 22
23 -import com.google.common.collect.ImmutableList; 23 +import com.google.common.collect.ImmutableSet;
24 24
25 public class CompletedBatchOperation implements BatchOperationResult<FlowEntry> { 25 public class CompletedBatchOperation implements BatchOperationResult<FlowEntry> {
26 26
27 27
28 private final boolean success; 28 private final boolean success;
29 - private final List<FlowEntry> failures; 29 + private final Set<FlowEntry> failures;
30 30
31 - public CompletedBatchOperation(boolean success, List<FlowEntry> failures) { 31 + public CompletedBatchOperation(boolean success, Set<FlowEntry> failures) {
32 this.success = success; 32 this.success = success;
33 - this.failures = ImmutableList.copyOf(failures); 33 + this.failures = ImmutableSet.copyOf(failures);
34 } 34 }
35 35
36 @Override 36 @Override
...@@ -39,7 +39,7 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowEntry> ...@@ -39,7 +39,7 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowEntry>
39 } 39 }
40 40
41 @Override 41 @Override
42 - public List<FlowEntry> failedItems() { 42 + public Set<FlowEntry> failedItems() {
43 return failures; 43 return failures;
44 } 44 }
45 45
......
...@@ -55,6 +55,16 @@ public final class DefaultTrafficSelector implements TrafficSelector { ...@@ -55,6 +55,16 @@ public final class DefaultTrafficSelector implements TrafficSelector {
55 } 55 }
56 56
57 @Override 57 @Override
58 + public Criterion getCriterion(Criterion.Type type) {
59 + for (Criterion c : criteria) {
60 + if (c.type() == type) {
61 + return c;
62 + }
63 + }
64 + return null;
65 + }
66 +
67 + @Override
58 public int hashCode() { 68 public int hashCode() {
59 return Objects.hash(criteria); 69 return Objects.hash(criteria);
60 } 70 }
...@@ -176,6 +186,17 @@ public final class DefaultTrafficSelector implements TrafficSelector { ...@@ -176,6 +186,17 @@ public final class DefaultTrafficSelector implements TrafficSelector {
176 } 186 }
177 187
178 @Override 188 @Override
189 + public Builder matchLambda(Short lambda) {
190 + return add(Criteria.matchLambda(lambda));
191 + }
192 +
193 + @Override
194 + public Builder matchOpticalSignalType(Byte signalType) {
195 + return add(Criteria.matchOpticalSignalType(signalType));
196 +
197 + }
198 +
199 + @Override
179 public TrafficSelector build() { 200 public TrafficSelector build() {
180 return new DefaultTrafficSelector(ImmutableSet.copyOf(selector.values())); 201 return new DefaultTrafficSelector(ImmutableSet.copyOf(selector.values()));
181 } 202 }
......
...@@ -137,6 +137,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -137,6 +137,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
137 case OUTPUT: 137 case OUTPUT:
138 outputs.add(instruction); 138 outputs.add(instruction);
139 break; 139 break;
140 + case L0MODIFICATION:
140 case L2MODIFICATION: 141 case L2MODIFICATION:
141 case L3MODIFICATION: 142 case L3MODIFICATION:
142 // TODO: enforce modification order if any 143 // TODO: enforce modification order if any
...@@ -193,6 +194,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -193,6 +194,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
193 } 194 }
194 195
195 @Override 196 @Override
197 + public Builder setLambda(short lambda) {
198 + return add(Instructions.modL0Lambda(lambda));
199 + }
200 +
201 + @Override
196 public TrafficTreatment build() { 202 public TrafficTreatment build() {
197 203
198 //If we are dropping should we just return an emptry list? 204 //If we are dropping should we just return an emptry list?
......
1 +package org.onlab.onos.net.flow;
2 +
3 +import org.onlab.onos.event.AbstractEvent;
4 +
5 +/**
6 + * Describes flow rule batch event.
7 + */
8 +public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.Type, FlowRuleBatchRequest> {
9 +
10 + /**
11 + * Type of flow rule events.
12 + */
13 + public enum Type {
14 +
15 + /**
16 + * Signifies that a batch operation has been initiated.
17 + */
18 + BATCH_OPERATION_REQUESTED,
19 +
20 + /**
21 + * Signifies that a batch operation has completed.
22 + */
23 + BATCH_OPERATION_COMPLETED,
24 + }
25 +
26 + private final CompletedBatchOperation result;
27 +
28 + /**
29 + * Constructs a new FlowRuleBatchEvent.
30 + * @param request batch operation request.
31 + * @return event.
32 + */
33 + public static FlowRuleBatchEvent requested(FlowRuleBatchRequest request) {
34 + FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_REQUESTED, request, null);
35 + return event;
36 + }
37 +
38 + /**
39 + * Constructs a new FlowRuleBatchEvent.
40 + * @param request batch operation request.
41 + * @param result completed batch operation result.
42 + * @return event.
43 + */
44 + public static FlowRuleBatchEvent completed(FlowRuleBatchRequest request, CompletedBatchOperation result) {
45 + FlowRuleBatchEvent event = new FlowRuleBatchEvent(Type.BATCH_OPERATION_COMPLETED, request, result);
46 + return event;
47 + }
48 +
49 + /**
50 + * Returns the result of this batch operation.
51 + * @return batch operation result.
52 + */
53 + public CompletedBatchOperation result() {
54 + return result;
55 + }
56 +
57 + /**
58 + * Creates an event of a given type and for the specified flow rule batch.
59 + *
60 + * @param type flow rule batch event type
61 + * @param batch event flow rule batch subject
62 + */
63 + private FlowRuleBatchEvent(Type type, FlowRuleBatchRequest request, CompletedBatchOperation result) {
64 + super(type, request);
65 + this.result = result;
66 + }
67 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +import java.util.Collections;
4 +import java.util.List;
5 +
6 +import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
7 +
8 +import com.google.common.collect.Lists;
9 +
10 +public class FlowRuleBatchRequest {
11 +
12 + private final int batchId;
13 + private final List<FlowEntry> toAdd;
14 + private final List<FlowEntry> toRemove;
15 +
16 + public FlowRuleBatchRequest(int batchId, List<FlowEntry> toAdd, List<FlowEntry> toRemove) {
17 + this.batchId = batchId;
18 + this.toAdd = Collections.unmodifiableList(toAdd);
19 + this.toRemove = Collections.unmodifiableList(toRemove);
20 + }
21 +
22 + public List<FlowEntry> toAdd() {
23 + return toAdd;
24 + }
25 +
26 + public List<FlowEntry> toRemove() {
27 + return toRemove;
28 + }
29 +
30 + public FlowRuleBatchOperation asBatchOperation() {
31 + List<FlowRuleBatchEntry> entries = Lists.newArrayList();
32 + for (FlowEntry e : toAdd) {
33 + entries.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, e));
34 + }
35 + for (FlowEntry e : toRemove) {
36 + entries.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, e));
37 + }
38 + return new FlowRuleBatchOperation(entries);
39 + }
40 +
41 + public int batchId() {
42 + return batchId;
43 + }
44 +}
...@@ -18,11 +18,11 @@ ...@@ -18,11 +18,11 @@
18 */ 18 */
19 package org.onlab.onos.net.flow; 19 package org.onlab.onos.net.flow;
20 20
21 -import java.util.concurrent.Future;
22 -
23 import org.onlab.onos.ApplicationId; 21 import org.onlab.onos.ApplicationId;
24 import org.onlab.onos.net.provider.Provider; 22 import org.onlab.onos.net.provider.Provider;
25 23
24 +import com.google.common.util.concurrent.ListenableFuture;
25 +
26 /** 26 /**
27 * Abstraction of a flow rule provider. 27 * Abstraction of a flow rule provider.
28 */ 28 */
...@@ -60,6 +60,6 @@ public interface FlowRuleProvider extends Provider { ...@@ -60,6 +60,6 @@ public interface FlowRuleProvider extends Provider {
60 * @param batch a batch of flow rules 60 * @param batch a batch of flow rules
61 * @return a future indicating the status of this execution 61 * @return a future indicating the status of this execution
62 */ 62 */
63 - Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch); 63 + ListenableFuture<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch);
64 64
65 } 65 }
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
18 */ 18 */
19 package org.onlab.onos.net.flow; 19 package org.onlab.onos.net.flow;
20 20
21 +import java.util.concurrent.Future;
22 +
21 import org.onlab.onos.ApplicationId; 23 import org.onlab.onos.ApplicationId;
22 import org.onlab.onos.net.DeviceId; 24 import org.onlab.onos.net.DeviceId;
23 import org.onlab.onos.store.Store; 25 import org.onlab.onos.store.Store;
...@@ -25,7 +27,7 @@ import org.onlab.onos.store.Store; ...@@ -25,7 +27,7 @@ import org.onlab.onos.store.Store;
25 /** 27 /**
26 * Manages inventory of flow rules; not intended for direct use. 28 * Manages inventory of flow rules; not intended for direct use.
27 */ 29 */
28 -public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegate> { 30 +public interface FlowRuleStore extends Store<FlowRuleBatchEvent, FlowRuleStoreDelegate> {
29 31
30 /** 32 /**
31 * Returns the number of flow rule in the store. 33 * Returns the number of flow rule in the store.
...@@ -59,12 +61,26 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat ...@@ -59,12 +61,26 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat
59 Iterable<FlowRule> getFlowRulesByAppId(ApplicationId appId); 61 Iterable<FlowRule> getFlowRulesByAppId(ApplicationId appId);
60 62
61 /** 63 /**
64 + // TODO: Better description of method behavior.
62 * Stores a new flow rule without generating events. 65 * Stores a new flow rule without generating events.
63 * 66 *
64 * @param rule the flow rule to add 67 * @param rule the flow rule to add
65 - * @return true if the rule should be handled locally
66 */ 68 */
67 - boolean storeFlowRule(FlowRule rule); 69 + void storeFlowRule(FlowRule rule);
70 +
71 + /**
72 + * Stores a batch of flow rules.
73 + * @param batchOperation batch of flow rules.
74 + * @return Future response indicating success/failure of the batch operation
75 + * all the way down to the device.
76 + */
77 + Future<CompletedBatchOperation> storeBatch(FlowRuleBatchOperation batchOperation);
78 +
79 + /**
80 + * Invoked on the completion of a storeBatch operation.
81 + * @param result
82 + */
83 + void batchOperationComplete(FlowRuleBatchEvent event);
68 84
69 /** 85 /**
70 * Marks a flow rule for deletion. Actual deletion will occur 86 * Marks a flow rule for deletion. Actual deletion will occur
...@@ -73,7 +89,7 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat ...@@ -73,7 +89,7 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat
73 * @param rule the flow rule to delete 89 * @param rule the flow rule to delete
74 * @return true if the rule should be handled locally 90 * @return true if the rule should be handled locally
75 */ 91 */
76 - boolean deleteFlowRule(FlowRule rule); 92 + void deleteFlowRule(FlowRule rule);
77 93
78 /** 94 /**
79 * Stores a new flow rule, or updates an existing entry. 95 * Stores a new flow rule, or updates an existing entry.
......
...@@ -23,5 +23,5 @@ import org.onlab.onos.store.StoreDelegate; ...@@ -23,5 +23,5 @@ import org.onlab.onos.store.StoreDelegate;
23 /** 23 /**
24 * Flow rule store delegate abstraction. 24 * Flow rule store delegate abstraction.
25 */ 25 */
26 -public interface FlowRuleStoreDelegate extends StoreDelegate<FlowRuleEvent> { 26 +public interface FlowRuleStoreDelegate extends StoreDelegate<FlowRuleBatchEvent> {
27 } 27 }
......
...@@ -39,6 +39,15 @@ public interface TrafficSelector { ...@@ -39,6 +39,15 @@ public interface TrafficSelector {
39 Set<Criterion> criteria(); 39 Set<Criterion> criteria();
40 40
41 /** 41 /**
42 + * Returns the selection criterion for a particular type, if it exists in
43 + * this traffic selector.
44 + *
45 + * @param type criterion type to look up
46 + * @return the criterion of the specified type if one exists, otherwise null
47 + */
48 + Criterion getCriterion(Criterion.Type type);
49 +
50 + /**
42 * Builder of traffic selector entities. 51 * Builder of traffic selector entities.
43 */ 52 */
44 public interface Builder { 53 public interface Builder {
...@@ -130,6 +139,20 @@ public interface TrafficSelector { ...@@ -130,6 +139,20 @@ public interface TrafficSelector {
130 public Builder matchTcpDst(Short tcpPort); 139 public Builder matchTcpDst(Short tcpPort);
131 140
132 /** 141 /**
142 + * Matches an optical signal ID or lambda.
143 + * @param lambda
144 + * @return a selection builder
145 + */
146 + public Builder matchLambda(Short lambda);
147 +
148 + /**
149 + * Matches an optical Signal Type.
150 + * @param signalType
151 + * @return a selection builder
152 + */
153 + public Builder matchOpticalSignalType(Byte signalType);
154 +
155 + /**
133 * Builds an immutable traffic selector. 156 * Builds an immutable traffic selector.
134 * 157 *
135 * @return traffic selector 158 * @return traffic selector
......
...@@ -105,6 +105,13 @@ public interface TrafficTreatment { ...@@ -105,6 +105,13 @@ public interface TrafficTreatment {
105 public Builder setIpDst(IpPrefix addr); 105 public Builder setIpDst(IpPrefix addr);
106 106
107 /** 107 /**
108 + * Sets the optical channel ID or lambda.
109 + * @param lambda optical channel ID
110 + * @return a treatment builder
111 + */
112 + public Builder setLambda(short lambda);
113 +
114 + /**
108 * Builds an immutable traffic treatment descriptor. 115 * Builds an immutable traffic treatment descriptor.
109 * 116 *
110 * @return traffic treatment 117 * @return traffic treatment
......
...@@ -151,10 +151,30 @@ public final class Criteria { ...@@ -151,10 +151,30 @@ public final class Criteria {
151 return new TcpPortCriterion(tcpPort, Type.TCP_DST); 151 return new TcpPortCriterion(tcpPort, Type.TCP_DST);
152 } 152 }
153 153
154 - /* 154 + /**
155 - * Implementations of criteria. 155 + * Creates a match on lambda field using the specified value.
156 + *
157 + * @param lambda
158 + * @return match criterion
156 */ 159 */
160 + public static Criterion matchLambda(Short lambda) {
161 + return new LambdaCriterion(lambda, Type.OCH_SIGID);
162 + }
163 +
164 + /**
165 + * Creates a match on lambda field using the specified value.
166 + *
167 + * @param lambda
168 + * @return match criterion
169 + */
170 + public static Criterion matchOpticalSignalType(Byte lambda) {
171 + return new OpticalSignalTypeCriterion(lambda, Type.OCH_SIGTYPE);
172 + }
157 173
174 +
175 + /**
176 + * Implementations of criteria.
177 + */
158 public static final class PortCriterion implements Criterion { 178 public static final class PortCriterion implements Criterion {
159 private final PortNumber port; 179 private final PortNumber port;
160 180
...@@ -523,4 +543,93 @@ public final class Criteria { ...@@ -523,4 +543,93 @@ public final class Criteria {
523 return false; 543 return false;
524 } 544 }
525 } 545 }
546 +
547 + public static final class LambdaCriterion implements Criterion {
548 +
549 + private final short lambda;
550 + private final Type type;
551 +
552 + public LambdaCriterion(short lambda, Type type) {
553 + this.lambda = lambda;
554 + this.type = type;
555 + }
556 +
557 + @Override
558 + public Type type() {
559 + return this.type;
560 + }
561 +
562 + public Short lambda() {
563 + return this.lambda;
564 + }
565 +
566 + @Override
567 + public String toString() {
568 + return toStringHelper(type().toString())
569 + .add("lambda", lambda).toString();
570 + }
571 +
572 + @Override
573 + public int hashCode() {
574 + return Objects.hash(lambda, type);
575 + }
576 +
577 + @Override
578 + public boolean equals(Object obj) {
579 + if (this == obj) {
580 + return true;
581 + }
582 + if (obj instanceof LambdaCriterion) {
583 + LambdaCriterion that = (LambdaCriterion) obj;
584 + return Objects.equals(lambda, that.lambda) &&
585 + Objects.equals(type, that.type);
586 + }
587 + return false;
588 + }
589 + }
590 +
591 + public static final class OpticalSignalTypeCriterion implements Criterion {
592 +
593 + private final byte signalType;
594 + private final Type type;
595 +
596 + public OpticalSignalTypeCriterion(byte signalType, Type type) {
597 + this.signalType = signalType;
598 + this.type = type;
599 + }
600 +
601 + @Override
602 + public Type type() {
603 + return this.type;
604 + }
605 +
606 + public Byte signalType() {
607 + return this.signalType;
608 + }
609 +
610 + @Override
611 + public String toString() {
612 + return toStringHelper(type().toString())
613 + .add("signalType", signalType).toString();
614 + }
615 +
616 + @Override
617 + public int hashCode() {
618 + return Objects.hash(signalType, type);
619 + }
620 +
621 + @Override
622 + public boolean equals(Object obj) {
623 + if (this == obj) {
624 + return true;
625 + }
626 + if (obj instanceof OpticalSignalTypeCriterion) {
627 + OpticalSignalTypeCriterion that = (OpticalSignalTypeCriterion) obj;
628 + return Objects.equals(signalType, that.signalType) &&
629 + Objects.equals(type, that.type);
630 + }
631 + return false;
632 + }
633 + }
634 +
526 } 635 }
......
...@@ -108,7 +108,11 @@ public interface Criterion { ...@@ -108,7 +108,11 @@ public interface Criterion {
108 /** Logical Port Metadata. */ 108 /** Logical Port Metadata. */
109 TUNNEL_ID, 109 TUNNEL_ID,
110 /** IPv6 Extension Header pseudo-field. */ 110 /** IPv6 Extension Header pseudo-field. */
111 - IPV6_EXTHDR 111 + IPV6_EXTHDR,
112 + /** Optical channel signal ID (lambda). */
113 + OCH_SIGID,
114 + /** Optical channel signal type (fixed or flexible). */
115 + OCH_SIGTYPE
112 } 116 }
113 117
114 /** 118 /**
......
...@@ -43,6 +43,11 @@ public interface Instruction { ...@@ -43,6 +43,11 @@ public interface Instruction {
43 GROUP, 43 GROUP,
44 44
45 /** 45 /**
46 + * Signifies that the traffic should be modified in L0 way.
47 + */
48 + L0MODIFICATION,
49 +
50 + /**
46 * Signifies that the traffic should be modified in L2 way. 51 * Signifies that the traffic should be modified in L2 way.
47 */ 52 */
48 L2MODIFICATION, 53 L2MODIFICATION,
......
...@@ -24,6 +24,8 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -24,6 +24,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
24 import java.util.Objects; 24 import java.util.Objects;
25 25
26 import org.onlab.onos.net.PortNumber; 26 import org.onlab.onos.net.PortNumber;
27 +import org.onlab.onos.net.flow.instructions.L0ModificationInstruction.L0SubType;
28 +import org.onlab.onos.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
27 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.L2SubType; 29 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.L2SubType;
28 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction; 30 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
29 import org.onlab.onos.net.flow.instructions.L3ModificationInstruction.L3SubType; 31 import org.onlab.onos.net.flow.instructions.L3ModificationInstruction.L3SubType;
...@@ -62,6 +64,16 @@ public final class Instructions { ...@@ -62,6 +64,16 @@ public final class Instructions {
62 } 64 }
63 65
64 /** 66 /**
67 + * Creates a l0 modification.
68 + * @param lambda the lambda to modify to.
69 + * @return a l0 modification
70 + */
71 + public static L0ModificationInstruction modL0Lambda(short lambda) {
72 + checkNotNull(lambda, "L0 lambda cannot be null");
73 + return new ModLambdaInstruction(L0SubType.LAMBDA, lambda);
74 + }
75 +
76 + /**
65 * Creates a l2 src modification. 77 * Creates a l2 src modification.
66 * @param addr the mac address to modify to. 78 * @param addr the mac address to modify to.
67 * @return a l2 modification 79 * @return a l2 modification
......
1 +package org.onlab.onos.net.flow.instructions;
2 +
3 +import static com.google.common.base.MoreObjects.toStringHelper;
4 +
5 +import java.util.Objects;
6 +
7 +public abstract class L0ModificationInstruction implements Instruction {
8 +
9 + /**
10 + * Represents the type of traffic treatment.
11 + */
12 + public enum L0SubType {
13 + /**
14 + * Lambda modification.
15 + */
16 + LAMBDA
17 +
18 + //TODO: remaining types
19 + }
20 +
21 + public abstract L0SubType subtype();
22 +
23 + @Override
24 + public Type type() {
25 + return Type.L0MODIFICATION;
26 + }
27 +
28 + /**
29 + * Represents a L0 lambda modification instruction.
30 + */
31 + public static final class ModLambdaInstruction extends L0ModificationInstruction {
32 +
33 + private final L0SubType subtype;
34 + private final short lambda;
35 +
36 + public ModLambdaInstruction(L0SubType subType, short lambda) {
37 + this.subtype = subType;
38 + this.lambda = lambda;
39 + }
40 +
41 + @Override
42 + public L0SubType subtype() {
43 + return this.subtype;
44 + }
45 +
46 + public short lambda() {
47 + return this.lambda;
48 + }
49 +
50 + @Override
51 + public String toString() {
52 + return toStringHelper(subtype().toString())
53 + .add("lambda", lambda).toString();
54 + }
55 +
56 + @Override
57 + public int hashCode() {
58 + return Objects.hash(lambda, type(), subtype);
59 + }
60 +
61 + @Override
62 + public boolean equals(Object obj) {
63 + if (this == obj) {
64 + return true;
65 + }
66 + if (obj instanceof ModLambdaInstruction) {
67 + ModLambdaInstruction that = (ModLambdaInstruction) obj;
68 + return Objects.equals(lambda, that.lambda) &&
69 + Objects.equals(this.type(), that.type()) &&
70 + Objects.equals(subtype, that.subtype);
71 + }
72 + return false;
73 + }
74 + }
75 +}
1 +package org.onlab.onos.net.intent;
2 +
3 +import org.onlab.onos.ApplicationId;
4 +import org.onlab.onos.net.ConnectPoint;
5 +
6 +/**
7 + * An optical layer Intent for a connectivity from one Transponder port to another
8 + * Transponder port. No trafficSelector as well as trafficTreament are needed.
9 + *
10 + */
11 +public class OpticalConnectivityIntent extends Intent {
12 + protected ConnectPoint src;
13 + protected ConnectPoint dst;
14 +
15 + /**
16 + * Constructor.
17 + *
18 + * @param id ID for this new Intent object.
19 + * @param src The source transponder port.
20 + * @param dst The destination transponder port.
21 + */
22 + public OpticalConnectivityIntent(ApplicationId appId, ConnectPoint src, ConnectPoint dst) {
23 + super(id(OpticalConnectivityIntent.class, src, dst),
24 + appId, null);
25 + this.src = src;
26 + this.dst = dst;
27 + }
28 +
29 + /**
30 + * Constructor for serializer.
31 + */
32 + protected OpticalConnectivityIntent() {
33 + super();
34 + this.src = null;
35 + this.dst = null;
36 + }
37 +
38 + /**
39 + * Gets source transponder port.
40 + *
41 + * @return The source transponder port.
42 + */
43 + public ConnectPoint getSrcConnectPoint() {
44 + return src;
45 + }
46 +
47 + /**
48 + * Gets destination transponder port.
49 + *
50 + * @return The source transponder port.
51 + */
52 + public ConnectPoint getDst() {
53 + return dst;
54 + }
55 +}
1 +package org.onlab.onos.net.intent;
2 +
3 +import java.util.Collection;
4 +
5 +import org.onlab.onos.ApplicationId;
6 +import org.onlab.onos.net.ConnectPoint;
7 +import org.onlab.onos.net.Link;
8 +import org.onlab.onos.net.NetworkResource;
9 +import org.onlab.onos.net.Path;
10 +
11 +import com.google.common.base.MoreObjects;
12 +import com.google.common.collect.ImmutableSet;
13 +
14 +public class OpticalPathIntent extends Intent {
15 +
16 + private final ConnectPoint src;
17 + private final ConnectPoint dst;
18 + private final Path path;
19 +
20 +
21 + public OpticalPathIntent(ApplicationId appId,
22 + ConnectPoint src,
23 + ConnectPoint dst,
24 + Path path) {
25 + super(id(OpticalPathIntent.class, src, dst),
26 + appId,
27 + ImmutableSet.<NetworkResource>copyOf(path.links()));
28 + this.src = src;
29 + this.dst = dst;
30 + this.path = path;
31 + }
32 +
33 + protected OpticalPathIntent() {
34 + this.src = null;
35 + this.dst = null;
36 + this.path = null;
37 + }
38 +
39 + public ConnectPoint src() {
40 + return src;
41 + }
42 +
43 + public ConnectPoint dst() {
44 + return dst;
45 + }
46 +
47 + public Path path() {
48 + return path;
49 + }
50 +
51 + @Override
52 + public boolean isInstallable() {
53 + return true;
54 + }
55 +
56 + @Override
57 + public String toString() {
58 + return MoreObjects.toStringHelper(getClass())
59 + .add("id", id())
60 + .add("ingressPort", src)
61 + .add("egressPort", dst)
62 + .add("path", path)
63 + .toString();
64 + }
65 +
66 + public Collection<Link> requiredLinks() {
67 + return path.links();
68 + }
69 +}
...@@ -3,6 +3,21 @@ package org.onlab.onos.net.resource; ...@@ -3,6 +3,21 @@ package org.onlab.onos.net.resource;
3 /** 3 /**
4 * Representation of allocated bandwidth resource. 4 * Representation of allocated bandwidth resource.
5 */ 5 */
6 -public interface BandwidthResourceAllocation extends BandwidthResourceRequest { 6 +public class BandwidthResourceAllocation extends BandwidthResourceRequest
7 + implements ResourceAllocation {
7 8
9 + @Override
10 + public ResourceType type() {
11 + return ResourceType.BANDWIDTH;
12 + }
13 +
14 + /**
15 + * Creates a new {@link BandwidthResourceAllocation} with {@link Bandwidth}
16 + * object.
17 + *
18 + * @param bandwidth allocated bandwidth
19 + */
20 + public BandwidthResourceAllocation(Bandwidth bandwidth) {
21 + super(bandwidth);
22 + }
8 } 23 }
......
...@@ -3,11 +3,39 @@ package org.onlab.onos.net.resource; ...@@ -3,11 +3,39 @@ package org.onlab.onos.net.resource;
3 /** 3 /**
4 * Representation of a request for bandwidth resource. 4 * Representation of a request for bandwidth resource.
5 */ 5 */
6 -public interface BandwidthResourceRequest { 6 +public class BandwidthResourceRequest implements ResourceRequest {
7 + private final Bandwidth bandwidth;
8 +
9 + /**
10 + * Creates a new {@link BandwidthResourceRequest} with {@link Bandwidth}
11 + * object.
12 + *
13 + * @param bandwidth {@link Bandwidth} object to be requested
14 + */
15 + public BandwidthResourceRequest(Bandwidth bandwidth) {
16 + this.bandwidth = bandwidth;
17 + }
18 +
19 + /**
20 + * Creates a new {@link BandwidthResourceRequest} with bandwidth value.
21 + *
22 + * @param bandwidth bandwidth value to be requested
23 + */
24 + public BandwidthResourceRequest(double bandwidth) {
25 + this.bandwidth = Bandwidth.valueOf(bandwidth);
26 + }
27 +
7 /** 28 /**
8 * Returns the bandwidth resource. 29 * Returns the bandwidth resource.
9 * 30 *
10 * @return the bandwidth resource 31 * @return the bandwidth resource
11 */ 32 */
12 - Bandwidth bandwidth(); 33 + public Bandwidth bandwidth() {
34 + return bandwidth;
35 + }
36 +
37 + @Override
38 + public ResourceType type() {
39 + return ResourceType.BANDWIDTH;
40 + }
13 } 41 }
......
1 +package org.onlab.onos.net.resource;
2 +
3 +import java.util.Collection;
4 +import java.util.HashSet;
5 +import java.util.Set;
6 +
7 +import org.onlab.onos.net.Link;
8 +import org.onlab.onos.net.intent.IntentId;
9 +
10 +import com.google.common.collect.ImmutableSet;
11 +
12 +/**
13 + * Implementation of {@link LinkResourceRequest}.
14 + */
15 +public final class DefaultLinkResourceRequest implements LinkResourceRequest {
16 +
17 + private final IntentId intentId;
18 + private final Collection<Link> links;
19 + private final Set<ResourceRequest> resources;
20 +
21 + /**
22 + * Creates a new link resource request with the given ID, links, and
23 + * resource requests.
24 + *
25 + * @param intentId intent ID related to this request
26 + * @param links a set of links for the request
27 + * @param resources a set of resources to be requested
28 + */
29 + private DefaultLinkResourceRequest(IntentId intentId,
30 + Collection<Link> links,
31 + Set<ResourceRequest> resources) {
32 + this.intentId = intentId;
33 + this.links = ImmutableSet.copyOf(links);
34 + this.resources = ImmutableSet.copyOf(resources);
35 + }
36 +
37 +
38 + @Override
39 + public ResourceType type() {
40 + return null;
41 + }
42 +
43 + @Override
44 + public IntentId intendId() {
45 + return intentId;
46 + }
47 +
48 + @Override
49 + public Collection<Link> links() {
50 + return links;
51 + }
52 +
53 + @Override
54 + public Set<ResourceRequest> resources() {
55 + return resources;
56 + }
57 +
58 + /**
59 + * Returns builder of link resource request.
60 + *
61 + * @param intentId intent ID related to this request
62 + * @param links a set of links for the request
63 + * @return builder of link resource request
64 + */
65 + public static LinkResourceRequest.Builder builder(
66 + IntentId intentId, Collection<Link> links) {
67 + return new Builder(intentId, links);
68 + }
69 +
70 + /**
71 + * Builder of link resource request.
72 + */
73 + public static final class Builder implements LinkResourceRequest.Builder {
74 + private IntentId intentId;
75 + private Collection<Link> links;
76 + private Set<ResourceRequest> resources;
77 +
78 + /**
79 + * Creates a new link resource request.
80 + *
81 + * @param intentId intent ID related to this request
82 + * @param links a set of links for the request
83 + */
84 + private Builder(IntentId intentId, Collection<Link> links) {
85 + this.intentId = intentId;
86 + this.links = links;
87 + this.resources = new HashSet<>();
88 + }
89 +
90 + /**
91 + * Adds lambda request.
92 + *
93 + * @return self
94 + */
95 + @Override
96 + public Builder addLambdaRequest() {
97 + resources.add(new LambdaResourceRequest());
98 + return this;
99 + }
100 +
101 + /**
102 + * Adds bandwidth request with bandwidth value.
103 + *
104 + * @param bandwidth bandwidth value to be requested
105 + * @return self
106 + */
107 + @Override
108 + public Builder addBandwidthRequest(double bandwidth) {
109 + resources.add(new BandwidthResourceRequest(bandwidth));
110 + return this;
111 + }
112 +
113 + /**
114 + * Returns link resource request.
115 + *
116 + * @return link resource request
117 + */
118 + @Override
119 + public LinkResourceRequest build() {
120 + return new DefaultLinkResourceRequest(intentId, links, resources);
121 + }
122 + }
123 +
124 +}
...@@ -3,11 +3,31 @@ package org.onlab.onos.net.resource; ...@@ -3,11 +3,31 @@ package org.onlab.onos.net.resource;
3 /** 3 /**
4 * Representation of allocated lambda resource. 4 * Representation of allocated lambda resource.
5 */ 5 */
6 -public interface LambdaResourceAllocation extends LambdaResourceRequest { 6 +public class LambdaResourceAllocation extends LambdaResourceRequest
7 + implements ResourceAllocation {
8 + private final Lambda lambda;
9 +
10 + @Override
11 + public ResourceType type() {
12 + return ResourceType.LAMBDA;
13 + }
14 +
15 + /**
16 + * Creates a new {@link LambdaResourceAllocation} with {@link Lambda}
17 + * object.
18 + *
19 + * @param lambda allocated lambda
20 + */
21 + public LambdaResourceAllocation(Lambda lambda) {
22 + this.lambda = lambda;
23 + }
24 +
7 /** 25 /**
8 * Returns the lambda resource. 26 * Returns the lambda resource.
9 * 27 *
10 * @return the lambda resource 28 * @return the lambda resource
11 */ 29 */
12 - Lambda lambda(); 30 + public Lambda lambda() {
31 + return lambda;
32 + }
13 } 33 }
......
...@@ -3,6 +3,11 @@ package org.onlab.onos.net.resource; ...@@ -3,6 +3,11 @@ package org.onlab.onos.net.resource;
3 /** 3 /**
4 * Representation of a request for lambda resource. 4 * Representation of a request for lambda resource.
5 */ 5 */
6 -public interface LambdaResourceRequest { 6 +public class LambdaResourceRequest implements ResourceRequest {
7 +
8 + @Override
9 + public ResourceType type() {
10 + return ResourceType.LAMBDA;
11 + }
7 12
8 } 13 }
......
1 package org.onlab.onos.net.resource; 1 package org.onlab.onos.net.resource;
2 2
3 +import java.util.Set;
4 +
3 import org.onlab.onos.net.Link; 5 import org.onlab.onos.net.Link;
4 6
5 /** 7 /**
...@@ -12,5 +14,5 @@ public interface LinkResourceAllocations extends LinkResourceRequest { ...@@ -12,5 +14,5 @@ public interface LinkResourceAllocations extends LinkResourceRequest {
12 * @param link the target link 14 * @param link the target link
13 * @return allocated resource for the link 15 * @return allocated resource for the link
14 */ 16 */
15 - ResourceAllocation getResourceAllocation(Link link); 17 + Set<ResourceAllocation> getResourceAllocation(Link link);
16 } 18 }
......
...@@ -31,4 +31,31 @@ public interface LinkResourceRequest extends ResourceRequest { ...@@ -31,4 +31,31 @@ public interface LinkResourceRequest extends ResourceRequest {
31 * @return the set of resource requests 31 * @return the set of resource requests
32 */ 32 */
33 Set<ResourceRequest> resources(); 33 Set<ResourceRequest> resources();
34 +
35 + /**
36 + * Builder of link resource request.
37 + */
38 + interface Builder {
39 + /**
40 + * Adds lambda request.
41 + *
42 + * @return self
43 + */
44 + public Builder addLambdaRequest();
45 +
46 + /**
47 + * Adds bandwidth request with bandwidth value.
48 + *
49 + * @param bandwidth bandwidth value to be requested
50 + * @return self
51 + */
52 + public Builder addBandwidthRequest(double bandwidth);
53 +
54 + /**
55 + * Returns link resource request.
56 + *
57 + * @return link resource request
58 + */
59 + public LinkResourceRequest build();
60 + }
34 } 61 }
......
...@@ -31,6 +31,14 @@ public interface LinkResourceService { ...@@ -31,6 +31,14 @@ public interface LinkResourceService {
31 Iterable<LinkResourceAllocations> getAllocations(); 31 Iterable<LinkResourceAllocations> getAllocations();
32 32
33 /** 33 /**
34 + * Returns the resources allocated for an Intent.
35 + *
36 + * @param intentId the target Intent's id
37 + * @return allocated resources for Intent
38 + */
39 + LinkResourceAllocations getAllocations(IntentId intentId);
40 +
41 + /**
34 * Returns all allocated resources to given link. 42 * Returns all allocated resources to given link.
35 * 43 *
36 * @param link a target link 44 * @param link a target link
......
...@@ -4,5 +4,11 @@ package org.onlab.onos.net.resource; ...@@ -4,5 +4,11 @@ package org.onlab.onos.net.resource;
4 * Abstraction of resource request. 4 * Abstraction of resource request.
5 */ 5 */
6 public interface ResourceRequest { 6 public interface ResourceRequest {
7 + /**
8 + * Returns the resource type.
9 + *
10 + * @return the resource type
11 + */
12 + ResourceType type();
7 13
8 } 14 }
......
1 +package org.onlab.onos.net.resource;
2 +
3 +public enum ResourceType {
4 + LAMBDA,
5 + BANDWIDTH,
6 +}
1 /** 1 /**
2 * Services for reserving network resources, e.g.&nbsp;bandwidth, lambdas. 2 * Services for reserving network resources, e.g.&nbsp;bandwidth, lambdas.
3 */ 3 */
4 -package org.onlab.onos.net.resource;
...\ No newline at end of file ...\ No newline at end of file
4 +package org.onlab.onos.net.resource;
......
1 +/*
2 + * Licensed to the Apache Software Foundation (ASF) under one
3 + * or more contributor license agreements. See the NOTICE file
4 + * distributed with this work for additional information
5 + * regarding copyright ownership. The ASF licenses this file
6 + * to you under the Apache License, Version 2.0 (the
7 + * "License"); you may not use this file except in compliance
8 + * with the License. You may obtain a copy of the License at
9 + *
10 + * http://www.apache.org/licenses/LICENSE-2.0
11 + *
12 + * Unless required by applicable law or agreed to in writing,
13 + * software distributed under the License is distributed on an
14 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 + * KIND, either express or implied. See the License for the
16 + * specific language governing permissions and limitations
17 + * under the License.
18 + */
19 +package org.onlab.onos.codec;
20 +
21 +import com.fasterxml.jackson.databind.ObjectMapper;
22 +import com.fasterxml.jackson.databind.node.ArrayNode;
23 +import com.fasterxml.jackson.databind.node.ObjectNode;
24 +import com.google.common.collect.ImmutableList;
25 +import org.junit.Test;
26 +
27 +import java.util.List;
28 +import java.util.Objects;
29 +
30 +import static org.junit.Assert.assertEquals;
31 +
32 +/**
33 + * Test of the base JSON codec abstraction.
34 + */
35 +public class JsonCodecTest {
36 +
37 + private static class Foo {
38 + final String name;
39 +
40 + Foo(String name) {
41 + this.name = name;
42 + }
43 +
44 + @Override
45 + public int hashCode() {
46 + return Objects.hash(name);
47 + }
48 +
49 + @Override
50 + public boolean equals(Object obj) {
51 + if (this == obj) {
52 + return true;
53 + }
54 + if (obj == null || getClass() != obj.getClass()) {
55 + return false;
56 + }
57 + final Foo other = (Foo) obj;
58 + return Objects.equals(this.name, other.name);
59 + }
60 + }
61 +
62 + private static class FooCodec extends JsonCodec<Foo> {
63 + @Override
64 + public ObjectNode encode(Foo entity, ObjectMapper mapper) {
65 + return mapper.createObjectNode().put("name", entity.name);
66 + }
67 +
68 + @Override
69 + public Foo decode(ObjectNode json) {
70 + return new Foo(json.get("name").asText());
71 + }
72 + }
73 +
74 + @Test
75 + public void encode() {
76 + Foo f1 = new Foo("foo");
77 + Foo f2 = new Foo("bar");
78 + FooCodec codec = new FooCodec();
79 + ImmutableList<Foo> entities = ImmutableList.of(f1, f2);
80 + ArrayNode json = codec.encode(entities, new ObjectMapper());
81 + List<Foo> foos = codec.decode(json);
82 + assertEquals("incorrect encode/decode", entities, foos);
83 + }
84 +
85 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -2,11 +2,15 @@ package org.onlab.onos.net.flow.impl; ...@@ -2,11 +2,15 @@ package org.onlab.onos.net.flow.impl;
2 2
3 import static com.google.common.base.Preconditions.checkNotNull; 3 import static com.google.common.base.Preconditions.checkNotNull;
4 import static org.slf4j.LoggerFactory.getLogger; 4 import static org.slf4j.LoggerFactory.getLogger;
5 +import static org.onlab.util.Tools.namedThreads;
5 6
6 import java.util.List; 7 import java.util.List;
7 import java.util.Map; 8 import java.util.Map;
9 +import java.util.Set;
8 import java.util.concurrent.CancellationException; 10 import java.util.concurrent.CancellationException;
9 import java.util.concurrent.ExecutionException; 11 import java.util.concurrent.ExecutionException;
12 +import java.util.concurrent.ExecutorService;
13 +import java.util.concurrent.Executors;
10 import java.util.concurrent.Future; 14 import java.util.concurrent.Future;
11 import java.util.concurrent.TimeUnit; 15 import java.util.concurrent.TimeUnit;
12 import java.util.concurrent.TimeoutException; 16 import java.util.concurrent.TimeoutException;
...@@ -30,7 +34,9 @@ import org.onlab.onos.net.flow.FlowEntry; ...@@ -30,7 +34,9 @@ import org.onlab.onos.net.flow.FlowEntry;
30 import org.onlab.onos.net.flow.FlowRule; 34 import org.onlab.onos.net.flow.FlowRule;
31 import org.onlab.onos.net.flow.FlowRuleBatchEntry; 35 import org.onlab.onos.net.flow.FlowRuleBatchEntry;
32 import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation; 36 import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
37 +import org.onlab.onos.net.flow.FlowRuleBatchEvent;
33 import org.onlab.onos.net.flow.FlowRuleBatchOperation; 38 import org.onlab.onos.net.flow.FlowRuleBatchOperation;
39 +import org.onlab.onos.net.flow.FlowRuleBatchRequest;
34 import org.onlab.onos.net.flow.FlowRuleEvent; 40 import org.onlab.onos.net.flow.FlowRuleEvent;
35 import org.onlab.onos.net.flow.FlowRuleListener; 41 import org.onlab.onos.net.flow.FlowRuleListener;
36 import org.onlab.onos.net.flow.FlowRuleProvider; 42 import org.onlab.onos.net.flow.FlowRuleProvider;
...@@ -47,6 +53,9 @@ import com.google.common.collect.ArrayListMultimap; ...@@ -47,6 +53,9 @@ import com.google.common.collect.ArrayListMultimap;
47 import com.google.common.collect.Lists; 53 import com.google.common.collect.Lists;
48 import com.google.common.collect.Maps; 54 import com.google.common.collect.Maps;
49 import com.google.common.collect.Multimap; 55 import com.google.common.collect.Multimap;
56 +import com.google.common.collect.Sets;
57 +import com.google.common.util.concurrent.Futures;
58 +import com.google.common.util.concurrent.ListenableFuture;
50 59
51 /** 60 /**
52 * Provides implementation of the flow NB &amp; SB APIs. 61 * Provides implementation of the flow NB &amp; SB APIs.
...@@ -67,6 +76,9 @@ public class FlowRuleManager ...@@ -67,6 +76,9 @@ public class FlowRuleManager
67 76
68 private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate(); 77 private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate();
69 78
79 + private final ExecutorService futureListeners =
80 + Executors.newCachedThreadPool(namedThreads("provider-future-listeners"));
81 +
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected FlowRuleStore store; 83 protected FlowRuleStore store;
72 84
...@@ -85,6 +97,8 @@ public class FlowRuleManager ...@@ -85,6 +97,8 @@ public class FlowRuleManager
85 97
86 @Deactivate 98 @Deactivate
87 public void deactivate() { 99 public void deactivate() {
100 + futureListeners.shutdownNow();
101 +
88 store.unsetDelegate(delegate); 102 store.unsetDelegate(delegate);
89 eventDispatcher.removeSink(FlowRuleEvent.class); 103 eventDispatcher.removeSink(FlowRuleEvent.class);
90 log.info("Stopped"); 104 log.info("Stopped");
...@@ -104,14 +118,7 @@ public class FlowRuleManager ...@@ -104,14 +118,7 @@ public class FlowRuleManager
104 public void applyFlowRules(FlowRule... flowRules) { 118 public void applyFlowRules(FlowRule... flowRules) {
105 for (int i = 0; i < flowRules.length; i++) { 119 for (int i = 0; i < flowRules.length; i++) {
106 FlowRule f = flowRules[i]; 120 FlowRule f = flowRules[i];
107 - boolean local = store.storeFlowRule(f); 121 + store.storeFlowRule(f);
108 - if (local) {
109 - // TODO: aggregate all local rules and push down once?
110 - applyFlowRulesToProviders(f);
111 - eventDispatcher.post(
112 - new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADD_REQUESTED, f));
113 -
114 - }
115 } 122 }
116 } 123 }
117 124
...@@ -135,13 +142,7 @@ public class FlowRuleManager ...@@ -135,13 +142,7 @@ public class FlowRuleManager
135 FlowRule f; 142 FlowRule f;
136 for (int i = 0; i < flowRules.length; i++) { 143 for (int i = 0; i < flowRules.length; i++) {
137 f = flowRules[i]; 144 f = flowRules[i];
138 - boolean local = store.deleteFlowRule(f); 145 + store.deleteFlowRule(f);
139 - if (local) {
140 - // TODO: aggregate all local rules and push down once?
141 - removeFlowRulesFromProviders(f);
142 - eventDispatcher.post(
143 - new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVE_REQUESTED, f));
144 - }
145 } 146 }
146 } 147 }
147 148
...@@ -185,33 +186,21 @@ public class FlowRuleManager ...@@ -185,33 +186,21 @@ public class FlowRuleManager
185 @Override 186 @Override
186 public Future<CompletedBatchOperation> applyBatch( 187 public Future<CompletedBatchOperation> applyBatch(
187 FlowRuleBatchOperation batch) { 188 FlowRuleBatchOperation batch) {
188 - Multimap<FlowRuleProvider, FlowRuleBatchEntry> batches = 189 + Multimap<DeviceId, FlowRuleBatchEntry> perDeviceBatches =
189 ArrayListMultimap.create(); 190 ArrayListMultimap.create();
190 List<Future<CompletedBatchOperation>> futures = Lists.newArrayList(); 191 List<Future<CompletedBatchOperation>> futures = Lists.newArrayList();
191 for (FlowRuleBatchEntry fbe : batch.getOperations()) { 192 for (FlowRuleBatchEntry fbe : batch.getOperations()) {
192 final FlowRule f = fbe.getTarget(); 193 final FlowRule f = fbe.getTarget();
193 - final Device device = deviceService.getDevice(f.deviceId()); 194 + perDeviceBatches.put(f.deviceId(), fbe);
194 - final FlowRuleProvider frp = getProvider(device.providerId());
195 - batches.put(frp, fbe);
196 - switch (fbe.getOperator()) {
197 - case ADD:
198 - store.storeFlowRule(f);
199 - break;
200 - case REMOVE:
201 - store.deleteFlowRule(f);
202 - break;
203 - case MODIFY:
204 - default:
205 - log.error("Batch operation type {} unsupported.", fbe.getOperator());
206 - }
207 } 195 }
208 - for (FlowRuleProvider provider : batches.keySet()) { 196 +
197 + for (DeviceId deviceId : perDeviceBatches.keySet()) {
209 FlowRuleBatchOperation b = 198 FlowRuleBatchOperation b =
210 - new FlowRuleBatchOperation(batches.get(provider)); 199 + new FlowRuleBatchOperation(perDeviceBatches.get(deviceId));
211 - Future<CompletedBatchOperation> future = provider.executeBatch(b); 200 + Future<CompletedBatchOperation> future = store.storeBatch(b);
212 futures.add(future); 201 futures.add(future);
213 } 202 }
214 - return new FlowRuleBatchFuture(futures, batches); 203 + return new FlowRuleBatchFuture(futures, perDeviceBatches);
215 } 204 }
216 205
217 @Override 206 @Override
...@@ -324,6 +313,7 @@ public class FlowRuleManager ...@@ -324,6 +313,7 @@ public class FlowRuleManager
324 post(event); 313 post(event);
325 } 314 }
326 } else { 315 } else {
316 + log.info("Removing flow rules....");
327 removeFlowRules(flowEntry); 317 removeFlowRules(flowEntry);
328 } 318 }
329 319
...@@ -391,21 +381,48 @@ public class FlowRuleManager ...@@ -391,21 +381,48 @@ public class FlowRuleManager
391 381
392 // Store delegate to re-post events emitted from the store. 382 // Store delegate to re-post events emitted from the store.
393 private class InternalStoreDelegate implements FlowRuleStoreDelegate { 383 private class InternalStoreDelegate implements FlowRuleStoreDelegate {
384 + // TODO: Right now we only dispatch events at individual flowEntry level.
385 + // It may be more efficient for also dispatch events as a batch.
394 @Override 386 @Override
395 - public void notify(FlowRuleEvent event) { 387 + public void notify(FlowRuleBatchEvent event) {
388 + final FlowRuleBatchRequest request = event.subject();
396 switch (event.type()) { 389 switch (event.type()) {
397 - case RULE_ADD_REQUESTED: 390 + case BATCH_OPERATION_REQUESTED:
398 - applyFlowRulesToProviders(event.subject()); 391 + for (FlowEntry entry : request.toAdd()) {
399 - break; 392 + eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADD_REQUESTED, entry));
400 - case RULE_REMOVE_REQUESTED: 393 + }
401 - removeFlowRulesFromProviders(event.subject()); 394 + for (FlowEntry entry : request.toRemove()) {
402 - break; 395 + eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVE_REQUESTED, entry));
396 + }
397 + // FIXME: what about op.equals(FlowRuleOperation.MODIFY) ?
398 +
399 + FlowRuleBatchOperation batchOperation = request.asBatchOperation();
400 +
401 + FlowRuleProvider flowRuleProvider =
402 + getProvider(batchOperation.getOperations().get(0).getTarget().deviceId());
403 + final ListenableFuture<CompletedBatchOperation> result =
404 + flowRuleProvider.executeBatch(batchOperation);
405 + result.addListener(new Runnable() {
406 + @Override
407 + public void run() {
408 + store.batchOperationComplete(FlowRuleBatchEvent.completed(request,
409 + Futures.getUnchecked(result)));
410 + }
411 + }, futureListeners);
403 412
404 - case RULE_ADDED: 413 + break;
405 - case RULE_REMOVED: 414 + case BATCH_OPERATION_COMPLETED:
406 - case RULE_UPDATED: 415 + Set<FlowEntry> failedItems = event.result().failedItems();
407 - // only dispatch events related to switch 416 + for (FlowEntry entry : request.toAdd()) {
408 - eventDispatcher.post(event); 417 + if (!failedItems.contains(entry)) {
418 + eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADDED, entry));
419 + }
420 + }
421 + for (FlowEntry entry : request.toRemove()) {
422 + if (!failedItems.contains(entry)) {
423 + eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVED, entry));
424 + }
425 + }
409 break; 426 break;
410 default: 427 default:
411 break; 428 break;
...@@ -413,18 +430,15 @@ public class FlowRuleManager ...@@ -413,18 +430,15 @@ public class FlowRuleManager
413 } 430 }
414 } 431 }
415 432
416 - private class FlowRuleBatchFuture 433 + private class FlowRuleBatchFuture implements Future<CompletedBatchOperation> {
417 - implements Future<CompletedBatchOperation> {
418 434
419 private final List<Future<CompletedBatchOperation>> futures; 435 private final List<Future<CompletedBatchOperation>> futures;
420 - private final Multimap<FlowRuleProvider, FlowRuleBatchEntry> batches; 436 + private final Multimap<DeviceId, FlowRuleBatchEntry> batches;
421 private final AtomicReference<BatchState> state; 437 private final AtomicReference<BatchState> state;
422 private CompletedBatchOperation overall; 438 private CompletedBatchOperation overall;
423 439
424 -
425 -
426 public FlowRuleBatchFuture(List<Future<CompletedBatchOperation>> futures, 440 public FlowRuleBatchFuture(List<Future<CompletedBatchOperation>> futures,
427 - Multimap<FlowRuleProvider, FlowRuleBatchEntry> batches) { 441 + Multimap<DeviceId, FlowRuleBatchEntry> batches) {
428 this.futures = futures; 442 this.futures = futures;
429 this.batches = batches; 443 this.batches = batches;
430 state = new AtomicReference<FlowRuleManager.BatchState>(); 444 state = new AtomicReference<FlowRuleManager.BatchState>();
...@@ -466,7 +480,7 @@ public class FlowRuleManager ...@@ -466,7 +480,7 @@ public class FlowRuleManager
466 } 480 }
467 481
468 boolean success = true; 482 boolean success = true;
469 - List<FlowEntry> failed = Lists.newLinkedList(); 483 + Set<FlowEntry> failed = Sets.newHashSet();
470 CompletedBatchOperation completed; 484 CompletedBatchOperation completed;
471 for (Future<CompletedBatchOperation> future : futures) { 485 for (Future<CompletedBatchOperation> future : futures) {
472 completed = future.get(); 486 completed = future.get();
...@@ -486,7 +500,7 @@ public class FlowRuleManager ...@@ -486,7 +500,7 @@ public class FlowRuleManager
486 return overall; 500 return overall;
487 } 501 }
488 boolean success = true; 502 boolean success = true;
489 - List<FlowEntry> failed = Lists.newLinkedList(); 503 + Set<FlowEntry> failed = Sets.newHashSet();
490 CompletedBatchOperation completed; 504 CompletedBatchOperation completed;
491 long start = System.nanoTime(); 505 long start = System.nanoTime();
492 long end = start + unit.toNanos(timeout); 506 long end = start + unit.toNanos(timeout);
...@@ -500,7 +514,7 @@ public class FlowRuleManager ...@@ -500,7 +514,7 @@ public class FlowRuleManager
500 return finalizeBatchOperation(success, failed); 514 return finalizeBatchOperation(success, failed);
501 } 515 }
502 516
503 - private boolean validateBatchOperation(List<FlowEntry> failed, 517 + private boolean validateBatchOperation(Set<FlowEntry> failed,
504 CompletedBatchOperation completed) { 518 CompletedBatchOperation completed) {
505 519
506 if (isCancelled()) { 520 if (isCancelled()) {
...@@ -522,7 +536,7 @@ public class FlowRuleManager ...@@ -522,7 +536,7 @@ public class FlowRuleManager
522 } 536 }
523 537
524 private CompletedBatchOperation finalizeBatchOperation(boolean success, 538 private CompletedBatchOperation finalizeBatchOperation(boolean success,
525 - List<FlowEntry> failed) { 539 + Set<FlowEntry> failed) {
526 synchronized (this) { 540 synchronized (this) {
527 if (!state.compareAndSet(BatchState.STARTED, BatchState.FINISHED)) { 541 if (!state.compareAndSet(BatchState.STARTED, BatchState.FINISHED)) {
528 if (state.get() == BatchState.FINISHED) { 542 if (state.get() == BatchState.FINISHED) {
...@@ -545,11 +559,6 @@ public class FlowRuleManager ...@@ -545,11 +559,6 @@ public class FlowRuleManager
545 store.storeFlowRule(fbe.getTarget()); 559 store.storeFlowRule(fbe.getTarget());
546 } 560 }
547 } 561 }
548 -
549 } 562 }
550 } 563 }
551 -
552 -
553 -
554 -
555 } 564 }
......
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import java.util.ArrayList;
6 +import java.util.Iterator;
7 +import java.util.List;
8 +import java.util.Set;
9 +
10 +import org.apache.felix.scr.annotations.Activate;
11 +import org.apache.felix.scr.annotations.Component;
12 +import org.apache.felix.scr.annotations.Deactivate;
13 +import org.apache.felix.scr.annotations.Reference;
14 +import org.apache.felix.scr.annotations.ReferenceCardinality;
15 +import org.onlab.onos.CoreService;
16 +import org.onlab.onos.net.ConnectPoint;
17 +import org.onlab.onos.net.Link;
18 +import org.onlab.onos.net.Path;
19 +import org.onlab.onos.net.intent.Intent;
20 +import org.onlab.onos.net.intent.IntentCompiler;
21 +import org.onlab.onos.net.intent.IntentExtensionService;
22 +import org.onlab.onos.net.intent.OpticalConnectivityIntent;
23 +import org.onlab.onos.net.intent.OpticalPathIntent;
24 +import org.onlab.onos.net.provider.ProviderId;
25 +import org.onlab.onos.net.resource.LinkResourceService;
26 +import org.onlab.onos.net.topology.LinkWeight;
27 +import org.onlab.onos.net.topology.PathService;
28 +import org.onlab.onos.net.topology.Topology;
29 +import org.onlab.onos.net.topology.TopologyEdge;
30 +import org.onlab.onos.net.topology.TopologyService;
31 +import org.slf4j.Logger;
32 +
33 +/**
34 + * Optical compiler for OpticalConnectivityIntent.
35 + * It firstly computes K-shortest paths in the optical-layer, then choose the optimal one to assign a wavelength.
36 + * Finally, it generates one or more opticalPathintent(s) with opticalMatchs and opticalActions.
37 + */
38 +@Component(immediate = true)
39 +public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
40 +
41 + private final Logger log = getLogger(getClass());
42 + private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true);
43 +
44 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
45 + protected IntentExtensionService intentManager;
46 +
47 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
48 + protected PathService pathService;
49 +
50 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 + protected TopologyService topologyService;
52 +
53 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
54 + protected LinkResourceService resourceService;
55 +
56 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
57 + protected CoreService coreService;
58 +
59 + @Activate
60 + public void activate() {
61 + intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
62 + }
63 +
64 + @Deactivate
65 + public void deactivate() {
66 + intentManager.unregisterCompiler(OpticalConnectivityIntent.class);
67 + }
68 +
69 + @Override
70 + public List<Intent> compile(OpticalConnectivityIntent intent) {
71 + // TODO: compute multiple paths using the K-shortest path algorithm
72 + List<Intent> retList = new ArrayList<>();
73 + Path path = calculatePath(intent.getSrcConnectPoint(), intent.getDst());
74 + if (path == null) {
75 + return retList;
76 + } else {
77 + log.info("the computed lightpath is : {}.", path.toString());
78 + }
79 +
80 + List<Link> links = new ArrayList<>();
81 + // links.add(DefaultEdgeLink.createEdgeLink(intent.getSrcConnectPoint(), true));
82 + links.addAll(path.links());
83 + //links.add(DefaultEdgeLink.createEdgeLink(intent.getDst(), false));
84 +
85 + // create a new opticalPathIntent
86 + Intent newIntent = new OpticalPathIntent(intent.appId(),
87 + intent.getSrcConnectPoint(),
88 + intent.getDst(),
89 + path);
90 +
91 + retList.add(newIntent);
92 +
93 + return retList;
94 + }
95 +
96 + private Path calculatePath(ConnectPoint start, ConnectPoint end) {
97 + // TODO: support user policies
98 + Topology topology = topologyService.currentTopology();
99 + LinkWeight weight = new LinkWeight() {
100 + @Override
101 + public double weight(TopologyEdge edge) {
102 + boolean isOptical = false;
103 +
104 + Link.Type lt = edge.link().type();
105 +
106 + //String t = edge.link().annotations().value("linkType");
107 + if (lt == Link.Type.OPTICAL) {
108 + isOptical = true;
109 + }
110 + if (isOptical) {
111 + return 1; // optical links
112 + } else {
113 + return 10000; // packet links
114 + }
115 + }
116 + };
117 +
118 + Set<Path> paths = topologyService.getPaths(topology,
119 + start.deviceId(),
120 + end.deviceId(),
121 + weight);
122 +
123 + Iterator<Path> itr = paths.iterator();
124 + while (itr.hasNext()) {
125 + Path path = itr.next();
126 + if (path.cost() >= 10000) {
127 + itr.remove();
128 + }
129 + }
130 +
131 + if (paths.isEmpty()) {
132 + log.info("No optical path found from " + start + " to " + end);
133 + return null;
134 + } else {
135 + return paths.iterator().next();
136 + }
137 +
138 + }
139 +
140 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
4 +import static org.slf4j.LoggerFactory.getLogger;
5 +
6 +import java.util.List;
7 +
8 +import org.apache.felix.scr.annotations.Activate;
9 +import org.apache.felix.scr.annotations.Component;
10 +import org.apache.felix.scr.annotations.Deactivate;
11 +import org.apache.felix.scr.annotations.Reference;
12 +import org.apache.felix.scr.annotations.ReferenceCardinality;
13 +import org.onlab.onos.ApplicationId;
14 +import org.onlab.onos.CoreService;
15 +import org.onlab.onos.net.ConnectPoint;
16 +import org.onlab.onos.net.Link;
17 +import org.onlab.onos.net.flow.DefaultFlowRule;
18 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
19 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
20 +import org.onlab.onos.net.flow.FlowRule;
21 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
22 +import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
23 +import org.onlab.onos.net.flow.FlowRuleBatchOperation;
24 +import org.onlab.onos.net.flow.FlowRuleService;
25 +import org.onlab.onos.net.flow.TrafficSelector;
26 +import org.onlab.onos.net.flow.TrafficTreatment;
27 +import org.onlab.onos.net.intent.IntentExtensionService;
28 +import org.onlab.onos.net.intent.IntentInstaller;
29 +import org.onlab.onos.net.intent.OpticalPathIntent;
30 +import org.onlab.onos.net.resource.DefaultLinkResourceRequest;
31 +import org.onlab.onos.net.resource.Lambda;
32 +import org.onlab.onos.net.resource.LambdaResourceAllocation;
33 +import org.onlab.onos.net.resource.LinkResourceAllocations;
34 +import org.onlab.onos.net.resource.LinkResourceRequest;
35 +import org.onlab.onos.net.resource.LinkResourceService;
36 +import org.onlab.onos.net.resource.ResourceAllocation;
37 +import org.onlab.onos.net.resource.ResourceType;
38 +import org.onlab.onos.net.topology.TopologyService;
39 +import org.slf4j.Logger;
40 +
41 +import com.google.common.collect.Lists;
42 +
43 +/**
44 + * OpticaliIntentInstaller for optical path intents.
45 + * It essentially generates optical FlowRules and
46 + * call the flowRule service to execute them.
47 + */
48 +
49 +@Component(immediate = true)
50 +public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIntent> {
51 + private final Logger log = getLogger(getClass());
52 +
53 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
54 + protected IntentExtensionService intentManager;
55 +
56 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
57 + protected FlowRuleService flowRuleService;
58 +
59 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 + protected CoreService coreService;
61 +
62 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 + protected TopologyService topologyService;
64 +
65 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 + protected LinkResourceService resourceService;
67 +
68 + private ApplicationId appId;
69 +
70 + //final short WAVELENGTH = 80;
71 +
72 + @Activate
73 + public void activate() {
74 + appId = coreService.registerApplication("org.onlab.onos.net.intent");
75 + intentManager.registerInstaller(OpticalPathIntent.class, this);
76 + }
77 +
78 + @Deactivate
79 + public void deactivate() {
80 + intentManager.unregisterInstaller(OpticalPathIntent.class);
81 + }
82 +
83 + @Override
84 + public List<FlowRuleBatchOperation> install(OpticalPathIntent intent) {
85 + LinkResourceAllocations allocations = assignWavelength(intent);
86 +
87 + TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
88 + selectorBuilder.matchInport(intent.src().port());
89 +
90 + List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
91 + ConnectPoint prev = intent.src();
92 +
93 + //TODO throw exception if the lambda was not assigned successfully
94 + for (Link link : intent.path().links()) {
95 + Lambda la = null;
96 + for (ResourceAllocation allocation : allocations.getResourceAllocation(link)) {
97 + if (allocation.type() == ResourceType.LAMBDA) {
98 + la = ((LambdaResourceAllocation) allocation).lambda();
99 + break;
100 + }
101 + }
102 +
103 + if (la == null) {
104 + log.info("Lambda was not assigned successfully");
105 + return null;
106 + }
107 +
108 + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
109 + treatmentBuilder.setOutput(link.src().port());
110 + treatmentBuilder.setLambda((short) la.toInt());
111 +
112 + FlowRule rule = new DefaultFlowRule(prev.deviceId(),
113 + selectorBuilder.build(),
114 + treatmentBuilder.build(),
115 + 100,
116 + appId,
117 + 100,
118 + true);
119 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
120 +
121 + prev = link.dst();
122 + selectorBuilder.matchInport(link.dst().port());
123 + selectorBuilder.matchLambda((short) la.toInt());
124 + }
125 +
126 + // build the last T port rule
127 + TrafficTreatment treatmentLast = builder()
128 + .setOutput(intent.dst().port()).build();
129 + FlowRule rule = new DefaultFlowRule(intent.dst().deviceId(),
130 + selectorBuilder.build(),
131 + treatmentLast,
132 + 100,
133 + appId,
134 + 100,
135 + true);
136 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
137 +
138 + return Lists.newArrayList(new FlowRuleBatchOperation(rules));
139 + }
140 +
141 + private LinkResourceAllocations assignWavelength(OpticalPathIntent intent) {
142 + LinkResourceRequest.Builder request = DefaultLinkResourceRequest.builder(intent.id(),
143 + intent.path().links())
144 + .addLambdaRequest();
145 + LinkResourceAllocations retLambda = resourceService.requestResources(request.build());
146 + return retLambda;
147 + }
148 +
149 + /*private Lambda assignWavelength(List<Link> links) {
150 + // TODO More wavelength assignment algorithm
151 + int wavenum = 0;
152 + Iterator<Link> itrlink = links.iterator();
153 + for (int i = 1; i <= WAVELENGTH; i++) {
154 + wavenum = i;
155 + boolean found = true;
156 + while (itrlink.hasNext()) {
157 + Link link = itrlink.next();
158 + if (isWavelengthUsed(link, i)) {
159 + found = false;
160 + break;
161 + }
162 + }
163 + // First-Fit wavelength assignment algorithm
164 + if (found) {
165 + break;
166 + }
167 + }
168 +
169 + if (wavenum == 0) {
170 + return null;
171 + }
172 +
173 + Lambda wave = Lambda.valueOf(wavenum);
174 + return wave;
175 + }
176 +
177 + private boolean isWavelengthUsed(Link link, int i) {
178 + Iterable<LinkResourceAllocations> wave = resourceService.getAllocations(link);
179 + for (LinkResourceAllocations ir : wave) {
180 + //if ir.resources().contains(i) {
181 + //}
182 + }
183 + return false;
184 + }*/
185 +
186 + @Override
187 + public List<FlowRuleBatchOperation> uninstall(OpticalPathIntent intent) {
188 + LinkResourceAllocations allocations = resourceService.getAllocations(intent.id());
189 +
190 + TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
191 + selectorBuilder.matchInport(intent.src().port());
192 +
193 + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
194 +
195 + List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
196 + ConnectPoint prev = intent.src();
197 +
198 + //TODO throw exception if the lambda was not retrieved successfully
199 + for (Link link : intent.path().links()) {
200 + Lambda la = null;
201 + for (ResourceAllocation allocation : allocations.getResourceAllocation(link)) {
202 + if (allocation.type() == ResourceType.LAMBDA) {
203 + la = ((LambdaResourceAllocation) allocation).lambda();
204 + break;
205 + }
206 + }
207 +
208 + if (la == null) {
209 + log.info("Lambda was not retrieved successfully");
210 + return null;
211 + }
212 +
213 + treatmentBuilder.setOutput(link.src().port());
214 + treatmentBuilder.setLambda((short) la.toInt());
215 +
216 + FlowRule rule = new DefaultFlowRule(prev.deviceId(),
217 + selectorBuilder.build(),
218 + treatmentBuilder.build(),
219 + 100,
220 + appId,
221 + 100,
222 + true);
223 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
224 +
225 + prev = link.dst();
226 + selectorBuilder.matchInport(link.dst().port());
227 + selectorBuilder.matchLambda((short) la.toInt());
228 + }
229 +
230 + // build the last T port rule
231 + TrafficTreatment treatmentLast = builder()
232 + .setOutput(intent.dst().port()).build();
233 + FlowRule rule = new DefaultFlowRule(intent.dst().deviceId(),
234 + selectorBuilder.build(),
235 + treatmentLast,
236 + 100,
237 + appId,
238 + 100,
239 + true);
240 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
241 +
242 + return Lists.newArrayList(new FlowRuleBatchOperation(rules));
243 + }
244 +
245 +}
1 +package org.onlab.onos.net.resource.impl;
2 +
3 +import java.util.Collection;
4 +import java.util.Collections;
5 +import java.util.Map;
6 +import java.util.Set;
7 +
8 +import org.onlab.onos.net.Link;
9 +import org.onlab.onos.net.intent.IntentId;
10 +import org.onlab.onos.net.resource.LinkResourceAllocations;
11 +import org.onlab.onos.net.resource.LinkResourceRequest;
12 +import org.onlab.onos.net.resource.ResourceAllocation;
13 +import org.onlab.onos.net.resource.ResourceRequest;
14 +import org.onlab.onos.net.resource.ResourceType;
15 +
16 +/**
17 + * Implementation of {@link LinkResourceAllocations}.
18 + */
19 +public class DefaultLinkResourceAllocations implements LinkResourceAllocations {
20 + private final LinkResourceRequest request;
21 + private final Map<Link, Set<ResourceAllocation>> allocations;
22 +
23 + /**
24 + * Creates a new link resource allocations.
25 + *
26 + * @param request requested resources
27 + * @param allocations allocated resources
28 + */
29 + protected DefaultLinkResourceAllocations(LinkResourceRequest request,
30 + Map<Link, Set<ResourceAllocation>> allocations) {
31 + this.request = request;
32 + this.allocations = allocations;
33 + }
34 +
35 + @Override
36 + public IntentId intendId() {
37 + return request.intendId();
38 + }
39 +
40 + @Override
41 + public Collection<Link> links() {
42 + return request.links();
43 + }
44 +
45 + @Override
46 + public Set<ResourceRequest> resources() {
47 + return request.resources();
48 + }
49 +
50 + @Override
51 + public ResourceType type() {
52 + return null;
53 + }
54 +
55 + @Override
56 + public Set<ResourceAllocation> getResourceAllocation(Link link) {
57 + Set<ResourceAllocation> result = allocations.get(link);
58 + if (result == null) {
59 + result = Collections.emptySet();
60 + }
61 + return result;
62 + }
63 +
64 +}
1 +package org.onlab.onos.net.resource.impl;
2 +
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import java.util.HashMap;
6 +import java.util.Map;
7 +import java.util.Set;
8 +
9 +import org.apache.felix.scr.annotations.Activate;
10 +import org.apache.felix.scr.annotations.Component;
11 +import org.apache.felix.scr.annotations.Deactivate;
12 +import org.apache.felix.scr.annotations.Service;
13 +import org.onlab.onos.net.Link;
14 +import org.onlab.onos.net.intent.IntentId;
15 +import org.onlab.onos.net.resource.BandwidthResourceAllocation;
16 +import org.onlab.onos.net.resource.BandwidthResourceRequest;
17 +import org.onlab.onos.net.resource.Lambda;
18 +import org.onlab.onos.net.resource.LambdaResourceAllocation;
19 +import org.onlab.onos.net.resource.LinkResourceAllocations;
20 +import org.onlab.onos.net.resource.LinkResourceRequest;
21 +import org.onlab.onos.net.resource.LinkResourceService;
22 +import org.onlab.onos.net.resource.ResourceAllocation;
23 +import org.onlab.onos.net.resource.ResourceRequest;
24 +import org.slf4j.Logger;
25 +
26 +import com.google.common.collect.Sets;
27 +
28 +/**
29 + * Provides basic implementation of link resources allocation.
30 + */
31 +@Component(immediate = true)
32 +@Service
33 +public class LinkResourceManager implements LinkResourceService {
34 +
35 + private final Logger log = getLogger(getClass());
36 +
37 + @Activate
38 + public void activate() {
39 + log.info("Started");
40 + }
41 +
42 + @Deactivate
43 + public void deactivate() {
44 + log.info("Stopped");
45 + }
46 +
47 + @Override
48 + public LinkResourceAllocations requestResources(LinkResourceRequest req) {
49 + // TODO implement it using a resource data store.
50 +
51 + ResourceAllocation alloc = null;
52 + for (ResourceRequest r: req.resources()) {
53 + switch (r.type()) {
54 + case BANDWIDTH:
55 + log.info("requestResources() always returns requested bandwidth");
56 + BandwidthResourceRequest br = (BandwidthResourceRequest) r;
57 + alloc = new BandwidthResourceAllocation(br.bandwidth());
58 + break;
59 + case LAMBDA:
60 + log.info("requestResources() always returns lambda 7");
61 + alloc = new LambdaResourceAllocation(Lambda.valueOf(7));
62 + break;
63 + default:
64 + break;
65 + }
66 + }
67 +
68 + Map<Link, Set<ResourceAllocation>> allocations = new HashMap<>();
69 + for (Link link: req.links()) {
70 + allocations.put(link, Sets.newHashSet(alloc));
71 + }
72 + return new DefaultLinkResourceAllocations(req, allocations);
73 + }
74 +
75 + @Override
76 + public void releaseResources(LinkResourceAllocations allocations) {
77 + // TODO Auto-generated method stub
78 +
79 + }
80 +
81 + @Override
82 + public Iterable<LinkResourceAllocations> getAllocations() {
83 + // TODO Auto-generated method stub
84 + return null;
85 + }
86 +
87 + @Override
88 + public LinkResourceAllocations getAllocations(IntentId intentId) {
89 + // TODO Auto-generated method stub
90 + return null;
91 + }
92 +
93 + @Override
94 + public Iterable<LinkResourceAllocations> getAllocations(Link link) {
95 + // TODO Auto-generated method stub
96 + return null;
97 + }
98 +
99 + @Override
100 + public Iterable<IntentId> getIntents(Link link) {
101 + // TODO Auto-generated method stub
102 + return null;
103 + }
104 +
105 + @Override
106 + public ResourceRequest getAvailableResources(Link link) {
107 + // TODO Auto-generated method stub
108 + return null;
109 + }
110 +
111 +}
1 +/**
2 + * Services for reserving network resources, e.g.&nbsp;bandwidth, lambdas.
3 + */
4 +package org.onlab.onos.net.resource.impl;
...@@ -157,16 +157,12 @@ public class StatisticManager implements StatisticService { ...@@ -157,16 +157,12 @@ public class StatisticManager implements StatisticService {
157 case RULE_UPDATED: 157 case RULE_UPDATED:
158 if (rule instanceof FlowEntry) { 158 if (rule instanceof FlowEntry) {
159 statisticStore.addOrUpdateStatistic((FlowEntry) rule); 159 statisticStore.addOrUpdateStatistic((FlowEntry) rule);
160 - } else {
161 - log.warn("IT AIN'T A FLOWENTRY");
162 } 160 }
163 break; 161 break;
164 case RULE_ADD_REQUESTED: 162 case RULE_ADD_REQUESTED:
165 - log.info("Preparing for stats");
166 statisticStore.prepareForStatistics(rule); 163 statisticStore.prepareForStatistics(rule);
167 break; 164 break;
168 case RULE_REMOVE_REQUESTED: 165 case RULE_REMOVE_REQUESTED:
169 - log.info("Removing stats");
170 statisticStore.removeFromStatistics(rule); 166 statisticStore.removeFromStatistics(rule);
171 break; 167 break;
172 case RULE_REMOVED: 168 case RULE_REMOVED:
......
1 package org.onlab.onos.net.flow.impl; 1 package org.onlab.onos.net.flow.impl;
2 2
3 - 3 +import static org.junit.Assert.assertEquals;
4 - 4 +import static org.junit.Assert.assertFalse;
5 -import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*; 5 +import static org.junit.Assert.assertNotNull;
6 - 6 +import static org.junit.Assert.assertTrue;
7 +import static org.junit.Assert.fail;
8 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
9 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADD_REQUESTED;
10 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
11 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVE_REQUESTED;
12 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
7 13
8 import java.util.ArrayList; 14 import java.util.ArrayList;
9 import java.util.Collections; 15 import java.util.Collections;
...@@ -12,6 +18,7 @@ import java.util.List; ...@@ -12,6 +18,7 @@ import java.util.List;
12 import java.util.Map; 18 import java.util.Map;
13 import java.util.Set; 19 import java.util.Set;
14 import java.util.concurrent.ExecutionException; 20 import java.util.concurrent.ExecutionException;
21 +import java.util.concurrent.Executor;
15 import java.util.concurrent.Future; 22 import java.util.concurrent.Future;
16 import java.util.concurrent.TimeUnit; 23 import java.util.concurrent.TimeUnit;
17 import java.util.concurrent.TimeoutException; 24 import java.util.concurrent.TimeoutException;
...@@ -31,6 +38,7 @@ import org.onlab.onos.net.Port; ...@@ -31,6 +38,7 @@ import org.onlab.onos.net.Port;
31 import org.onlab.onos.net.PortNumber; 38 import org.onlab.onos.net.PortNumber;
32 import org.onlab.onos.net.device.DeviceListener; 39 import org.onlab.onos.net.device.DeviceListener;
33 import org.onlab.onos.net.device.DeviceService; 40 import org.onlab.onos.net.device.DeviceService;
41 +import org.onlab.onos.net.flow.BatchOperation;
34 import org.onlab.onos.net.flow.CompletedBatchOperation; 42 import org.onlab.onos.net.flow.CompletedBatchOperation;
35 import org.onlab.onos.net.flow.DefaultFlowEntry; 43 import org.onlab.onos.net.flow.DefaultFlowEntry;
36 import org.onlab.onos.net.flow.DefaultFlowRule; 44 import org.onlab.onos.net.flow.DefaultFlowRule;
...@@ -50,7 +58,6 @@ import org.onlab.onos.net.flow.TrafficSelector; ...@@ -50,7 +58,6 @@ import org.onlab.onos.net.flow.TrafficSelector;
50 import org.onlab.onos.net.flow.TrafficTreatment; 58 import org.onlab.onos.net.flow.TrafficTreatment;
51 import org.onlab.onos.net.flow.criteria.Criterion; 59 import org.onlab.onos.net.flow.criteria.Criterion;
52 import org.onlab.onos.net.flow.instructions.Instruction; 60 import org.onlab.onos.net.flow.instructions.Instruction;
53 -import org.onlab.onos.net.flow.BatchOperation;
54 import org.onlab.onos.net.provider.AbstractProvider; 61 import org.onlab.onos.net.provider.AbstractProvider;
55 import org.onlab.onos.net.provider.ProviderId; 62 import org.onlab.onos.net.provider.ProviderId;
56 import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore; 63 import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
...@@ -59,16 +66,7 @@ import com.google.common.collect.ImmutableList; ...@@ -59,16 +66,7 @@ import com.google.common.collect.ImmutableList;
59 import com.google.common.collect.ImmutableMap; 66 import com.google.common.collect.ImmutableMap;
60 import com.google.common.collect.Lists; 67 import com.google.common.collect.Lists;
61 import com.google.common.collect.Sets; 68 import com.google.common.collect.Sets;
62 - 69 +import com.google.common.util.concurrent.ListenableFuture;
63 -import static java.util.Collections.EMPTY_LIST;
64 -import static org.junit.Assert.assertEquals;
65 -import static org.junit.Assert.assertFalse;
66 -import static org.junit.Assert.assertNotNull;
67 -import static org.junit.Assert.assertTrue;
68 -import static org.junit.Assert.fail;
69 -import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
70 -import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
71 -import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
72 70
73 /** 71 /**
74 * Test codifying the flow rule service & flow rule provider service contracts. 72 * Test codifying the flow rule service & flow rule provider service contracts.
...@@ -182,7 +180,6 @@ public class FlowRuleManagerTest { ...@@ -182,7 +180,6 @@ public class FlowRuleManagerTest {
182 180
183 // TODO: If preserving iteration order is a requirement, redo FlowRuleStore. 181 // TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
184 //backing store is sensitive to the order of additions/removals 182 //backing store is sensitive to the order of additions/removals
185 - @SuppressWarnings("unchecked")
186 private boolean validateState(Map<FlowRule, FlowEntryState> expected) { 183 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
187 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected); 184 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
188 Iterable<FlowEntry> rules = service.getFlowEntries(DID); 185 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
...@@ -526,13 +523,13 @@ public class FlowRuleManagerTest { ...@@ -526,13 +523,13 @@ public class FlowRuleManagerTest {
526 } 523 }
527 524
528 @Override 525 @Override
529 - public Future<CompletedBatchOperation> executeBatch( 526 + public ListenableFuture<CompletedBatchOperation> executeBatch(
530 BatchOperation<FlowRuleBatchEntry> batch) { 527 BatchOperation<FlowRuleBatchEntry> batch) {
531 return new TestInstallationFuture(); 528 return new TestInstallationFuture();
532 } 529 }
533 530
534 private class TestInstallationFuture 531 private class TestInstallationFuture
535 - implements Future<CompletedBatchOperation> { 532 + implements ListenableFuture<CompletedBatchOperation> {
536 533
537 @Override 534 @Override
538 public boolean cancel(boolean mayInterruptIfRunning) { 535 public boolean cancel(boolean mayInterruptIfRunning) {
...@@ -550,10 +547,9 @@ public class FlowRuleManagerTest { ...@@ -550,10 +547,9 @@ public class FlowRuleManagerTest {
550 } 547 }
551 548
552 @Override 549 @Override
553 - @SuppressWarnings("unchecked")
554 public CompletedBatchOperation get() 550 public CompletedBatchOperation get()
555 throws InterruptedException, ExecutionException { 551 throws InterruptedException, ExecutionException {
556 - return new CompletedBatchOperation(true, EMPTY_LIST); 552 + return new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet());
557 } 553 }
558 554
559 @Override 555 @Override
...@@ -562,6 +558,11 @@ public class FlowRuleManagerTest { ...@@ -562,6 +558,11 @@ public class FlowRuleManagerTest {
562 ExecutionException, TimeoutException { 558 ExecutionException, TimeoutException {
563 return null; 559 return null;
564 } 560 }
561 +
562 + @Override
563 + public void addListener(Runnable task, Executor executor) {
564 + // TODO: add stuff.
565 + }
565 } 566 }
566 567
567 } 568 }
...@@ -581,6 +582,12 @@ public class FlowRuleManagerTest { ...@@ -581,6 +582,12 @@ public class FlowRuleManagerTest {
581 } 582 }
582 583
583 @Override 584 @Override
585 + public Criterion getCriterion(
586 + org.onlab.onos.net.flow.criteria.Criterion.Type type) {
587 + return null;
588 + }
589 +
590 + @Override
584 public int hashCode() { 591 public int hashCode() {
585 return testval; 592 return testval;
586 } 593 }
...@@ -592,6 +599,7 @@ public class FlowRuleManagerTest { ...@@ -592,6 +599,7 @@ public class FlowRuleManagerTest {
592 } 599 }
593 return false; 600 return false;
594 } 601 }
602 +
595 } 603 }
596 604
597 private class TestTreatment implements TrafficTreatment { 605 private class TestTreatment implements TrafficTreatment {
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 +import static org.onlab.onos.net.NetTestTools.createPath;
4 +
3 import java.util.ArrayList; 5 import java.util.ArrayList;
4 import java.util.Arrays; 6 import java.util.Arrays;
5 import java.util.Collections; 7 import java.util.Collections;
...@@ -12,12 +14,11 @@ import org.onlab.onos.net.Path; ...@@ -12,12 +14,11 @@ import org.onlab.onos.net.Path;
12 import org.onlab.onos.net.flow.TrafficSelector; 14 import org.onlab.onos.net.flow.TrafficSelector;
13 import org.onlab.onos.net.flow.TrafficTreatment; 15 import org.onlab.onos.net.flow.TrafficTreatment;
14 import org.onlab.onos.net.flow.criteria.Criterion; 16 import org.onlab.onos.net.flow.criteria.Criterion;
17 +import org.onlab.onos.net.flow.criteria.Criterion.Type;
15 import org.onlab.onos.net.flow.instructions.Instruction; 18 import org.onlab.onos.net.flow.instructions.Instruction;
16 import org.onlab.onos.net.topology.LinkWeight; 19 import org.onlab.onos.net.topology.LinkWeight;
17 import org.onlab.onos.net.topology.PathService; 20 import org.onlab.onos.net.topology.PathService;
18 21
19 -import static org.onlab.onos.net.NetTestTools.createPath;
20 -
21 /** 22 /**
22 * Common mocks used by the intent framework tests. 23 * Common mocks used by the intent framework tests.
23 */ 24 */
...@@ -30,6 +31,11 @@ public class IntentTestsMocks { ...@@ -30,6 +31,11 @@ public class IntentTestsMocks {
30 public Set<Criterion> criteria() { 31 public Set<Criterion> criteria() {
31 return new HashSet<>(); 32 return new HashSet<>();
32 } 33 }
34 +
35 + @Override
36 + public Criterion getCriterion(Type type) {
37 + return null;
38 + }
33 } 39 }
34 40
35 /** 41 /**
......
...@@ -103,7 +103,7 @@ public class ClusterCommunicationManager ...@@ -103,7 +103,7 @@ public class ClusterCommunicationManager
103 final ControllerNode localNode = clusterService.getLocalNode(); 103 final ControllerNode localNode = clusterService.getLocalNode();
104 for (NodeId nodeId : nodes) { 104 for (NodeId nodeId : nodes) {
105 if (!nodeId.equals(localNode.id())) { 105 if (!nodeId.equals(localNode.id())) {
106 - ok = unicast(message, nodeId) && ok; 106 + ok = unicastUnchecked(message, nodeId) && ok;
107 } 107 }
108 } 108 }
109 return ok; 109 return ok;
...@@ -124,6 +124,14 @@ public class ClusterCommunicationManager ...@@ -124,6 +124,14 @@ public class ClusterCommunicationManager
124 } 124 }
125 } 125 }
126 126
127 + private boolean unicastUnchecked(ClusterMessage message, NodeId toNodeId) throws IOException {
128 + try {
129 + return unicast(message, toNodeId);
130 + } catch (IOException e) {
131 + return false;
132 + }
133 + }
134 +
127 @Override 135 @Override
128 public ClusterMessageResponse sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException { 136 public ClusterMessageResponse sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException {
129 ControllerNode node = clusterService.getNode(toNodeId); 137 ControllerNode node = clusterService.getNode(toNodeId);
......
...@@ -3,12 +3,21 @@ package org.onlab.onos.store.flow.impl; ...@@ -3,12 +3,21 @@ package org.onlab.onos.store.flow.impl;
3 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; 3 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
4 import static org.slf4j.LoggerFactory.getLogger; 4 import static org.slf4j.LoggerFactory.getLogger;
5 import static org.onlab.onos.store.flow.impl.FlowStoreMessageSubjects.*; 5 import static org.onlab.onos.store.flow.impl.FlowStoreMessageSubjects.*;
6 +import static org.onlab.util.Tools.namedThreads;
6 7
7 import java.io.IOException; 8 import java.io.IOException;
9 +import java.util.ArrayList;
10 +import java.util.Arrays;
8 import java.util.Collection; 11 import java.util.Collection;
9 import java.util.Collections; 12 import java.util.Collections;
13 +import java.util.Map;
14 +import java.util.concurrent.ExecutorService;
15 +import java.util.concurrent.Executors;
16 +import java.util.concurrent.Future;
10 import java.util.concurrent.TimeUnit; 17 import java.util.concurrent.TimeUnit;
11 import java.util.concurrent.TimeoutException; 18 import java.util.concurrent.TimeoutException;
19 +import java.util.concurrent.atomic.AtomicInteger;
20 +import java.util.List;
12 21
13 import org.apache.felix.scr.annotations.Activate; 22 import org.apache.felix.scr.annotations.Activate;
14 import org.apache.felix.scr.annotations.Component; 23 import org.apache.felix.scr.annotations.Component;
...@@ -18,12 +27,20 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -18,12 +27,20 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
18 import org.apache.felix.scr.annotations.Service; 27 import org.apache.felix.scr.annotations.Service;
19 import org.onlab.onos.ApplicationId; 28 import org.onlab.onos.ApplicationId;
20 import org.onlab.onos.cluster.ClusterService; 29 import org.onlab.onos.cluster.ClusterService;
30 +import org.onlab.onos.net.Device;
21 import org.onlab.onos.net.DeviceId; 31 import org.onlab.onos.net.DeviceId;
32 +import org.onlab.onos.net.device.DeviceService;
33 +import org.onlab.onos.net.flow.CompletedBatchOperation;
22 import org.onlab.onos.net.flow.DefaultFlowEntry; 34 import org.onlab.onos.net.flow.DefaultFlowEntry;
23 import org.onlab.onos.net.flow.FlowEntry; 35 import org.onlab.onos.net.flow.FlowEntry;
24 import org.onlab.onos.net.flow.FlowEntry.FlowEntryState; 36 import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
25 import org.onlab.onos.net.flow.FlowRule; 37 import org.onlab.onos.net.flow.FlowRule;
38 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
39 +import org.onlab.onos.net.flow.FlowRuleBatchEvent;
40 +import org.onlab.onos.net.flow.FlowRuleBatchOperation;
41 +import org.onlab.onos.net.flow.FlowRuleBatchRequest;
26 import org.onlab.onos.net.flow.FlowRuleEvent; 42 import org.onlab.onos.net.flow.FlowRuleEvent;
43 +import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
27 import org.onlab.onos.net.flow.FlowRuleEvent.Type; 44 import org.onlab.onos.net.flow.FlowRuleEvent.Type;
28 import org.onlab.onos.net.flow.FlowRuleStore; 45 import org.onlab.onos.net.flow.FlowRuleStore;
29 import org.onlab.onos.net.flow.FlowRuleStoreDelegate; 46 import org.onlab.onos.net.flow.FlowRuleStoreDelegate;
...@@ -42,7 +59,12 @@ import org.slf4j.Logger; ...@@ -42,7 +59,12 @@ import org.slf4j.Logger;
42 59
43 import com.google.common.collect.ArrayListMultimap; 60 import com.google.common.collect.ArrayListMultimap;
44 import com.google.common.collect.ImmutableSet; 61 import com.google.common.collect.ImmutableSet;
62 +import com.google.common.collect.Iterables;
63 +import com.google.common.collect.Maps;
45 import com.google.common.collect.Multimap; 64 import com.google.common.collect.Multimap;
65 +import com.google.common.util.concurrent.Futures;
66 +import com.google.common.util.concurrent.ListenableFuture;
67 +import com.google.common.util.concurrent.SettableFuture;
46 68
47 /** 69 /**
48 * Manages inventory of flow rules using a distributed state management protocol. 70 * Manages inventory of flow rules using a distributed state management protocol.
...@@ -50,7 +72,7 @@ import com.google.common.collect.Multimap; ...@@ -50,7 +72,7 @@ import com.google.common.collect.Multimap;
50 @Component(immediate = true) 72 @Component(immediate = true)
51 @Service 73 @Service
52 public class DistributedFlowRuleStore 74 public class DistributedFlowRuleStore
53 - extends AbstractStore<FlowRuleEvent, FlowRuleStoreDelegate> 75 + extends AbstractStore<FlowRuleBatchEvent, FlowRuleStoreDelegate>
54 implements FlowRuleStore { 76 implements FlowRuleStore {
55 77
56 private final Logger log = getLogger(getClass()); 78 private final Logger log = getLogger(getClass());
...@@ -63,13 +85,26 @@ public class DistributedFlowRuleStore ...@@ -63,13 +85,26 @@ public class DistributedFlowRuleStore
63 ArrayListMultimap.<Short, FlowRule>create(); 85 ArrayListMultimap.<Short, FlowRule>create();
64 86
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 - private ReplicaInfoService replicaInfoManager; 88 + protected ReplicaInfoService replicaInfoManager;
67 89
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 - private ClusterCommunicationService clusterCommunicator; 91 + protected ClusterCommunicationService clusterCommunicator;
70 92
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 - private ClusterService clusterService; 94 + protected ClusterService clusterService;
95 +
96 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 + protected DeviceService deviceService;
98 +
99 + private final AtomicInteger localBatchIdGen = new AtomicInteger();
100 +
101 +
102 + // FIXME switch to expiraing map/Cache?
103 + private Map<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = Maps.newConcurrentMap();
104 +
105 + private final ExecutorService futureListeners =
106 + Executors.newCachedThreadPool(namedThreads("flowstore-peer-responders"));
107 +
73 108
74 protected static final KryoSerializer SERIALIZER = new KryoSerializer() { 109 protected static final KryoSerializer SERIALIZER = new KryoSerializer() {
75 @Override 110 @Override
...@@ -86,38 +121,44 @@ public class DistributedFlowRuleStore ...@@ -86,38 +121,44 @@ public class DistributedFlowRuleStore
86 121
87 @Activate 122 @Activate
88 public void activate() { 123 public void activate() {
89 - clusterCommunicator.addSubscriber(STORE_FLOW_RULE, new ClusterMessageHandler() { 124 + clusterCommunicator.addSubscriber(APPLY_BATCH_FLOWS, new ClusterMessageHandler() {
90 125
91 @Override 126 @Override
92 - public void handle(ClusterMessage message) { 127 + public void handle(final ClusterMessage message) {
93 - FlowRule rule = SERIALIZER.decode(message.payload()); 128 + FlowRuleBatchOperation operation = SERIALIZER.decode(message.payload());
94 - log.info("received add request for {}", rule); 129 + log.info("received batch request {}", operation);
95 - storeFlowEntryInternal(rule); 130 + final ListenableFuture<CompletedBatchOperation> f = storeBatchInternal(operation);
96 - // FIXME what to respond. 131 +
97 - try { 132 + f.addListener(new Runnable() {
98 - message.respond(SERIALIZER.encode("ACK")); 133 +
99 - } catch (IOException e) { 134 + @Override
100 - log.error("Failed to respond back", e); 135 + public void run() {
101 - } 136 + CompletedBatchOperation result = Futures.getUnchecked(f);
137 + try {
138 + message.respond(SERIALIZER.encode(result));
139 + } catch (IOException e) {
140 + log.error("Failed to respond back", e);
141 + }
142 + }
143 + }, futureListeners);
102 } 144 }
103 }); 145 });
104 146
105 - clusterCommunicator.addSubscriber(DELETE_FLOW_RULE, new ClusterMessageHandler() { 147 + clusterCommunicator.addSubscriber(GET_FLOW_ENTRY, new ClusterMessageHandler() {
106 148
107 @Override 149 @Override
108 public void handle(ClusterMessage message) { 150 public void handle(ClusterMessage message) {
109 FlowRule rule = SERIALIZER.decode(message.payload()); 151 FlowRule rule = SERIALIZER.decode(message.payload());
110 - log.info("received delete request for {}", rule); 152 + log.info("received get flow entry request for {}", rule);
111 - deleteFlowRuleInternal(rule); 153 + FlowEntry flowEntry = getFlowEntryInternal(rule);
112 - // FIXME what to respond.
113 try { 154 try {
114 - message.respond(SERIALIZER.encode("ACK")); 155 + message.respond(SERIALIZER.encode(flowEntry));
115 } catch (IOException e) { 156 } catch (IOException e) {
116 log.error("Failed to respond back", e); 157 log.error("Failed to respond back", e);
117 } 158 }
118 -
119 } 159 }
120 }); 160 });
161 +
121 log.info("Started"); 162 log.info("Started");
122 } 163 }
123 164
...@@ -127,14 +168,42 @@ public class DistributedFlowRuleStore ...@@ -127,14 +168,42 @@ public class DistributedFlowRuleStore
127 } 168 }
128 169
129 170
171 + // TODO: This is not a efficient operation on a distributed sharded
172 + // flow store. We need to revisit the need for this operation or at least
173 + // make it device specific.
130 @Override 174 @Override
131 public int getFlowRuleCount() { 175 public int getFlowRuleCount() {
132 - return flowEntries.size(); 176 + // implementing in-efficient operation for debugging purpose.
177 + int sum = 0;
178 + for (Device device : deviceService.getDevices()) {
179 + final DeviceId did = device.id();
180 + sum += Iterables.size(getFlowEntries(did));
181 + }
182 + return sum;
133 } 183 }
134 184
135 @Override 185 @Override
136 public synchronized FlowEntry getFlowEntry(FlowRule rule) { 186 public synchronized FlowEntry getFlowEntry(FlowRule rule) {
137 - return getFlowEntryInternal(rule); 187 + ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(rule.deviceId());
188 + if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) {
189 + return getFlowEntryInternal(rule);
190 + }
191 +
192 + log.info("Forwarding getFlowEntry to {}, which is the primary (master) for device {}",
193 + replicaInfo.master().orNull(), rule.deviceId());
194 +
195 + ClusterMessage message = new ClusterMessage(
196 + clusterService.getLocalNode().id(),
197 + FlowStoreMessageSubjects.GET_FLOW_ENTRY,
198 + SERIALIZER.encode(rule));
199 +
200 + try {
201 + ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get());
202 + return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
203 + } catch (IOException | TimeoutException e) {
204 + // FIXME: throw a FlowStoreException
205 + throw new RuntimeException(e);
206 + }
138 } 207 }
139 208
140 private synchronized StoredFlowEntry getFlowEntryInternal(FlowRule rule) { 209 private synchronized StoredFlowEntry getFlowEntryInternal(FlowRule rule) {
...@@ -165,56 +234,31 @@ public class DistributedFlowRuleStore ...@@ -165,56 +234,31 @@ public class DistributedFlowRuleStore
165 } 234 }
166 235
167 @Override 236 @Override
168 - public boolean storeFlowRule(FlowRule rule) { 237 + public void storeFlowRule(FlowRule rule) {
169 - ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(rule.deviceId()); 238 + storeBatch(new FlowRuleBatchOperation(Arrays.asList(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule))));
170 - if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) {
171 - return storeFlowEntryInternal(rule);
172 - }
173 -
174 - log.info("Forwarding storeFlowRule to {}, which is the primary (master) for device {}",
175 - replicaInfo.master().orNull(), rule.deviceId());
176 -
177 - ClusterMessage message = new ClusterMessage(
178 - clusterService.getLocalNode().id(),
179 - FlowStoreMessageSubjects.STORE_FLOW_RULE,
180 - SERIALIZER.encode(rule));
181 -
182 - try {
183 - ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get());
184 - response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
185 - } catch (IOException | TimeoutException e) {
186 - // FIXME: throw a FlowStoreException
187 - throw new RuntimeException(e);
188 - }
189 - return false;
190 } 239 }
191 240
192 - private synchronized boolean storeFlowEntryInternal(FlowRule flowRule) { 241 + @Override
193 - StoredFlowEntry flowEntry = new DefaultFlowEntry(flowRule); 242 + public Future<CompletedBatchOperation> storeBatch(FlowRuleBatchOperation operation) {
194 - DeviceId deviceId = flowRule.deviceId(); 243 + if (operation.getOperations().isEmpty()) {
195 - // write to local copy. 244 + return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet()));
196 - if (!flowEntries.containsEntry(deviceId, flowEntry)) {
197 - flowEntries.put(deviceId, flowEntry);
198 - flowEntriesById.put(flowRule.appId(), flowEntry);
199 - notifyDelegate(new FlowRuleEvent(Type.RULE_ADD_REQUESTED, flowRule));
200 - return true;
201 } 245 }
202 - // write to backup.
203 - // TODO: write to a hazelcast map.
204 - return false;
205 - }
206 246
207 - @Override 247 + DeviceId deviceId = operation.getOperations().get(0).getTarget().deviceId();
208 - public synchronized boolean deleteFlowRule(FlowRule rule) { 248 +
209 - ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(rule.deviceId()); 249 + ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(deviceId);
250 +
210 if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) { 251 if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) {
211 - return deleteFlowRuleInternal(rule); 252 + return storeBatchInternal(operation);
212 } 253 }
213 254
255 + log.info("Forwarding storeBatch to {}, which is the primary (master) for device {}",
256 + replicaInfo.master().orNull(), deviceId);
257 +
214 ClusterMessage message = new ClusterMessage( 258 ClusterMessage message = new ClusterMessage(
215 clusterService.getLocalNode().id(), 259 clusterService.getLocalNode().id(),
216 - FlowStoreMessageSubjects.DELETE_FLOW_RULE, 260 + APPLY_BATCH_FLOWS,
217 - SERIALIZER.encode(rule)); 261 + SERIALIZER.encode(operation));
218 262
219 try { 263 try {
220 ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); 264 ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get());
...@@ -223,21 +267,48 @@ public class DistributedFlowRuleStore ...@@ -223,21 +267,48 @@ public class DistributedFlowRuleStore
223 // FIXME: throw a FlowStoreException 267 // FIXME: throw a FlowStoreException
224 throw new RuntimeException(e); 268 throw new RuntimeException(e);
225 } 269 }
226 - return false; 270 +
271 + return null;
227 } 272 }
228 273
229 - private synchronized boolean deleteFlowRuleInternal(FlowRule flowRule) { 274 + private ListenableFuture<CompletedBatchOperation> storeBatchInternal(FlowRuleBatchOperation operation) {
230 - StoredFlowEntry entry = getFlowEntryInternal(flowRule); 275 + List<FlowEntry> toRemove = new ArrayList<>();
231 - if (entry == null) { 276 + List<FlowEntry> toAdd = new ArrayList<>();
232 - return false; 277 + // TODO: backup changes to hazelcast map
278 + for (FlowRuleBatchEntry batchEntry : operation.getOperations()) {
279 + FlowRule flowRule = batchEntry.getTarget();
280 + FlowRuleOperation op = batchEntry.getOperator();
281 + if (op.equals(FlowRuleOperation.REMOVE)) {
282 + StoredFlowEntry entry = getFlowEntryInternal(flowRule);
283 + if (entry != null) {
284 + entry.setState(FlowEntryState.PENDING_REMOVE);
285 + toRemove.add(entry);
286 + }
287 + } else if (op.equals(FlowRuleOperation.ADD)) {
288 + StoredFlowEntry flowEntry = new DefaultFlowEntry(flowRule);
289 + DeviceId deviceId = flowRule.deviceId();
290 + if (!flowEntries.containsEntry(deviceId, flowEntry)) {
291 + flowEntries.put(deviceId, flowEntry);
292 + flowEntriesById.put(flowRule.appId(), flowEntry);
293 + toAdd.add(flowEntry);
294 + }
295 + }
296 + }
297 + if (toAdd.isEmpty() && toRemove.isEmpty()) {
298 + return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet()));
233 } 299 }
234 - entry.setState(FlowEntryState.PENDING_REMOVE);
235 300
236 - // TODO: also update backup. 301 + SettableFuture<CompletedBatchOperation> r = SettableFuture.create();
302 + final int batchId = localBatchIdGen.incrementAndGet();
237 303
238 - notifyDelegate(new FlowRuleEvent(Type.RULE_REMOVE_REQUESTED, flowRule)); 304 + pendingFutures.put(batchId, r);
305 + notifyDelegate(FlowRuleBatchEvent.requested(new FlowRuleBatchRequest(batchId, toAdd, toRemove)));
306 + return r;
307 + }
239 308
240 - return true; 309 + @Override
310 + public void deleteFlowRule(FlowRule rule) {
311 + storeBatch(new FlowRuleBatchOperation(Arrays.asList(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule))));
241 } 312 }
242 313
243 @Override 314 @Override
...@@ -247,18 +318,9 @@ public class DistributedFlowRuleStore ...@@ -247,18 +318,9 @@ public class DistributedFlowRuleStore
247 return addOrUpdateFlowRuleInternal(rule); 318 return addOrUpdateFlowRuleInternal(rule);
248 } 319 }
249 320
250 - ClusterMessage message = new ClusterMessage( 321 + log.error("Tried to update FlowRule {} state,"
251 - clusterService.getLocalNode().id(), 322 + + " while the Node was not the master.", rule);
252 - FlowStoreMessageSubjects.ADD_OR_UPDATE_FLOW_RULE, 323 + return null;
253 - SERIALIZER.encode(rule));
254 -
255 - try {
256 - ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get());
257 - return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
258 - } catch (IOException | TimeoutException e) {
259 - // FIXME: throw a FlowStoreException
260 - throw new RuntimeException(e);
261 - }
262 } 324 }
263 325
264 private synchronized FlowRuleEvent addOrUpdateFlowRuleInternal(FlowEntry rule) { 326 private synchronized FlowRuleEvent addOrUpdateFlowRuleInternal(FlowEntry rule) {
...@@ -292,18 +354,9 @@ public class DistributedFlowRuleStore ...@@ -292,18 +354,9 @@ public class DistributedFlowRuleStore
292 return removeFlowRuleInternal(rule); 354 return removeFlowRuleInternal(rule);
293 } 355 }
294 356
295 - ClusterMessage message = new ClusterMessage( 357 + log.error("Tried to remove FlowRule {},"
296 - clusterService.getLocalNode().id(), 358 + + " while the Node was not the master.", rule);
297 - FlowStoreMessageSubjects.REMOVE_FLOW_RULE, 359 + return null;
298 - SERIALIZER.encode(rule));
299 -
300 - try {
301 - ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get());
302 - return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
303 - } catch (IOException | TimeoutException e) {
304 - // FIXME: throw a FlowStoreException
305 - throw new RuntimeException(e);
306 - }
307 } 360 }
308 361
309 private synchronized FlowRuleEvent removeFlowRuleInternal(FlowEntry rule) { 362 private synchronized FlowRuleEvent removeFlowRuleInternal(FlowEntry rule) {
...@@ -315,4 +368,14 @@ public class DistributedFlowRuleStore ...@@ -315,4 +368,14 @@ public class DistributedFlowRuleStore
315 } 368 }
316 // TODO: also update backup. 369 // TODO: also update backup.
317 } 370 }
371 +
372 + @Override
373 + public void batchOperationComplete(FlowRuleBatchEvent event) {
374 + SettableFuture<CompletedBatchOperation> future
375 + = pendingFutures.get(event.subject().batchId());
376 + if (future != null) {
377 + future.set(event.result());
378 + }
379 + notifyDelegate(event);
380 + }
318 } 381 }
......
...@@ -7,9 +7,10 @@ import org.onlab.onos.store.cluster.messaging.MessageSubject; ...@@ -7,9 +7,10 @@ import org.onlab.onos.store.cluster.messaging.MessageSubject;
7 */ 7 */
8 public final class FlowStoreMessageSubjects { 8 public final class FlowStoreMessageSubjects {
9 private FlowStoreMessageSubjects() {} 9 private FlowStoreMessageSubjects() {}
10 - public static final MessageSubject STORE_FLOW_RULE = new MessageSubject("peer-forward-store-flow-rule"); 10 +
11 - public static final MessageSubject DELETE_FLOW_RULE = new MessageSubject("peer-forward-delete-flow-rule"); 11 + public static final MessageSubject APPLY_BATCH_FLOWS
12 - public static final MessageSubject ADD_OR_UPDATE_FLOW_RULE = 12 + = new MessageSubject("peer-forward-apply-batch");
13 - new MessageSubject("peer-forward-add-or-update-flow-rule"); 13 +
14 - public static final MessageSubject REMOVE_FLOW_RULE = new MessageSubject("peer-forward-remove-flow-rule"); 14 + public static final MessageSubject GET_FLOW_ENTRY
15 + = new MessageSubject("peer-forward-get-flow-entry");
15 } 16 }
......
...@@ -399,7 +399,7 @@ public class GossipHostStore ...@@ -399,7 +399,7 @@ public class GossipHostStore
399 } 399 }
400 400
401 // Auxiliary extension to allow location to mutate. 401 // Auxiliary extension to allow location to mutate.
402 - private class StoredHost extends DefaultHost { 402 + private static final class StoredHost extends DefaultHost {
403 private Timestamped<HostLocation> location; 403 private Timestamped<HostLocation> location;
404 404
405 /** 405 /**
......
...@@ -58,7 +58,6 @@ implements MastershipStore { ...@@ -58,7 +58,6 @@ implements MastershipStore {
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 protected ClusterService clusterService; 59 protected ClusterService clusterService;
60 60
61 - @SuppressWarnings({ "unchecked", "rawtypes" })
62 @Override 61 @Override
63 @Activate 62 @Activate
64 public void activate() { 63 public void activate() {
...@@ -76,9 +75,9 @@ implements MastershipStore { ...@@ -76,9 +75,9 @@ implements MastershipStore {
76 } 75 }
77 }; 76 };
78 77
79 - roleMap = new SMap(theInstance.getMap("nodeRoles"), this.serializer); 78 + roleMap = new SMap<>(theInstance.<byte[], byte[]>getMap("nodeRoles"), this.serializer);
80 roleMap.addEntryListener((new RemoteMasterShipEventHandler()), true); 79 roleMap.addEntryListener((new RemoteMasterShipEventHandler()), true);
81 - terms = new SMap(theInstance.getMap("terms"), this.serializer); 80 + terms = new SMap<>(theInstance.<byte[], byte[]>getMap("terms"), this.serializer);
82 clusterSize = theInstance.getAtomicLong("clustersize"); 81 clusterSize = theInstance.getAtomicLong("clustersize");
83 82
84 log.info("Started"); 83 log.info("Started");
......
1 package org.onlab.onos.store.mastership.impl; 1 package org.onlab.onos.store.mastership.impl;
2 2
3 import java.util.Collections; 3 import java.util.Collections;
4 -import java.util.HashMap; 4 +import java.util.EnumMap;
5 import java.util.LinkedList; 5 import java.util.LinkedList;
6 import java.util.List; 6 import java.util.List;
7 import java.util.Map; 7 import java.util.Map;
...@@ -17,9 +17,9 @@ import com.google.common.base.MoreObjects.ToStringHelper; ...@@ -17,9 +17,9 @@ import com.google.common.base.MoreObjects.ToStringHelper;
17 * A structure that holds node mastership roles associated with a 17 * A structure that holds node mastership roles associated with a
18 * {@link DeviceId}. This structure needs to be locked through IMap. 18 * {@link DeviceId}. This structure needs to be locked through IMap.
19 */ 19 */
20 -public class RoleValue { 20 +final class RoleValue {
21 21
22 - protected Map<MastershipRole, List<NodeId>> value = new HashMap<>(); 22 + protected final Map<MastershipRole, List<NodeId>> value = new EnumMap<>(MastershipRole.class);
23 23
24 public RoleValue() { 24 public RoleValue() {
25 value.put(MastershipRole.MASTER, new LinkedList<NodeId>()); 25 value.put(MastershipRole.MASTER, new LinkedList<NodeId>());
...@@ -27,7 +27,8 @@ public class RoleValue { ...@@ -27,7 +27,8 @@ public class RoleValue {
27 value.put(MastershipRole.NONE, new LinkedList<NodeId>()); 27 value.put(MastershipRole.NONE, new LinkedList<NodeId>());
28 } 28 }
29 29
30 - public Map<MastershipRole, List<NodeId>> value() { 30 + // exposing internals for serialization purpose only
31 + Map<MastershipRole, List<NodeId>> value() {
31 return Collections.unmodifiableMap(value); 32 return Collections.unmodifiableMap(value);
32 } 33 }
33 34
......
...@@ -35,10 +35,10 @@ public class RoleValueSerializer extends Serializer<RoleValue> { ...@@ -35,10 +35,10 @@ public class RoleValueSerializer extends Serializer<RoleValue> {
35 35
36 @Override 36 @Override
37 public void write(Kryo kryo, Output output, RoleValue type) { 37 public void write(Kryo kryo, Output output, RoleValue type) {
38 - output.writeInt(type.value().size()); 38 + final Map<MastershipRole, List<NodeId>> map = type.value();
39 + output.writeInt(map.size());
39 40
40 - for (Map.Entry<MastershipRole, List<NodeId>> el : 41 + for (Map.Entry<MastershipRole, List<NodeId>> el : map.entrySet()) {
41 - type.value().entrySet()) {
42 output.writeInt(el.getKey().ordinal()); 42 output.writeInt(el.getKey().ordinal());
43 43
44 List<NodeId> nodes = el.getValue(); 44 List<NodeId> nodes = el.getValue();
......
...@@ -492,7 +492,10 @@ public class SMap<K, V> implements IMap<K, V> { ...@@ -492,7 +492,10 @@ public class SMap<K, V> implements IMap<K, V> {
492 } 492 }
493 493
494 private V deserializeVal(byte[] val) { 494 private V deserializeVal(byte[] val) {
495 - return serializer.decode(val); 495 + if (val == null) {
496 + return null;
497 + }
498 + return serializer.decode(val.clone());
496 } 499 }
497 500
498 private Set<byte[]> serializeKeySet(Set<K> keys) { 501 private Set<byte[]> serializeKeySet(Set<K> keys) {
......
...@@ -5,6 +5,7 @@ import java.util.ArrayList; ...@@ -5,6 +5,7 @@ import java.util.ArrayList;
5 import java.util.Arrays; 5 import java.util.Arrays;
6 import java.util.HashMap; 6 import java.util.HashMap;
7 import java.util.HashSet; 7 import java.util.HashSet;
8 +import java.util.LinkedList;
8 9
9 import org.onlab.onos.cluster.ControllerNode; 10 import org.onlab.onos.cluster.ControllerNode;
10 import org.onlab.onos.cluster.DefaultControllerNode; 11 import org.onlab.onos.cluster.DefaultControllerNode;
...@@ -27,12 +28,16 @@ import org.onlab.onos.net.Port; ...@@ -27,12 +28,16 @@ import org.onlab.onos.net.Port;
27 import org.onlab.onos.net.PortNumber; 28 import org.onlab.onos.net.PortNumber;
28 import org.onlab.onos.net.device.DefaultDeviceDescription; 29 import org.onlab.onos.net.device.DefaultDeviceDescription;
29 import org.onlab.onos.net.device.DefaultPortDescription; 30 import org.onlab.onos.net.device.DefaultPortDescription;
31 +import org.onlab.onos.net.flow.CompletedBatchOperation;
30 import org.onlab.onos.net.flow.DefaultFlowEntry; 32 import org.onlab.onos.net.flow.DefaultFlowEntry;
31 import org.onlab.onos.net.flow.DefaultFlowRule; 33 import org.onlab.onos.net.flow.DefaultFlowRule;
32 import org.onlab.onos.net.flow.DefaultTrafficSelector; 34 import org.onlab.onos.net.flow.DefaultTrafficSelector;
33 import org.onlab.onos.net.flow.DefaultTrafficTreatment; 35 import org.onlab.onos.net.flow.DefaultTrafficTreatment;
34 import org.onlab.onos.net.flow.FlowEntry; 36 import org.onlab.onos.net.flow.FlowEntry;
35 import org.onlab.onos.net.flow.FlowId; 37 import org.onlab.onos.net.flow.FlowId;
38 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
39 +import org.onlab.onos.net.flow.FlowRuleBatchOperation;
40 +import org.onlab.onos.net.flow.StoredFlowEntry;
36 import org.onlab.onos.net.flow.criteria.Criteria; 41 import org.onlab.onos.net.flow.criteria.Criteria;
37 import org.onlab.onos.net.flow.criteria.Criterion; 42 import org.onlab.onos.net.flow.criteria.Criterion;
38 import org.onlab.onos.net.flow.instructions.Instructions; 43 import org.onlab.onos.net.flow.instructions.Instructions;
...@@ -79,6 +84,7 @@ public final class KryoNamespaces { ...@@ -79,6 +84,7 @@ public final class KryoNamespaces {
79 Arrays.asList().getClass(), 84 Arrays.asList().getClass(),
80 HashMap.class, 85 HashMap.class,
81 HashSet.class, 86 HashSet.class,
87 + LinkedList.class,
82 // 88 //
83 // 89 //
84 ControllerNode.State.class, 90 ControllerNode.State.class,
...@@ -97,6 +103,8 @@ public final class KryoNamespaces { ...@@ -97,6 +103,8 @@ public final class KryoNamespaces {
97 HostId.class, 103 HostId.class,
98 HostDescription.class, 104 HostDescription.class,
99 DefaultHostDescription.class, 105 DefaultHostDescription.class,
106 + DefaultFlowEntry.class,
107 + StoredFlowEntry.class,
100 DefaultFlowRule.class, 108 DefaultFlowRule.class,
101 DefaultFlowEntry.class, 109 DefaultFlowEntry.class,
102 FlowEntry.FlowEntryState.class, 110 FlowEntry.FlowEntryState.class,
...@@ -115,7 +123,11 @@ public final class KryoNamespaces { ...@@ -115,7 +123,11 @@ public final class KryoNamespaces {
115 DefaultTrafficTreatment.class, 123 DefaultTrafficTreatment.class,
116 Instructions.DropInstruction.class, 124 Instructions.DropInstruction.class,
117 Instructions.OutputInstruction.class, 125 Instructions.OutputInstruction.class,
118 - RoleInfo.class 126 + RoleInfo.class,
127 + FlowRuleBatchOperation.class,
128 + CompletedBatchOperation.class,
129 + FlowRuleBatchEntry.class,
130 + FlowRuleBatchEntry.FlowRuleOperation.class
119 ) 131 )
120 .register(URI.class, new URISerializer()) 132 .register(URI.class, new URISerializer())
121 .register(NodeId.class, new NodeIdSerializer()) 133 .register(NodeId.class, new NodeIdSerializer())
......
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_REMOVED; 3 +import com.google.common.base.Function;
4 -import static org.slf4j.LoggerFactory.getLogger; 4 +import com.google.common.collect.FluentIterable;
5 -import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; 5 +import com.google.common.util.concurrent.Futures;
6 -import java.util.Collections;
7 -import java.util.HashSet;
8 -import java.util.List;
9 -import java.util.Set;
10 -import java.util.concurrent.ConcurrentHashMap;
11 -import java.util.concurrent.ConcurrentMap;
12 -import java.util.concurrent.CopyOnWriteArrayList;
13 -
14 import org.apache.felix.scr.annotations.Activate; 6 import org.apache.felix.scr.annotations.Activate;
15 import org.apache.felix.scr.annotations.Component; 7 import org.apache.felix.scr.annotations.Component;
16 import org.apache.felix.scr.annotations.Deactivate; 8 import org.apache.felix.scr.annotations.Deactivate;
17 import org.apache.felix.scr.annotations.Service; 9 import org.apache.felix.scr.annotations.Service;
18 import org.onlab.onos.ApplicationId; 10 import org.onlab.onos.ApplicationId;
19 import org.onlab.onos.net.DeviceId; 11 import org.onlab.onos.net.DeviceId;
12 +import org.onlab.onos.net.flow.CompletedBatchOperation;
20 import org.onlab.onos.net.flow.DefaultFlowEntry; 13 import org.onlab.onos.net.flow.DefaultFlowEntry;
21 import org.onlab.onos.net.flow.FlowEntry; 14 import org.onlab.onos.net.flow.FlowEntry;
22 import org.onlab.onos.net.flow.FlowEntry.FlowEntryState; 15 import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
23 import org.onlab.onos.net.flow.FlowId; 16 import org.onlab.onos.net.flow.FlowId;
24 import org.onlab.onos.net.flow.FlowRule; 17 import org.onlab.onos.net.flow.FlowRule;
18 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
19 +import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
20 +import org.onlab.onos.net.flow.FlowRuleBatchEvent;
21 +import org.onlab.onos.net.flow.FlowRuleBatchOperation;
22 +import org.onlab.onos.net.flow.FlowRuleBatchRequest;
25 import org.onlab.onos.net.flow.FlowRuleEvent; 23 import org.onlab.onos.net.flow.FlowRuleEvent;
26 import org.onlab.onos.net.flow.FlowRuleEvent.Type; 24 import org.onlab.onos.net.flow.FlowRuleEvent.Type;
27 import org.onlab.onos.net.flow.FlowRuleStore; 25 import org.onlab.onos.net.flow.FlowRuleStore;
...@@ -31,8 +29,19 @@ import org.onlab.onos.store.AbstractStore; ...@@ -31,8 +29,19 @@ import org.onlab.onos.store.AbstractStore;
31 import org.onlab.util.NewConcurrentHashMap; 29 import org.onlab.util.NewConcurrentHashMap;
32 import org.slf4j.Logger; 30 import org.slf4j.Logger;
33 31
34 -import com.google.common.base.Function; 32 +import java.util.Arrays;
35 -import com.google.common.collect.FluentIterable; 33 +import java.util.Collections;
34 +import java.util.HashSet;
35 +import java.util.List;
36 +import java.util.Set;
37 +import java.util.concurrent.ConcurrentHashMap;
38 +import java.util.concurrent.ConcurrentMap;
39 +import java.util.concurrent.CopyOnWriteArrayList;
40 +import java.util.concurrent.Future;
41 +
42 +import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked;
43 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
44 +import static org.slf4j.LoggerFactory.getLogger;
36 45
37 /** 46 /**
38 * Manages inventory of flow rules using trivial in-memory implementation. 47 * Manages inventory of flow rules using trivial in-memory implementation.
...@@ -40,7 +49,7 @@ import com.google.common.collect.FluentIterable; ...@@ -40,7 +49,7 @@ import com.google.common.collect.FluentIterable;
40 @Component(immediate = true) 49 @Component(immediate = true)
41 @Service 50 @Service
42 public class SimpleFlowRuleStore 51 public class SimpleFlowRuleStore
43 - extends AbstractStore<FlowRuleEvent, FlowRuleStoreDelegate> 52 + extends AbstractStore<FlowRuleBatchEvent, FlowRuleStoreDelegate>
44 implements FlowRuleStore { 53 implements FlowRuleStore {
45 54
46 private final Logger log = getLogger(getClass()); 55 private final Logger log = getLogger(getClass());
...@@ -122,15 +131,15 @@ public class SimpleFlowRuleStore ...@@ -122,15 +131,15 @@ public class SimpleFlowRuleStore
122 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) { 131 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
123 // flatten and make iterator unmodifiable 132 // flatten and make iterator unmodifiable
124 return FluentIterable.from(getFlowTable(deviceId).values()) 133 return FluentIterable.from(getFlowTable(deviceId).values())
125 - .transformAndConcat( 134 + .transformAndConcat(
126 - new Function<List<StoredFlowEntry>, Iterable<? extends FlowEntry>>() { 135 + new Function<List<StoredFlowEntry>, Iterable<? extends FlowEntry>>() {
127 136
128 - @Override 137 + @Override
129 - public Iterable<? extends FlowEntry> apply( 138 + public Iterable<? extends FlowEntry> apply(
130 - List<StoredFlowEntry> input) { 139 + List<StoredFlowEntry> input) {
131 - return Collections.unmodifiableList(input); 140 + return Collections.unmodifiableList(input);
132 - } 141 + }
133 - }); 142 + });
134 } 143 }
135 144
136 @Override 145 @Override
...@@ -148,12 +157,11 @@ public class SimpleFlowRuleStore ...@@ -148,12 +157,11 @@ public class SimpleFlowRuleStore
148 } 157 }
149 158
150 @Override 159 @Override
151 - public boolean storeFlowRule(FlowRule rule) { 160 + public void storeFlowRule(FlowRule rule) {
152 - final boolean added = storeFlowRuleInternal(rule); 161 + storeFlowRuleInternal(rule);
153 - return added;
154 } 162 }
155 163
156 - private boolean storeFlowRuleInternal(FlowRule rule) { 164 + private void storeFlowRuleInternal(FlowRule rule) {
157 StoredFlowEntry f = new DefaultFlowEntry(rule); 165 StoredFlowEntry f = new DefaultFlowEntry(rule);
158 final DeviceId did = f.deviceId(); 166 final DeviceId did = f.deviceId();
159 final FlowId fid = f.id(); 167 final FlowId fid = f.id();
...@@ -162,19 +170,20 @@ public class SimpleFlowRuleStore ...@@ -162,19 +170,20 @@ public class SimpleFlowRuleStore
162 for (StoredFlowEntry fe : existing) { 170 for (StoredFlowEntry fe : existing) {
163 if (fe.equals(rule)) { 171 if (fe.equals(rule)) {
164 // was already there? ignore 172 // was already there? ignore
165 - return false; 173 + return;
166 } 174 }
167 } 175 }
168 // new flow rule added 176 // new flow rule added
169 existing.add(f); 177 existing.add(f);
170 - // TODO: Should we notify only if it's "remote" event? 178 + notifyDelegate(FlowRuleBatchEvent.requested(
171 - //notifyDelegate(new FlowRuleEvent(Type.RULE_ADD_REQUESTED, rule)); 179 + new FlowRuleBatchRequest(1, /* FIXME generate something */
172 - return true; 180 + Arrays.<FlowEntry>asList(f),
181 + Collections.<FlowEntry>emptyList())));
173 } 182 }
174 } 183 }
175 184
176 @Override 185 @Override
177 - public boolean deleteFlowRule(FlowRule rule) { 186 + public void deleteFlowRule(FlowRule rule) {
178 187
179 List<StoredFlowEntry> entries = getFlowEntries(rule.deviceId(), rule.id()); 188 List<StoredFlowEntry> entries = getFlowEntries(rule.deviceId(), rule.id());
180 189
...@@ -184,14 +193,17 @@ public class SimpleFlowRuleStore ...@@ -184,14 +193,17 @@ public class SimpleFlowRuleStore
184 synchronized (entry) { 193 synchronized (entry) {
185 entry.setState(FlowEntryState.PENDING_REMOVE); 194 entry.setState(FlowEntryState.PENDING_REMOVE);
186 // TODO: Should we notify only if it's "remote" event? 195 // TODO: Should we notify only if it's "remote" event?
187 - //notifyDelegate(new FlowRuleEvent(Type.RULE_REMOVE_REQUESTED, rule)); 196 + notifyDelegate(FlowRuleBatchEvent.requested(
188 - return true; 197 + new FlowRuleBatchRequest(1, /* FIXME generate something */
198 + Collections.<FlowEntry>emptyList(),
199 + Arrays.<FlowEntry>asList(entry))));
189 } 200 }
190 } 201 }
191 } 202 }
192 } 203 }
204 +
205 +
193 //log.warn("Cannot find rule {}", rule); 206 //log.warn("Cannot find rule {}", rule);
194 - return false;
195 } 207 }
196 208
197 @Override 209 @Override
...@@ -237,4 +249,24 @@ public class SimpleFlowRuleStore ...@@ -237,4 +249,24 @@ public class SimpleFlowRuleStore
237 } 249 }
238 return null; 250 return null;
239 } 251 }
252 +
253 + @Override
254 + public Future<CompletedBatchOperation> storeBatch(
255 + FlowRuleBatchOperation batchOperation) {
256 + for (FlowRuleBatchEntry entry : batchOperation.getOperations()) {
257 + if (entry.getOperator().equals(FlowRuleOperation.ADD)) {
258 + storeFlowRule(entry.getTarget());
259 + } else if (entry.getOperator().equals(FlowRuleOperation.REMOVE)) {
260 + deleteFlowRule(entry.getTarget());
261 + } else {
262 + throw new UnsupportedOperationException("Unsupported operation type");
263 + }
264 + }
265 + return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet()));
266 + }
267 +
268 + @Override
269 + public void batchOperationComplete(FlowRuleBatchEvent event) {
270 + notifyDelegate(event);
271 + }
240 } 272 }
......
...@@ -269,7 +269,7 @@ public class SimpleHostStore ...@@ -269,7 +269,7 @@ public class SimpleHostStore
269 } 269 }
270 270
271 // Auxiliary extension to allow location to mutate. 271 // Auxiliary extension to allow location to mutate.
272 - private class StoredHost extends DefaultHost { 272 + private static final class StoredHost extends DefaultHost {
273 private HostLocation location; 273 private HostLocation location;
274 274
275 /** 275 /**
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <prerequisites>
8 + <maven>3.0.0</maven>
9 + </prerequisites>
10 +
11 + <parent>
12 + <groupId>org.onlab.onos</groupId>
13 + <artifactId>onos</artifactId>
14 + <version>1.0.0-SNAPSHOT</version>
15 + <relativePath>../pom.xml</relativePath>
16 + </parent>
17 +
18 + <artifactId>onos-docs-external</artifactId>
19 + <packaging>pom</packaging>
20 +
21 + <description>ONOS Java API documentation</description>
22 +
23 + <modules>
24 + <module>..</module>
25 + </modules>
26 +
27 + <url>http://onlab.us/</url>
28 +
29 + <build>
30 + <plugins>
31 + <plugin>
32 + <groupId>org.apache.maven.plugins</groupId>
33 + <artifactId>maven-javadoc-plugin</artifactId>
34 + <version>2.10.1</version>
35 + <configuration>
36 + <show>package</show>
37 + <excludePackageNames>org.onlab.thirdparty:*.impl:*.impl.*:org.onlab.onos.provider.*:org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli*:org.onlab.onos.tvue:org.onlab.onos.foo:org.onlab.onos.mobility:org.onlab.onos.proxyarp:org.onlab.onos.fwd:org.onlab.onos.ifwd:org.onlab.onos.optical:org.onlab.onos.config:org.onlab.onos.calendar:org.onlab.onos.sdnip*:org.onlab.onos.metrics</excludePackageNames>
38 + <docfilessubdirs>true</docfilessubdirs>
39 + <doctitle>ONOS Java API</doctitle>
40 + <groups>
41 + <group>
42 + <title>Network Model &amp; Services</title>
43 + <packages>
44 + org.onlab.onos:org.onlab.onos.*
45 + </packages>
46 + </group>
47 + <group>
48 + <title>Utilities</title>
49 + <packages>
50 + org.onlab.*
51 + </packages>
52 + </group>
53 + </groups>
54 + </configuration>
55 + </plugin>
56 + </plugins>
57 + </build>
58 +
59 +</project>
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <prerequisites>
8 + <maven>3.0.0</maven>
9 + </prerequisites>
10 +
11 + <parent>
12 + <groupId>org.onlab.onos</groupId>
13 + <artifactId>onos</artifactId>
14 + <version>1.0.0-SNAPSHOT</version>
15 + <relativePath>../pom.xml</relativePath>
16 + </parent>
17 +
18 + <artifactId>onos-docs</artifactId>
19 + <packaging>pom</packaging>
20 +
21 + <description>ONOS Java API documentation</description>
22 +
23 + <modules>
24 + <module>..</module>
25 + </modules>
26 +
27 + <url>http://onlab.us/</url>
28 +
29 + <build>
30 + <plugins>
31 + <plugin>
32 + <groupId>org.apache.maven.plugins</groupId>
33 + <artifactId>maven-javadoc-plugin</artifactId>
34 + <version>2.10.1</version>
35 + <configuration>
36 + <show>package</show>
37 + <docfilessubdirs>true</docfilessubdirs>
38 + <doctitle>ONOS Java API</doctitle>
39 + <groups>
40 + <group>
41 + <title>Network Model &amp; Services</title>
42 + <packages>
43 + org.onlab.onos:org.onlab.onos.*
44 + </packages>
45 + </group>
46 + <group>
47 + <title>Core Subsystems</title>
48 + <packages>
49 + org.onlab.onos.impl:org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*:org.onlab.onos.net.intent.impl:org.onlab.onos.net.proxyarp.impl:org.onlab.onos.mastership.impl:org.onlab.onos.json:org.onlab.onos.json.*:org.onlab.onos.provider.host.impl:org.onlab.onos.provider.lldp.impl:org.onlab.onos.net.statistic.impl
50 + </packages>
51 + </group>
52 + <group>
53 + <title>OpenFlow Providers &amp; Controller
54 + </title>
55 + <packages>
56 + org.onlab.onos.provider.of.*:org.onlab.onos.openflow.*
57 + </packages>
58 + </group>
59 + <group>
60 + <title>Utilities</title>
61 + <packages>
62 + org.onlab.*
63 + </packages>
64 + </group>
65 + <group>
66 + <title>GUI, REST &amp; Command-Line</title>
67 + <packages>
68 + org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli:org.onlab.onos.gui.*:org.onlab.onos.rest.*:org.onlab.onos.cli.*
69 + </packages>
70 + </group>
71 + <group>
72 + <title>Sample Applications</title>
73 + <packages>
74 + org.onlab.onos.tvue:org.onlab.onos.fwd:org.onlab.onos.ifwd:org.onlab.onos.mobility:org.onlab.onos.proxyarp:org.onlab.onos.foo:org.onlab.onos.calendar:org.onlab.onos.sdnip:org.onlab.onos.sdnip.*:org.onlab.onos.optical:org.onlab.onos.optical.*:org.onlab.onos.metrics.*:org.onlab.onos.config
75 + </packages>
76 + </group>
77 + </groups>
78 + <excludePackageNames>org.onlab.thirdparty
79 + </excludePackageNames>
80 + </configuration>
81 + </plugin>
82 + </plugins>
83 + </build>
84 +
85 +</project>
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
35 <bundle>mvn:io.netty/netty-transport-native-epoll/4.0.23.Final</bundle> 35 <bundle>mvn:io.netty/netty-transport-native-epoll/4.0.23.Final</bundle>
36 <bundle>mvn:commons-pool/commons-pool/1.6</bundle> 36 <bundle>mvn:commons-pool/commons-pool/1.6</bundle>
37 37
38 - <bundle>mvn:com.hazelcast/hazelcast/3.3</bundle> 38 + <bundle>mvn:com.hazelcast/hazelcast/3.3.2</bundle>
39 <bundle>mvn:io.dropwizard.metrics/metrics-core/3.1.0</bundle> 39 <bundle>mvn:io.dropwizard.metrics/metrics-core/3.1.0</bundle>
40 <bundle>mvn:io.dropwizard.metrics/metrics-json/3.1.0</bundle> 40 <bundle>mvn:io.dropwizard.metrics/metrics-json/3.1.0</bundle>
41 <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle> 41 <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle>
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
30 <groupId>org.projectfloodlight</groupId> 30 <groupId>org.projectfloodlight</groupId>
31 <artifactId>openflowj</artifactId> 31 <artifactId>openflowj</artifactId>
32 <!-- FIXME once experimenter gets merged to upstream --> 32 <!-- FIXME once experimenter gets merged to upstream -->
33 - <version>0.3.8-optical_experimenter3</version> 33 + <version>0.3.8-optical_experimenter4</version>
34 </dependency> 34 </dependency>
35 <dependency> 35 <dependency>
36 <groupId>io.netty</groupId> 36 <groupId>io.netty</groupId>
......
1 package org.onlab.onos.openflow.controller; 1 package org.onlab.onos.openflow.controller;
2 2
3 +
4 +import java.util.Collections;
5 +import java.util.concurrent.atomic.AtomicBoolean;
6 +
3 import org.onlab.packet.Ethernet; 7 import org.onlab.packet.Ethernet;
4 import org.projectfloodlight.openflow.protocol.OFPacketIn; 8 import org.projectfloodlight.openflow.protocol.OFPacketIn;
5 import org.projectfloodlight.openflow.protocol.OFPacketOut; 9 import org.projectfloodlight.openflow.protocol.OFPacketOut;
...@@ -9,9 +13,6 @@ import org.projectfloodlight.openflow.protocol.match.MatchField; ...@@ -9,9 +13,6 @@ import org.projectfloodlight.openflow.protocol.match.MatchField;
9 import org.projectfloodlight.openflow.types.OFBufferId; 13 import org.projectfloodlight.openflow.types.OFBufferId;
10 import org.projectfloodlight.openflow.types.OFPort; 14 import org.projectfloodlight.openflow.types.OFPort;
11 15
12 -import java.util.Collections;
13 -import java.util.concurrent.atomic.AtomicBoolean;
14 -
15 public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext { 16 public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
16 17
17 private final AtomicBoolean free = new AtomicBoolean(true); 18 private final AtomicBoolean free = new AtomicBoolean(true);
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 <modelVersion>4.0.0</modelVersion> 5 <modelVersion>4.0.0</modelVersion>
6 6
7 + <prerequisites>
8 + <maven>3.0.0</maven>
9 + </prerequisites>
10 +
7 <groupId>org.onlab.onos</groupId> 11 <groupId>org.onlab.onos</groupId>
8 <artifactId>onos</artifactId> 12 <artifactId>onos</artifactId>
9 <packaging>pom</packaging> 13 <packaging>pom</packaging>
...@@ -28,7 +32,6 @@ ...@@ -28,7 +32,6 @@
28 32
29 <licenses> 33 <licenses>
30 <license> 34 <license>
31 - <!-- TODO: Is this really our license scheme? -->
32 <name>Apache License, Version 2.0</name> 35 <name>Apache License, Version 2.0</name>
33 <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> 36 <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
34 </license> 37 </license>
...@@ -192,7 +195,7 @@ ...@@ -192,7 +195,7 @@
192 <dependency> 195 <dependency>
193 <groupId>com.hazelcast</groupId> 196 <groupId>com.hazelcast</groupId>
194 <artifactId>hazelcast</artifactId> 197 <artifactId>hazelcast</artifactId>
195 - <version>3.3</version> 198 + <version>3.3.2</version>
196 </dependency> 199 </dependency>
197 <dependency> 200 <dependency>
198 <groupId>com.eclipsesource.minimal-json</groupId> 201 <groupId>com.eclipsesource.minimal-json</groupId>
...@@ -528,59 +531,6 @@ ...@@ -528,59 +531,6 @@
528 </execution> 531 </execution>
529 </executions> 532 </executions>
530 </plugin> 533 </plugin>
531 -
532 - <plugin>
533 - <groupId>org.apache.maven.plugins</groupId>
534 - <artifactId>maven-javadoc-plugin</artifactId>
535 - <version>2.10.1</version>
536 - <configuration>
537 - <show>package</show>
538 - <docfilessubdirs>true</docfilessubdirs>
539 - <doctitle>ONOS Java API</doctitle>
540 - <groups>
541 - <group>
542 - <title>Network Model &amp; Services</title>
543 - <packages>
544 - org.onlab.onos:org.onlab.onos.*
545 - </packages>
546 - </group>
547 - <group>
548 - <title>Core Subsystems</title>
549 - <packages>
550 - org.onlab.onos.impl:org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*:org.onlab.onos.net.intent.impl:org.onlab.onos.net.proxyarp.impl:org.onlab.onos.mastership.impl:org.onlab.onos.json:org.onlab.onos.json.*:org.onlab.onos.provider.host.impl:org.onlab.onos.provider.lldp.impl:org.onlab.onos.net.statistic.impl
551 - </packages>
552 - </group>
553 - <group>
554 - <title>OpenFlow Providers &amp; Controller
555 - </title>
556 - <packages>
557 - org.onlab.onos.provider.of.*:org.onlab.onos.openflow.*
558 - </packages>
559 - </group>
560 - <group>
561 - <title>Utilities</title>
562 - <packages>
563 - org.onlab.*
564 - </packages>
565 - </group>
566 - <group>
567 - <title>GUI, REST &amp; Command-Line</title>
568 - <packages>
569 - org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli:org.onlab.onos.gui.*:org.onlab.onos.rest.*:org.onlab.onos.cli.*
570 - </packages>
571 - </group>
572 - <group>
573 - <title>Sample Applications</title>
574 - <packages>
575 - org.onlab.onos.tvue:org.onlab.onos.fwd:org.onlab.onos.ifwd:org.onlab.onos.mobility:org.onlab.onos.proxyarp:org.onlab.onos.foo:org.onlab.onos.calendar:org.onlab.onos.sdnip:org.onlab.onos.sdnip.*:org.onlab.onos.optical:org.onlab.onos.optical.*:org.onlab.onos.metrics.*
576 - </packages>
577 - </group>
578 - </groups>
579 - <excludePackageNames>org.onlab.thirdparty
580 - </excludePackageNames>
581 - </configuration>
582 - </plugin>
583 -
584 </plugins> 534 </plugins>
585 </build> 535 </build>
586 536
...@@ -607,10 +557,6 @@ ...@@ -607,10 +557,6 @@
607 </rulesets> 557 </rulesets>
608 </configuration> 558 </configuration>
609 </plugin> 559 </plugin>
610 -
611 </plugins> 560 </plugins>
612 </reporting> 561 </reporting>
613 - <prerequisites>
614 - <maven>3.0.0</maven>
615 - </prerequisites>
616 </project> 562 </project>
......
...@@ -90,7 +90,7 @@ public class LinkDiscovery implements TimerTask { ...@@ -90,7 +90,7 @@ public class LinkDiscovery implements TimerTask {
90 * Instantiates discovery manager for the given physical switch. Creates a 90 * Instantiates discovery manager for the given physical switch. Creates a
91 * generic LLDP packet that will be customized for the port it is sent out on. 91 * generic LLDP packet that will be customized for the port it is sent out on.
92 * Starts the the timer for the discovery process. 92 * Starts the the timer for the discovery process.
93 - * @param device the physical switch 93 + * @param device the physical switch
94 * @param masterService 94 * @param masterService
95 * @param useBDDP flag to also use BDDP for discovery 95 * @param useBDDP flag to also use BDDP for discovery
96 */ 96 */
...@@ -217,7 +217,7 @@ public class LinkDiscovery implements TimerTask { ...@@ -217,7 +217,7 @@ public class LinkDiscovery implements TimerTask {
217 final PortNumber srcPort = PortNumber.portNumber(onoslldp.getPort()); 217 final PortNumber srcPort = PortNumber.portNumber(onoslldp.getPort());
218 final DeviceId srcDeviceId = DeviceId.deviceId(onoslldp.getDeviceString()); 218 final DeviceId srcDeviceId = DeviceId.deviceId(onoslldp.getDeviceString());
219 final DeviceId dstDeviceId = context.inPacket().receivedFrom().deviceId(); 219 final DeviceId dstDeviceId = context.inPacket().receivedFrom().deviceId();
220 - this.ackProbe(srcPort.toLong()); 220 + this.ackProbe(dstPort.toLong());
221 ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort); 221 ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort);
222 ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort); 222 ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort);
223 223
...@@ -245,7 +245,7 @@ public class LinkDiscovery implements TimerTask { ...@@ -245,7 +245,7 @@ public class LinkDiscovery implements TimerTask {
245 */ 245 */
246 @Override 246 @Override
247 public void run(final Timeout t) { 247 public void run(final Timeout t) {
248 - this.log.debug("sending probes"); 248 + this.log.trace("sending probes");
249 synchronized (this) { 249 synchronized (this) {
250 final Iterator<Long> fastIterator = this.fastPorts.iterator(); 250 final Iterator<Long> fastIterator = this.fastPorts.iterator();
251 Long portNumber; 251 Long portNumber;
...@@ -256,7 +256,7 @@ public class LinkDiscovery implements TimerTask { ...@@ -256,7 +256,7 @@ public class LinkDiscovery implements TimerTask {
256 .getAndIncrement(); 256 .getAndIncrement();
257 257
258 if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) { 258 if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) {
259 - this.log.debug("sending fast probe to port"); 259 + this.log.trace("sending fast probe to port");
260 sendProbes(portNumber); 260 sendProbes(portNumber);
261 } else { 261 } else {
262 // Update fast and slow ports 262 // Update fast and slow ports
...@@ -278,7 +278,7 @@ public class LinkDiscovery implements TimerTask { ...@@ -278,7 +278,7 @@ public class LinkDiscovery implements TimerTask {
278 Iterator<Long> slowIterator = this.slowPorts.iterator(); 278 Iterator<Long> slowIterator = this.slowPorts.iterator();
279 while (slowIterator.hasNext()) { 279 while (slowIterator.hasNext()) {
280 portNumber = slowIterator.next(); 280 portNumber = slowIterator.next();
281 - this.log.debug("sending slow probe to port {}", portNumber); 281 + this.log.trace("sending slow probe to port {}", portNumber);
282 282
283 sendProbes(portNumber); 283 sendProbes(portNumber);
284 284
......
...@@ -23,6 +23,8 @@ import org.projectfloodlight.openflow.protocol.OFFlowRemoved; ...@@ -23,6 +23,8 @@ import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
23 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; 23 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
24 import org.projectfloodlight.openflow.protocol.OFInstructionType; 24 import org.projectfloodlight.openflow.protocol.OFInstructionType;
25 import org.projectfloodlight.openflow.protocol.action.OFAction; 25 import org.projectfloodlight.openflow.protocol.action.OFAction;
26 +import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
27 +import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
26 import org.projectfloodlight.openflow.protocol.action.OFActionOutput; 28 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
27 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst; 29 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
28 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc; 30 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
...@@ -34,6 +36,7 @@ import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; ...@@ -34,6 +36,7 @@ import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
34 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions; 36 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
35 import org.projectfloodlight.openflow.protocol.match.Match; 37 import org.projectfloodlight.openflow.protocol.match.Match;
36 import org.projectfloodlight.openflow.protocol.match.MatchField; 38 import org.projectfloodlight.openflow.protocol.match.MatchField;
39 +import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
37 import org.projectfloodlight.openflow.types.IPv4Address; 40 import org.projectfloodlight.openflow.types.IPv4Address;
38 import org.projectfloodlight.openflow.types.Masked; 41 import org.projectfloodlight.openflow.types.Masked;
39 import org.slf4j.Logger; 42 import org.slf4j.Logger;
...@@ -166,6 +169,15 @@ public class FlowEntryBuilder { ...@@ -166,6 +169,15 @@ public class FlowEntryBuilder {
166 builder.setIpSrc(IpPrefix.valueOf(si.getInt())); 169 builder.setIpSrc(IpPrefix.valueOf(si.getInt()));
167 } 170 }
168 break; 171 break;
172 + case EXPERIMENTER:
173 + OFActionExperimenter exp = (OFActionExperimenter) act;
174 + if (exp.getExperimenter() == 0x80005A06) {
175 + OFActionCircuit ct = (OFActionCircuit) exp;
176 + builder.setLambda(((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber());
177 + } else {
178 + log.warn("Unsupported OFActionExperimenter {}", exp.getExperimenter());
179 + }
180 + break;
169 case SET_TP_DST: 181 case SET_TP_DST:
170 case SET_TP_SRC: 182 case SET_TP_SRC:
171 case POP_MPLS: 183 case POP_MPLS:
...@@ -188,7 +200,7 @@ public class FlowEntryBuilder { ...@@ -188,7 +200,7 @@ public class FlowEntryBuilder {
188 case DEC_MPLS_TTL: 200 case DEC_MPLS_TTL:
189 case DEC_NW_TTL: 201 case DEC_NW_TTL:
190 case ENQUEUE: 202 case ENQUEUE:
191 - case EXPERIMENTER: 203 +
192 case GROUP: 204 case GROUP:
193 default: 205 default:
194 log.warn("Action type {} not yet implemented.", act.getType()); 206 log.warn("Action type {} not yet implemented.", act.getType());
...@@ -268,6 +280,10 @@ public class FlowEntryBuilder { ...@@ -268,6 +280,10 @@ public class FlowEntryBuilder {
268 case TCP_SRC: 280 case TCP_SRC:
269 builder.matchTcpSrc((short) match.get(MatchField.TCP_SRC).getPort()); 281 builder.matchTcpSrc((short) match.get(MatchField.TCP_SRC).getPort());
270 break; 282 break;
283 + case OCH_SIGID:
284 + builder.matchLambda(match.get(MatchField.OCH_SIGID).getChannelNumber());
285 + break;
286 + case OCH_SIGTYPE_BASIC:
271 case ARP_OP: 287 case ARP_OP:
272 case ARP_SHA: 288 case ARP_SHA:
273 case ARP_SPA: 289 case ARP_SPA:
......
...@@ -14,6 +14,7 @@ import org.onlab.onos.net.flow.criteria.Criteria.EthCriterion; ...@@ -14,6 +14,7 @@ import org.onlab.onos.net.flow.criteria.Criteria.EthCriterion;
14 import org.onlab.onos.net.flow.criteria.Criteria.EthTypeCriterion; 14 import org.onlab.onos.net.flow.criteria.Criteria.EthTypeCriterion;
15 import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion; 15 import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion;
16 import org.onlab.onos.net.flow.criteria.Criteria.IPProtocolCriterion; 16 import org.onlab.onos.net.flow.criteria.Criteria.IPProtocolCriterion;
17 +import org.onlab.onos.net.flow.criteria.Criteria.LambdaCriterion;
17 import org.onlab.onos.net.flow.criteria.Criteria.PortCriterion; 18 import org.onlab.onos.net.flow.criteria.Criteria.PortCriterion;
18 import org.onlab.onos.net.flow.criteria.Criteria.TcpPortCriterion; 19 import org.onlab.onos.net.flow.criteria.Criteria.TcpPortCriterion;
19 import org.onlab.onos.net.flow.criteria.Criteria.VlanIdCriterion; 20 import org.onlab.onos.net.flow.criteria.Criteria.VlanIdCriterion;
...@@ -21,6 +22,8 @@ import org.onlab.onos.net.flow.criteria.Criteria.VlanPcpCriterion; ...@@ -21,6 +22,8 @@ import org.onlab.onos.net.flow.criteria.Criteria.VlanPcpCriterion;
21 import org.onlab.onos.net.flow.criteria.Criterion; 22 import org.onlab.onos.net.flow.criteria.Criterion;
22 import org.onlab.onos.net.flow.instructions.Instruction; 23 import org.onlab.onos.net.flow.instructions.Instruction;
23 import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction; 24 import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
25 +import org.onlab.onos.net.flow.instructions.L0ModificationInstruction;
26 +import org.onlab.onos.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
24 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction; 27 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction;
25 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction; 28 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
26 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction; 29 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
...@@ -35,6 +38,7 @@ import org.projectfloodlight.openflow.protocol.OFFlowModFlags; ...@@ -35,6 +38,7 @@ import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
35 import org.projectfloodlight.openflow.protocol.action.OFAction; 38 import org.projectfloodlight.openflow.protocol.action.OFAction;
36 import org.projectfloodlight.openflow.protocol.match.Match; 39 import org.projectfloodlight.openflow.protocol.match.Match;
37 import org.projectfloodlight.openflow.protocol.match.MatchField; 40 import org.projectfloodlight.openflow.protocol.match.MatchField;
41 +import org.projectfloodlight.openflow.types.CircuitSignalID;
38 import org.projectfloodlight.openflow.types.EthType; 42 import org.projectfloodlight.openflow.types.EthType;
39 import org.projectfloodlight.openflow.types.IPv4Address; 43 import org.projectfloodlight.openflow.types.IPv4Address;
40 import org.projectfloodlight.openflow.types.IpProtocol; 44 import org.projectfloodlight.openflow.types.IpProtocol;
...@@ -137,6 +141,9 @@ public class FlowModBuilder { ...@@ -137,6 +141,9 @@ public class FlowModBuilder {
137 case DROP: 141 case DROP:
138 log.warn("Saw drop action; assigning drop action"); 142 log.warn("Saw drop action; assigning drop action");
139 return new LinkedList<>(); 143 return new LinkedList<>();
144 + case L0MODIFICATION:
145 + acts.add(buildL0Modification(i));
146 + break;
140 case L2MODIFICATION: 147 case L2MODIFICATION:
141 acts.add(buildL2Modification(i)); 148 acts.add(buildL2Modification(i));
142 break; 149 break;
...@@ -157,6 +164,20 @@ public class FlowModBuilder { ...@@ -157,6 +164,20 @@ public class FlowModBuilder {
157 return acts; 164 return acts;
158 } 165 }
159 166
167 + private OFAction buildL0Modification(Instruction i) {
168 + L0ModificationInstruction l0m = (L0ModificationInstruction) i;
169 + switch (l0m.subtype()) {
170 + case LAMBDA:
171 + ModLambdaInstruction ml = (ModLambdaInstruction) i;
172 + return factory.actions().circuit(factory.oxms().ochSigidBasic(
173 + new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
174 + default:
175 + log.warn("Unimplemented action type {}.", l0m.subtype());
176 + break;
177 + }
178 + return null;
179 + }
180 +
160 private OFAction buildL3Modification(Instruction i) { 181 private OFAction buildL3Modification(Instruction i) {
161 L3ModificationInstruction l3m = (L3ModificationInstruction) i; 182 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
162 ModIPInstruction ip; 183 ModIPInstruction ip;
...@@ -261,6 +282,11 @@ public class FlowModBuilder { ...@@ -261,6 +282,11 @@ public class FlowModBuilder {
261 tp = (TcpPortCriterion) c; 282 tp = (TcpPortCriterion) c;
262 mBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(tp.tcpPort())); 283 mBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(tp.tcpPort()));
263 break; 284 break;
285 + case OCH_SIGID:
286 + LambdaCriterion lc = (LambdaCriterion) c;
287 + mBuilder.setExact(MatchField.OCH_SIGID,
288 + new CircuitSignalID((byte) 1, (byte) 2, lc.lambda(), (short) 1));
289 + break;
264 case ARP_OP: 290 case ARP_OP:
265 case ARP_SHA: 291 case ARP_SHA:
266 case ARP_SPA: 292 case ARP_SPA:
......
...@@ -10,7 +10,7 @@ import java.util.Set; ...@@ -10,7 +10,7 @@ import java.util.Set;
10 import java.util.concurrent.ConcurrentHashMap; 10 import java.util.concurrent.ConcurrentHashMap;
11 import java.util.concurrent.CountDownLatch; 11 import java.util.concurrent.CountDownLatch;
12 import java.util.concurrent.ExecutionException; 12 import java.util.concurrent.ExecutionException;
13 -import java.util.concurrent.Future; 13 +import java.util.concurrent.Executor;
14 import java.util.concurrent.TimeUnit; 14 import java.util.concurrent.TimeUnit;
15 import java.util.concurrent.TimeoutException; 15 import java.util.concurrent.TimeoutException;
16 import java.util.concurrent.atomic.AtomicBoolean; 16 import java.util.concurrent.atomic.AtomicBoolean;
...@@ -69,9 +69,11 @@ import org.projectfloodlight.openflow.types.U32; ...@@ -69,9 +69,11 @@ import org.projectfloodlight.openflow.types.U32;
69 import org.slf4j.Logger; 69 import org.slf4j.Logger;
70 70
71 import com.google.common.collect.ArrayListMultimap; 71 import com.google.common.collect.ArrayListMultimap;
72 -import com.google.common.collect.Lists;
73 import com.google.common.collect.Maps; 72 import com.google.common.collect.Maps;
74 import com.google.common.collect.Multimap; 73 import com.google.common.collect.Multimap;
74 +import com.google.common.collect.Sets;
75 +import com.google.common.util.concurrent.ExecutionList;
76 +import com.google.common.util.concurrent.ListenableFuture;
75 77
76 /** 78 /**
77 * Provider which uses an OpenFlow controller to detect network 79 * Provider which uses an OpenFlow controller to detect network
...@@ -97,6 +99,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -97,6 +99,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
97 99
98 private final InternalFlowProvider listener = new InternalFlowProvider(); 100 private final InternalFlowProvider listener = new InternalFlowProvider();
99 101
102 + // FIXME: This should be an expiring map to ensure futures that don't have
103 + // a future eventually get garbage collected.
100 private final Map<Long, InstallationFuture> pendingFutures = 104 private final Map<Long, InstallationFuture> pendingFutures =
101 new ConcurrentHashMap<Long, InstallationFuture>(); 105 new ConcurrentHashMap<Long, InstallationFuture>();
102 106
...@@ -169,7 +173,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -169,7 +173,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
169 } 173 }
170 174
171 @Override 175 @Override
172 - public Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) { 176 + public ListenableFuture<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) {
173 final Set<Dpid> sws = 177 final Set<Dpid> sws =
174 Collections.newSetFromMap(new ConcurrentHashMap<Dpid, Boolean>()); 178 Collections.newSetFromMap(new ConcurrentHashMap<Dpid, Boolean>());
175 final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>(); 179 final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>();
...@@ -330,18 +334,20 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -330,18 +334,20 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
330 334
331 } 335 }
332 336
333 - private class InstallationFuture implements Future<CompletedBatchOperation> { 337 + private class InstallationFuture implements ListenableFuture<CompletedBatchOperation> {
334 338
335 private final Set<Dpid> sws; 339 private final Set<Dpid> sws;
336 private final AtomicBoolean ok = new AtomicBoolean(true); 340 private final AtomicBoolean ok = new AtomicBoolean(true);
337 private final Map<Long, FlowRuleBatchEntry> fms; 341 private final Map<Long, FlowRuleBatchEntry> fms;
338 342
339 - private final List<FlowEntry> offendingFlowMods = Lists.newLinkedList(); 343 + private final Set<FlowEntry> offendingFlowMods = Sets.newHashSet();
340 344
341 private final CountDownLatch countDownLatch; 345 private final CountDownLatch countDownLatch;
342 private Long pendingXid; 346 private Long pendingXid;
343 private BatchState state; 347 private BatchState state;
344 348
349 + private final ExecutionList executionList = new ExecutionList();
350 +
345 public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) { 351 public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) {
346 this.state = BatchState.STARTED; 352 this.state = BatchState.STARTED;
347 this.sws = sws; 353 this.sws = sws;
...@@ -350,6 +356,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -350,6 +356,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
350 } 356 }
351 357
352 public void fail(OFErrorMsg msg, Dpid dpid) { 358 public void fail(OFErrorMsg msg, Dpid dpid) {
359 +
353 ok.set(false); 360 ok.set(false);
354 removeRequirement(dpid); 361 removeRequirement(dpid);
355 FlowEntry fe = null; 362 FlowEntry fe = null;
...@@ -422,6 +429,9 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -422,6 +429,9 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
422 429
423 @Override 430 @Override
424 public boolean cancel(boolean mayInterruptIfRunning) { 431 public boolean cancel(boolean mayInterruptIfRunning) {
432 + if (isDone()) {
433 + return false;
434 + }
425 ok.set(false); 435 ok.set(false);
426 this.state = BatchState.CANCELLED; 436 this.state = BatchState.CANCELLED;
427 cleanUp(); 437 cleanUp();
...@@ -434,7 +444,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -434,7 +444,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
434 } 444 }
435 445
436 } 446 }
437 - return isCancelled(); 447 + invokeCallbacks();
448 + return true;
438 } 449 }
439 450
440 @Override 451 @Override
...@@ -444,14 +455,15 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -444,14 +455,15 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
444 455
445 @Override 456 @Override
446 public boolean isDone() { 457 public boolean isDone() {
447 - return this.state == BatchState.FINISHED; 458 + return this.state == BatchState.FINISHED || isCancelled();
448 } 459 }
449 460
450 @Override 461 @Override
451 public CompletedBatchOperation get() throws InterruptedException, ExecutionException { 462 public CompletedBatchOperation get() throws InterruptedException, ExecutionException {
452 countDownLatch.await(); 463 countDownLatch.await();
453 this.state = BatchState.FINISHED; 464 this.state = BatchState.FINISHED;
454 - return new CompletedBatchOperation(ok.get(), offendingFlowMods); 465 + CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods);
466 + return result;
455 } 467 }
456 468
457 @Override 469 @Override
...@@ -460,7 +472,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -460,7 +472,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
460 TimeoutException { 472 TimeoutException {
461 if (countDownLatch.await(timeout, unit)) { 473 if (countDownLatch.await(timeout, unit)) {
462 this.state = BatchState.FINISHED; 474 this.state = BatchState.FINISHED;
463 - return new CompletedBatchOperation(ok.get(), offendingFlowMods); 475 + CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods);
476 + return result;
464 } 477 }
465 throw new TimeoutException(); 478 throw new TimeoutException();
466 } 479 }
...@@ -478,10 +491,21 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -478,10 +491,21 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
478 491
479 private void removeRequirement(Dpid dpid) { 492 private void removeRequirement(Dpid dpid) {
480 countDownLatch.countDown(); 493 countDownLatch.countDown();
494 + if (countDownLatch.getCount() == 0) {
495 + invokeCallbacks();
496 + }
481 sws.remove(dpid); 497 sws.remove(dpid);
482 cleanUp(); 498 cleanUp();
483 } 499 }
484 500
501 + @Override
502 + public void addListener(Runnable runnable, Executor executor) {
503 + executionList.add(runnable, executor);
504 + }
505 +
506 + private void invokeCallbacks() {
507 + executionList.execute();
508 + }
485 } 509 }
486 510
487 } 511 }
......
...@@ -6,5 +6,4 @@ ...@@ -6,5 +6,4 @@
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
8 8
9 -cd $ONOS_ROOT 9 +cd $ONOS_ROOT && mvn clean install && cd docs && mvn javadoc:aggregate
10 -mvn clean install && mvn javadoc:aggregate
......
1 +package org.onlab.metrics;
2 +
3 +import com.codahale.metrics.Gauge;
4 +import com.codahale.metrics.Meter;
5 +
6 +/**
7 + * Metric measurements for events.
8 + */
9 +public class EventMetric {
10 + private static final String GAUGE_TIMESTAMP_NAME = "Timestamp.EpochMs";
11 + private static final String METER_RATE_NAME = "Rate";
12 +
13 + private final MetricsService metricsService;
14 + private final String componentName;
15 + private final String featureName;
16 +
17 + private MetricsComponent metricsComponent;
18 + private MetricsFeature metricsFeature;
19 +
20 + private volatile long lastEventTimestampEpochMs = 0;
21 + private Gauge<Long> lastEventTimestampGauge;
22 + private Meter eventRateMeter;
23 +
24 + /**
25 + * Constructor.
26 + *
27 + * @param metricsService the Metrics Service to use for Metrics
28 + * registration and deregistration
29 + * @param componentName the Metrics Component Name to use for Metrics
30 + * registration and deregistration
31 + * @param featureName the Metrics Feature Name to use for Metrics
32 + * registration and deregistration
33 + */
34 + public EventMetric(MetricsService metricsService, String componentName,
35 + String featureName) {
36 + this.metricsService = metricsService;
37 + this.componentName = componentName;
38 + this.featureName = featureName;
39 + }
40 +
41 + /**
42 + * Registers the metrics.
43 + */
44 + public void registerMetrics() {
45 + metricsComponent = metricsService.registerComponent(componentName);
46 + metricsFeature = metricsComponent.registerFeature(featureName);
47 +
48 + lastEventTimestampEpochMs = 0;
49 + lastEventTimestampGauge =
50 + metricsService.registerMetric(metricsComponent,
51 + metricsFeature,
52 + GAUGE_TIMESTAMP_NAME,
53 + new Gauge<Long>() {
54 + @Override
55 + public Long getValue() {
56 + return lastEventTimestampEpochMs;
57 + }
58 + });
59 +
60 + eventRateMeter = metricsService.createMeter(metricsComponent,
61 + metricsFeature,
62 + METER_RATE_NAME);
63 + }
64 +
65 + /**
66 + * Removes the metrics.
67 + */
68 + public void removeMetrics() {
69 + lastEventTimestampEpochMs = 0;
70 + metricsService.removeMetric(metricsComponent,
71 + metricsFeature,
72 + GAUGE_TIMESTAMP_NAME);
73 + metricsService.removeMetric(metricsComponent,
74 + metricsFeature,
75 + METER_RATE_NAME);
76 + }
77 +
78 + /**
79 + * Updates the metric measurements for a single event.
80 + */
81 + public void eventReceived() {
82 + lastEventTimestampEpochMs = System.currentTimeMillis();
83 + eventRateMeter.mark(1);
84 + }
85 +
86 + /**
87 + * Gets the last event timestamp Gauge (ms from the Epoch).
88 + *
89 + * @return the last event timestamp Gauge (ms from the Epoch)
90 + */
91 + public Gauge<Long> lastEventTimestampGauge() {
92 + return lastEventTimestampGauge;
93 + }
94 +
95 + /**
96 + * Gets the event rate meter.
97 + *
98 + * @return the event rate meter
99 + */
100 + public Meter eventRateMeter() {
101 + return eventRateMeter;
102 + }
103 +}
...@@ -32,7 +32,7 @@ public final class ChassisId { ...@@ -32,7 +32,7 @@ public final class ChassisId {
32 * @param value the value to use. 32 * @param value the value to use.
33 */ 33 */
34 public ChassisId(String value) { 34 public ChassisId(String value) {
35 - this.value = Long.valueOf(value, 16); 35 + this.value = Long.parseLong(value, 16);
36 } 36 }
37 37
38 /** 38 /**
......
...@@ -379,7 +379,7 @@ public class DHCP extends BasePacket { ...@@ -379,7 +379,7 @@ public class DHCP extends BasePacket {
379 // 300 379 // 300
380 int optionsLength = 0; 380 int optionsLength = 0;
381 for (final DHCPOption option : this.options) { 381 for (final DHCPOption option : this.options) {
382 - if (option.getCode() == 0 || option.getCode() == 255) { 382 + if (option.getCode() == 0 || option.getCode() == ((byte) 255)) {
383 optionsLength += 1; 383 optionsLength += 1;
384 } else { 384 } else {
385 optionsLength += 2 + (0xff & option.getLength()); 385 optionsLength += 2 + (0xff & option.getLength());
......
...@@ -438,7 +438,7 @@ public class IPv4 extends BasePacket { ...@@ -438,7 +438,7 @@ public class IPv4 extends BasePacket {
438 438
439 int result = 0; 439 int result = 0;
440 for (int i = 0; i < 4; ++i) { 440 for (int i = 0; i < 4; ++i) {
441 - result |= Integer.valueOf(octets[i]) << (3 - i) * 8; 441 + result |= Integer.parseInt(octets[i]) << (3 - i) * 8;
442 } 442 }
443 return result; 443 return result;
444 } 444 }
...@@ -471,7 +471,7 @@ public class IPv4 extends BasePacket { ...@@ -471,7 +471,7 @@ public class IPv4 extends BasePacket {
471 int result = 0; 471 int result = 0;
472 for (int i = 0; i < 4; ++i) { 472 for (int i = 0; i < 4; ++i) {
473 result = ipAddress >> (3 - i) * 8 & 0xff; 473 result = ipAddress >> (3 - i) * 8 & 0xff;
474 - sb.append(Integer.valueOf(result).toString()); 474 + sb.append(result);
475 if (i != 3) { 475 if (i != 3) {
476 sb.append("."); 476 sb.append(".");
477 } 477 }
......
...@@ -14,7 +14,7 @@ public final class HexString { ...@@ -14,7 +14,7 @@ public final class HexString {
14 */ 14 */
15 public static String toHexString(final byte[] bytes) { 15 public static String toHexString(final byte[] bytes) {
16 int i; 16 int i;
17 - StringBuilder ret = new StringBuilder(); 17 + StringBuilder ret = new StringBuilder(bytes.length * 3 - 1);
18 String tmp; 18 String tmp;
19 for (i = 0; i < bytes.length; i++) { 19 for (i = 0; i < bytes.length; i++) {
20 if (i > 0) { 20 if (i > 0) {
...@@ -31,22 +31,22 @@ public final class HexString { ...@@ -31,22 +31,22 @@ public final class HexString {
31 31
32 public static String toHexString(final long val, final int padTo) { 32 public static String toHexString(final long val, final int padTo) {
33 char[] arr = Long.toHexString(val).toCharArray(); 33 char[] arr = Long.toHexString(val).toCharArray();
34 - String ret = ""; 34 + StringBuilder ret = new StringBuilder(padTo * 3 - 1);
35 // prepend the right number of leading zeros 35 // prepend the right number of leading zeros
36 int i = 0; 36 int i = 0;
37 for (; i < (padTo * 2 - arr.length); i++) { 37 for (; i < (padTo * 2 - arr.length); i++) {
38 - ret += "0"; 38 + ret.append('0');
39 if ((i % 2) != 0) { 39 if ((i % 2) != 0) {
40 - ret += ":"; 40 + ret.append(':');
41 } 41 }
42 } 42 }
43 for (int j = 0; j < arr.length; j++) { 43 for (int j = 0; j < arr.length; j++) {
44 - ret += arr[j]; 44 + ret.append(arr[j]);
45 if ((((i + j) % 2) != 0) && (j < (arr.length - 1))) { 45 if ((((i + j) % 2) != 0) && (j < (arr.length - 1))) {
46 - ret += ":"; 46 + ret.append(':');
47 } 47 }
48 } 48 }
49 - return ret; 49 + return ret.toString();
50 } 50 }
51 51
52 public static String toHexString(final long val) { 52 public static String toHexString(final long val) {
......
...@@ -163,6 +163,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -163,6 +163,7 @@ public class NettyMessagingService implements MessagingService {
163 handlers.putIfAbsent(type, handler); 163 handlers.putIfAbsent(type, handler);
164 } 164 }
165 165
166 + @Override
166 public void unregisterHandler(String type) { 167 public void unregisterHandler(String type) {
167 handlers.remove(type); 168 handlers.remove(type);
168 } 169 }
...@@ -242,7 +243,7 @@ public class NettyMessagingService implements MessagingService { ...@@ -242,7 +243,7 @@ public class NettyMessagingService implements MessagingService {
242 } 243 }
243 } 244 }
244 245
245 - private class WriteTask implements Runnable { 246 + private static class WriteTask implements Runnable {
246 247
247 private final InternalMessage message; 248 private final InternalMessage message;
248 private final Channel channel; 249 private final Channel channel;
......
...@@ -15,19 +15,18 @@ ...@@ -15,19 +15,18 @@
15 <link rel="stylesheet" href="onos.css"> 15 <link rel="stylesheet" href="onos.css">
16 16
17 <script src="geometry.js"></script> 17 <script src="geometry.js"></script>
18 - <script src="onosui.js"></script> 18 + <script src="onos.js"></script>
19 19
20 </head> 20 </head>
21 <body> 21 <body>
22 <div id="frame"> 22 <div id="frame">
23 <div id="mast"> 23 <div id="mast">
24 - <span class="title"> 24 + <img id="logo" src="img/onos-logo.png" width="60" height="38">
25 - ONOS Web UI 25 + <span class="title">Open Network Operating System</span>
26 - </span>
27 <span class="right"> 26 <span class="right">
28 - <span class="radio">[one]</span> 27 + <span class="radio">[All Layers]</span>
29 - <span class="radio">[two]</span> 28 + <span class="radio">[Packet Only]</span>
30 - <span class="radio">[three]</span> 29 + <span class="radio">[Optical Only]</span>
31 </span> 30 </span>
32 </div> 31 </div>
33 <div id="view"></div> 32 <div id="view"></div>
......
...@@ -10,17 +10,32 @@ ...@@ -10,17 +10,32 @@
10 var api = onos.api; 10 var api = onos.api;
11 11
12 var config = { 12 var config = {
13 - layering: false, 13 + options: {
14 + layering: true,
15 + collisionPrevention: true
16 + },
14 jsonUrl: 'network.json', 17 jsonUrl: 'network.json',
15 iconUrl: { 18 iconUrl: {
16 - pkt: 'pkt.png', 19 + device: 'img/device.png',
17 - opt: 'opt.png' 20 + host: 'img/host.png',
21 + pkt: 'img/pkt.png',
22 + opt: 'img/opt.png'
18 }, 23 },
19 - mastHeight: 32, 24 + mastHeight: 36,
20 force: { 25 force: {
21 - linkDistance: 240, 26 + note: 'node.class or link.class is used to differentiate',
22 - linkStrength: 0.8, 27 + linkDistance: {
23 - charge: -400, 28 + infra: 240,
29 + host: 100
30 + },
31 + linkStrength: {
32 + infra: 1.0,
33 + host: 0.4
34 + },
35 + charge: {
36 + device: -800,
37 + host: -400
38 + },
24 ticksWithoutCollisions: 50, 39 ticksWithoutCollisions: 50,
25 marginLR: 20, 40 marginLR: 20,
26 marginTB: 20, 41 marginTB: 20,
...@@ -31,18 +46,27 @@ ...@@ -31,18 +46,27 @@
31 } 46 }
32 }, 47 },
33 labels: { 48 labels: {
34 - imgPad: 22, 49 + imgPad: 16,
35 padLR: 8, 50 padLR: 8,
36 padTB: 6, 51 padTB: 6,
37 marginLR: 3, 52 marginLR: 3,
38 marginTB: 2 53 marginTB: 2
39 }, 54 },
55 + icons: {
56 + w: 32,
57 + h: 32,
58 + xoff: -12,
59 + yoff: -8
60 + },
40 constraints: { 61 constraints: {
41 ypos: { 62 ypos: {
42 - pkt: 0.3, 63 + host: 0.15,
43 - opt: 0.7 64 + switch: 0.3,
65 + roadm: 0.7
44 } 66 }
45 - } 67 + },
68 + hostLinkWidth: 1.0,
69 + mouseOutTimerDelayMs: 120
46 }, 70 },
47 view = {}, 71 view = {},
48 network = {}, 72 network = {},
...@@ -104,14 +128,23 @@ ...@@ -104,14 +128,23 @@
104 var nw = network.forceWidth, 128 var nw = network.forceWidth,
105 nh = network.forceHeight; 129 nh = network.forceHeight;
106 130
107 - network.data.nodes.forEach(function(n) { 131 + function yPosConstraintForNode(n) {
132 + return config.constraints.ypos[n.type || 'host'];
133 + }
134 +
135 + // Note that both 'devices' and 'hosts' get mapped into the nodes array
136 +
137 + // first, the devices...
138 + network.data.devices.forEach(function(n) {
108 var ypc = yPosConstraintForNode(n), 139 var ypc = yPosConstraintForNode(n),
109 ix = Math.random() * 0.6 * nw + 0.2 * nw, 140 ix = Math.random() * 0.6 * nw + 0.2 * nw,
110 iy = ypc * nh, 141 iy = ypc * nh,
111 node = { 142 node = {
112 id: n.id, 143 id: n.id,
144 + labels: n.labels,
145 + class: 'device',
146 + icon: 'device',
113 type: n.type, 147 type: n.type,
114 - status: n.status,
115 x: ix, 148 x: ix,
116 y: iy, 149 y: iy,
117 constraint: { 150 constraint: {
...@@ -123,21 +156,61 @@ ...@@ -123,21 +156,61 @@
123 network.nodes.push(node); 156 network.nodes.push(node);
124 }); 157 });
125 158
126 - function yPosConstraintForNode(n) { 159 + // then, the hosts...
127 - return config.constraints.ypos[n.type] || 0.5; 160 + network.data.hosts.forEach(function(n) {
128 - } 161 + var ypc = yPosConstraintForNode(n),
162 + ix = Math.random() * 0.6 * nw + 0.2 * nw,
163 + iy = ypc * nh,
164 + node = {
165 + id: n.id,
166 + labels: n.labels,
167 + class: 'host',
168 + icon: 'host',
169 + type: n.type,
170 + x: ix,
171 + y: iy,
172 + constraint: {
173 + weight: 0.7,
174 + y: iy
175 + }
176 + };
177 + network.lookup[n.id] = node;
178 + network.nodes.push(node);
179 + });
129 180
130 181
182 + // now, process the explicit links...
131 network.data.links.forEach(function(n) { 183 network.data.links.forEach(function(n) {
132 var src = network.lookup[n.src], 184 var src = network.lookup[n.src],
133 dst = network.lookup[n.dst], 185 dst = network.lookup[n.dst],
134 id = src.id + "~" + dst.id; 186 id = src.id + "~" + dst.id;
135 187
136 var link = { 188 var link = {
189 + class: 'infra',
137 id: id, 190 id: id,
191 + type: n.type,
192 + width: n.linkWidth,
138 source: src, 193 source: src,
139 target: dst, 194 target: dst,
140 - strength: config.force.linkStrength 195 + strength: config.force.linkStrength.infra
196 + };
197 + network.links.push(link);
198 + });
199 +
200 + // finally, infer host links...
201 + network.data.hosts.forEach(function(n) {
202 + var src = network.lookup[n.id],
203 + dst = network.lookup[n.cp.device],
204 + id = src.id + "~" + dst.id;
205 +
206 + var link = {
207 + class: 'host',
208 + id: id,
209 + type: 'hostLink',
210 + width: config.hostLinkWidth,
211 + source: src,
212 + target: dst,
213 + strength: config.force.linkStrength.host
141 }; 214 };
142 network.links.push(link); 215 network.links.push(link);
143 }); 216 });
...@@ -145,13 +218,15 @@ ...@@ -145,13 +218,15 @@
145 218
146 function createLayout() { 219 function createLayout() {
147 220
221 + var cfg = config.force;
222 +
148 network.force = d3.layout.force() 223 network.force = d3.layout.force()
224 + .size([network.forceWidth, network.forceHeight])
149 .nodes(network.nodes) 225 .nodes(network.nodes)
150 .links(network.links) 226 .links(network.links)
151 - .linkStrength(function(d) { return d.strength; }) 227 + .linkStrength(function(d) { return cfg.linkStrength[d.class]; })
152 - .size([network.forceWidth, network.forceHeight]) 228 + .linkDistance(function(d) { return cfg.linkDistance[d.class]; })
153 - .linkDistance(config.force.linkDistance) 229 + .charge(function(d) { return cfg.charge[d.class]; })
154 - .charge(config.force.charge)
155 .on('tick', tick); 230 .on('tick', tick);
156 231
157 network.svg = d3.select('#view').append('svg') 232 network.svg = d3.select('#view').append('svg')
...@@ -205,9 +280,10 @@ ...@@ -205,9 +280,10 @@
205 network.link = network.svg.append('g').selectAll('.link') 280 network.link = network.svg.append('g').selectAll('.link')
206 .data(network.force.links(), function(d) {return d.id}) 281 .data(network.force.links(), function(d) {return d.id})
207 .enter().append('line') 282 .enter().append('line')
208 - .attr('class', 'link'); 283 + .attr('class', function(d) {return 'link ' + d.class});
284 +
209 285
210 - // TODO: drag behavior 286 + // == define node drag behavior...
211 network.draggedThreshold = d3.scale.linear() 287 network.draggedThreshold = d3.scale.linear()
212 .domain([0, 0.1]) 288 .domain([0, 0.1])
213 .range([5, 20]) 289 .range([5, 20])
...@@ -258,7 +334,11 @@ ...@@ -258,7 +334,11 @@
258 .data(network.force.nodes(), function(d) {return d.id}) 334 .data(network.force.nodes(), function(d) {return d.id})
259 .enter().append('g') 335 .enter().append('g')
260 .attr('class', function(d) { 336 .attr('class', function(d) {
261 - return 'node ' + d.type; 337 + var cls = 'node ' + d.class;
338 + if (d.type) {
339 + cls += ' ' + d.type;
340 + }
341 + return cls;
262 }) 342 })
263 .attr('transform', function(d) { 343 .attr('transform', function(d) {
264 return translate(d.x, d.y); 344 return translate(d.x, d.y);
...@@ -281,29 +361,33 @@ ...@@ -281,29 +361,33 @@
281 } 361 }
282 network.mouseoutTimeout = setTimeout(function() { 362 network.mouseoutTimeout = setTimeout(function() {
283 highlightObject(null); 363 highlightObject(null);
284 - }, 160); 364 + }, config.mouseOutTimerDelayMs);
285 } 365 }
286 }); 366 });
287 367
288 network.nodeRect = network.node.append('rect') 368 network.nodeRect = network.node.append('rect')
289 .attr('rx', 5) 369 .attr('rx', 5)
290 - .attr('ry', 5) 370 + .attr('ry', 5);
291 - .attr('width', 126) 371 + // note that width/height are adjusted to fit the label text
292 - .attr('height', 40);
293 372
294 network.node.each(function(d) { 373 network.node.each(function(d) {
295 var node = d3.select(this), 374 var node = d3.select(this),
296 rect = node.select('rect'), 375 rect = node.select('rect'),
297 - img = node.append('svg:image') 376 + icon = iconUrl(d),
298 - .attr('x', -16)
299 - .attr('y', -16)
300 - .attr('width', 32)
301 - .attr('height', 32)
302 - .attr('xlink:href', iconUrl(d)),
303 text = node.append('text') 377 text = node.append('text')
378 + // TODO: add label cycle behavior
304 .text(d.id) 379 .text(d.id)
305 - .attr('dy', '1.1em'), 380 + .attr('dy', '1.1em');
306 - dummy; 381 +
382 + if (icon) {
383 + var cfg = config.icons;
384 + node.append('svg:image')
385 + .attr('width', cfg.w)
386 + .attr('height', cfg.h)
387 + .attr('xlink:href', icon);
388 + // note, icon relative positioning (x,y) is done after we have
389 + // adjusted the bounds of the rectangle...
390 + }
307 391
308 }); 392 });
309 393
...@@ -352,7 +436,8 @@ ...@@ -352,7 +436,8 @@
352 .attr('height', bounds.y2 - bounds.y1); 436 .attr('height', bounds.y2 - bounds.y1);
353 437
354 node.select('image') 438 node.select('image')
355 - .attr('x', bounds.x1); 439 + .attr('x', bounds.x1 + config.icons.xoff)
440 + .attr('y', bounds.y1 + config.icons.yoff);
356 441
357 d.extent = { 442 d.extent = {
358 left: bounds.x1 - lab.marginLR, 443 left: bounds.x1 - lab.marginLR,
...@@ -384,7 +469,7 @@ ...@@ -384,7 +469,7 @@
384 } 469 }
385 470
386 function iconUrl(d) { 471 function iconUrl(d) {
387 - return config.iconUrl[d.type]; 472 + return config.iconUrl[d.icon];
388 } 473 }
389 474
390 function translate(x, y) { 475 function translate(x, y) {
...@@ -440,7 +525,7 @@ ...@@ -440,7 +525,7 @@
440 function tick(e) { 525 function tick(e) {
441 network.numTicks++; 526 network.numTicks++;
442 527
443 - if (config.layering) { 528 + if (config.options.layering) {
444 // adjust the y-coord of each node, based on y-pos constraints 529 // adjust the y-coord of each node, based on y-pos constraints
445 network.nodes.forEach(function (n) { 530 network.nodes.forEach(function (n) {
446 var z = e.alpha * n.constraint.weight; 531 var z = e.alpha * n.constraint.weight;
...@@ -450,7 +535,7 @@ ...@@ -450,7 +535,7 @@
450 }); 535 });
451 } 536 }
452 537
453 - if (network.preventCollisions) { 538 + if (config.options.collisionPrevention && network.preventCollisions) {
454 preventCollisions(); 539 preventCollisions();
455 } 540 }
456 541
......
1 { 1 {
2 - "id": "network-v1",
3 "meta": { 2 "meta": {
4 - "__comment_1__": "This is sample data for developing the ONOS UI", 3 + "comments": [
5 - "foo": "bar", 4 + "This is sample data for developing the ONOS UI (network view)",
6 - "zoo": "goo" 5 + " in a standalone mode (no server required).",
6 + " Eventually, we will wire this up to live data",
7 + " from the server, via a websocket.",
8 + "",
9 + "Note that this is just a first-draft of the data --",
10 + " additional fields will be added when they are needed."
11 + ],
12 + "otherMetaData": "can go here..."
7 }, 13 },
8 - "nodes": [ 14 + "devices": [
9 { 15 {
10 - "id": "sample1", 16 + "id": "of:0000000000000001",
11 - "type": "opt", 17 + "labels": ["00:00:00:00:00:00:00:01", "of/::01", "opt-1"],
12 - "status": "good" 18 + "type": "roadm"
13 }, 19 },
14 { 20 {
15 - "id": "00:00:00:00:00:00:00:02", 21 + "id": "of:0000000000000002",
16 - "type": "opt", 22 + "labels": ["00:00:00:00:00:00:00:02", "of/::02", "opt-2"],
17 - "status": "good" 23 + "type": "roadm"
18 }, 24 },
19 { 25 {
20 - "id": "00:00:00:00:00:00:00:03", 26 + "id": "of:0000000000000003",
21 - "type": "opt", 27 + "labels": ["00:00:00:00:00:00:00:03", "of/::03", "opt-3"],
22 - "status": "good" 28 + "type": "roadm"
23 }, 29 },
24 { 30 {
25 - "id": "00:00:00:00:00:00:00:04", 31 + "id": "of:0000000000000004",
26 - "type": "opt", 32 + "labels": ["00:00:00:00:00:00:00:04", "of/::04", "opt-4"],
27 - "status": "good" 33 + "type": "roadm"
28 }, 34 },
29 { 35 {
30 - "id": "00:00:00:00:00:00:00:11", 36 + "id": "of:0000000000000011",
31 - "type": "pkt", 37 + "labels": ["00:00:00:00:00:00:00:11", "of/::11", "pkt-11"],
32 - "status": "good" 38 + "type": "switch"
33 }, 39 },
34 { 40 {
35 - "id": "00:00:00:00:00:00:00:12", 41 + "id": "of:0000000000000012",
36 - "type": "pkt", 42 + "labels": ["00:00:00:00:00:00:00:12", "of/::12", "pkt-12"],
37 - "status": "good" 43 + "type": "switch"
38 }, 44 },
39 { 45 {
40 - "id": "00:00:00:00:00:00:00:13", 46 + "id": "of:0000000000000013",
41 - "type": "pkt", 47 + "labels": ["00:00:00:00:00:00:00:13", "of/::13", "pkt-13"],
42 - "status": "good" 48 + "type": "switch"
43 } 49 }
44 ], 50 ],
51 + "linkNotes": [
52 + "even though we have 'directionality' (src/dst), each link is",
53 + " considered to be bi-directional. Note that links between hosts",
54 + " and edge switches are inferred from host information, and not",
55 + " explicitly represented here."
56 + ],
45 "links": [ 57 "links": [
46 - { "src": "sample1", "dst": "00:00:00:00:00:00:00:02" }, 58 + {
47 - { "src": "sample1", "dst": "00:00:00:00:00:00:00:03" }, 59 + "src": "of:0000000000000001",
48 - { "src": "sample1", "dst": "00:00:00:00:00:00:00:04" }, 60 + "dst": "of:0000000000000002",
49 - { "src": "00:00:00:00:00:00:00:02", "dst": "00:00:00:00:00:00:00:03" }, 61 + "type": "optical",
50 - { "src": "00:00:00:00:00:00:00:02", "dst": "00:00:00:00:00:00:00:04" }, 62 + "linkWidth": 1.5
51 - { "src": "00:00:00:00:00:00:00:03", "dst": "00:00:00:00:00:00:00:04" }, 63 + },
52 - { "src": "00:00:00:00:00:00:00:13", "dst": "00:00:00:00:00:00:00:03" }, 64 + {
53 - { "src": "00:00:00:00:00:00:00:12", "dst": "00:00:00:00:00:00:00:02" }, 65 + "src": "of:0000000000000001",
54 - { "src": "00:00:00:00:00:00:00:11", "dst": "sample1" } 66 + "dst": "of:0000000000000003",
67 + "type": "optical",
68 + "linkWidth": 1.5
69 + },
70 + {
71 + "src": "of:0000000000000001",
72 + "dst": "of:0000000000000004",
73 + "type": "optical",
74 + "linkWidth": 1.5
75 + },
76 + {
77 + "src": "of:0000000000000002",
78 + "dst": "of:0000000000000003",
79 + "type": "optical",
80 + "linkWidth": 1.5
81 + },
82 + {
83 + "src": "of:0000000000000002",
84 + "dst": "of:0000000000000004",
85 + "type": "optical",
86 + "linkWidth": 1.5
87 + },
88 + {
89 + "src": "of:0000000000000003",
90 + "dst": "of:0000000000000004",
91 + "type": "optical",
92 + "linkWidth": 1.5
93 + },
94 + {
95 + "src": "of:0000000000000013",
96 + "dst": "of:0000000000000003",
97 + "type": "direct",
98 + "linkWidth": 1.0
99 + },
100 + {
101 + "src": "of:0000000000000012",
102 + "dst": "of:0000000000000002",
103 + "type": "direct",
104 + "linkWidth": 1.0
105 + },
106 + {
107 + "src": "of:0000000000000011",
108 + "dst": "of:0000000000000001",
109 + "type": "direct",
110 + "linkWidth": 1.0
111 + }
112 + ],
113 + "hosts": [
114 + {
115 + "id": "00:60:d3:00:11:01/7",
116 + "labels": ["00:60:d3:00:11:01/7", "Host-11-A"],
117 + "cp" : {
118 + "device": "of:0000000000000011",
119 + "port": 6
120 + }
121 + },
122 + {
123 + "id": "00:60:d3:00:11:02/7",
124 + "labels": ["00:60:d3:00:11:02/7", "Host-11-B"],
125 + "cp" : {
126 + "device": "of:0000000000000011",
127 + "port": 8
128 + }
129 + },
130 + {
131 + "id": "00:60:d3:00:12:01/4",
132 + "labels": ["00:60:d3:00:12:01/4", "Host-12-C"],
133 + "cp" : {
134 + "device": "of:0000000000000012",
135 + "port": 12
136 + }
137 + },
138 + {
139 + "id": "00:60:d3:00:12:02/4",
140 + "labels": ["00:60:d3:00:12:02/4", "Host-12-D"],
141 + "cp" : {
142 + "device": "of:0000000000000012",
143 + "port": 13
144 + }
145 + },
146 + {
147 + "id": "00:60:d3:00:13:01/19",
148 + "labels": ["00:60:d3:00:13:01/19", "Host-13-E"],
149 + "cp" : {
150 + "device": "of:0000000000000013",
151 + "port": 7
152 + }
153 + },
154 + {
155 + "id": "00:60:d3:00:13:02/19",
156 + "labels": ["00:60:d3:00:13:02/19", "Host-13-F"],
157 + "cp" : {
158 + "device": "of:0000000000000013",
159 + "port": 8
160 + }
161 + }
55 ] 162 ]
56 } 163 }
......
...@@ -13,13 +13,15 @@ body, html { ...@@ -13,13 +13,15 @@ body, html {
13 */ 13 */
14 14
15 span.title { 15 span.title {
16 - color: darkblue; 16 + color: #37b;
17 - font-size: 16pt; 17 + font-size: 14pt;
18 font-style: italic; 18 font-style: italic;
19 + vertical-align: 10px;
19 } 20 }
20 21
21 span.radio { 22 span.radio {
22 color: darkslateblue; 23 color: darkslateblue;
24 + font-size: 10pt;
23 } 25 }
24 26
25 span.right { 27 span.right {
...@@ -38,7 +40,7 @@ svg { ...@@ -38,7 +40,7 @@ svg {
38 * Network Graph elements ====================================== 40 * Network Graph elements ======================================
39 */ 41 */
40 42
41 -.link { 43 +svg .link {
42 fill: none; 44 fill: none;
43 stroke: #666; 45 stroke: #666;
44 stroke-width: 1.5px; 46 stroke-width: 1.5px;
...@@ -56,7 +58,7 @@ marker#end { ...@@ -56,7 +58,7 @@ marker#end {
56 stroke-width: 1.5px; 58 stroke-width: 1.5px;
57 } 59 }
58 60
59 -.node rect { 61 +svg .node rect {
60 stroke-width: 1.5px; 62 stroke-width: 1.5px;
61 63
62 transition: opacity 250ms; 64 transition: opacity 250ms;
...@@ -64,13 +66,15 @@ marker#end { ...@@ -64,13 +66,15 @@ marker#end {
64 -moz-transition: opacity 250ms; 66 -moz-transition: opacity 250ms;
65 } 67 }
66 68
67 -/*differentiate between packet and optical nodes*/ 69 +svg .node.device.roadm rect {
68 -svg .node.pkt rect { 70 + fill: #229;
69 - fill: #77a; 71 +}
72 +svg .node.device.switch rect {
73 + fill: #55f;
70 } 74 }
71 75
72 -svg .node.opt rect { 76 +svg .node.host rect {
73 - fill: #7a7; 77 + fill: #787;
74 } 78 }
75 79
76 svg .node text { 80 svg .node text {
...@@ -121,15 +125,13 @@ svg .legend .category text { ...@@ -121,15 +125,13 @@ svg .legend .category text {
121 #frame { 125 #frame {
122 width: 100%; 126 width: 100%;
123 height: 100%; 127 height: 100%;
124 - background-color: #cdf; 128 + background-color: #fff;
125 } 129 }
126 130
127 #mast { 131 #mast {
128 - height: 32px; 132 + height: 36px;
129 - background-color: #abe; 133 + padding: 4px;
134 + background-color: #ccc;
130 vertical-align: baseline; 135 vertical-align: baseline;
131 } 136 }
132 137
133 -#main {
134 - background-color: #99c;
135 -}
......