sangho
Committed by Gerrit Code Review

ONOS-1786: Updates group buckets when link status is changed.

 - Add null check for port map when creating new groups

Change-Id: I92b494d91e908011f2c08be850ccde648e647a09
...@@ -159,6 +159,7 @@ public class DefaultRoutingHandler { ...@@ -159,6 +159,7 @@ public class DefaultRoutingHandler {
159 private boolean repopulateRoutingRulesForRoutes(Set<ArrayList<DeviceId>> routes) { 159 private boolean repopulateRoutingRulesForRoutes(Set<ArrayList<DeviceId>> routes) {
160 rulePopulator.resetCounter(); 160 rulePopulator.resetCounter();
161 for (ArrayList<DeviceId> link: routes) { 161 for (ArrayList<DeviceId> link: routes) {
162 + // When only the source device is defined, reinstall routes to all other devices
162 if (link.size() == 1) { 163 if (link.size() == 1) {
163 ECMPShortestPathGraph ecmpSpg = new ECMPShortestPathGraph(link.get(0), srManager); 164 ECMPShortestPathGraph ecmpSpg = new ECMPShortestPathGraph(link.get(0), srManager);
164 if (populateEcmpRoutingRules(link.get(0), ecmpSpg)) { 165 if (populateEcmpRoutingRules(link.get(0), ecmpSpg)) {
......
...@@ -173,6 +173,11 @@ public class RoutingRulePopulator { ...@@ -173,6 +173,11 @@ public class RoutingRulePopulator {
173 TrafficTreatment treatment = tbuilder.build(); 173 TrafficTreatment treatment = tbuilder.build();
174 TrafficSelector selector = sbuilder.build(); 174 TrafficSelector selector = sbuilder.build();
175 175
176 + if (srManager.getNextObjectiveId(deviceId, ns) <= 0) {
177 + log.warn("No next objective in {} for ns: {}", deviceId, ns);
178 + return false;
179 + }
180 +
176 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective 181 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
177 .builder() 182 .builder()
178 .fromApp(srManager.appId) 183 .fromApp(srManager.appId)
...@@ -183,7 +188,7 @@ public class RoutingRulePopulator { ...@@ -183,7 +188,7 @@ public class RoutingRulePopulator {
183 .withPriority(100) 188 .withPriority(100)
184 .withFlag(ForwardingObjective.Flag.SPECIFIC); 189 .withFlag(ForwardingObjective.Flag.SPECIFIC);
185 log.debug("Installing IPv4 forwarding objective " 190 log.debug("Installing IPv4 forwarding objective "
186 - + "for router IP/subnet {} in switch {}", 191 + + "for router IP/subnet {} in switch {}",
187 ipPrefix, 192 ipPrefix,
188 deviceId); 193 deviceId);
189 srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add()); 194 srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add());
......
...@@ -304,6 +304,10 @@ public class SegmentRoutingManager { ...@@ -304,6 +304,10 @@ public class SegmentRoutingManager {
304 304
305 private void processLinkRemoved(Link link) { 305 private void processLinkRemoved(Link link) {
306 log.debug("A link {} was removed", link.toString()); 306 log.debug("A link {} was removed", link.toString());
307 + DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
308 + if (groupHandler != null) {
309 + groupHandler.portDown(link.src().port());
310 + }
307 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link); 311 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
308 } 312 }
309 313
......
...@@ -25,7 +25,9 @@ import org.onosproject.net.DeviceId; ...@@ -25,7 +25,9 @@ import org.onosproject.net.DeviceId;
25 import org.onosproject.net.Link; 25 import org.onosproject.net.Link;
26 import org.onosproject.net.flow.DefaultTrafficTreatment; 26 import org.onosproject.net.flow.DefaultTrafficTreatment;
27 import org.onosproject.net.flow.TrafficTreatment; 27 import org.onosproject.net.flow.TrafficTreatment;
28 +import org.onosproject.net.flowobjective.DefaultNextObjective;
28 import org.onosproject.net.flowobjective.FlowObjectiveService; 29 import org.onosproject.net.flowobjective.FlowObjectiveService;
30 +import org.onosproject.net.flowobjective.NextObjective;
29 import org.onosproject.net.link.LinkService; 31 import org.onosproject.net.link.LinkService;
30 32
31 /** 33 /**
...@@ -126,18 +128,18 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { ...@@ -126,18 +128,18 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
126 .setMpls(MplsLabel. 128 .setMpls(MplsLabel.
127 mplsLabel(ns.getEdgeLabel())); 129 mplsLabel(ns.getEdgeLabel()));
128 } 130 }
129 - /*GroupBucket updatedBucket = DefaultGroupBucket. 131 +
130 - createSelectGroupBucket(tBuilder.build()); 132 + Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
131 - GroupBuckets updatedBuckets = new GroupBuckets( 133 + if (nextId != null) {
132 - Arrays.asList(updatedBucket)); 134 + NextObjective.Builder nextObjBuilder = DefaultNextObjective
133 - log.debug("newPortToExistingNeighborAtEdgeRouter: " 135 + .builder().withId(nextId)
134 - + "groupService.addBucketsToGroup for neighborset{}", ns); 136 + .withType(NextObjective.Type.HASHED).fromApp(appId);
135 - groupService.addBucketsToGroup(deviceId, 137 +
136 - getGroupKey(ns), 138 + nextObjBuilder.addTreatment(tBuilder.build());
137 - updatedBuckets, 139 +
138 - getGroupKey(ns), 140 + NextObjective nextObjective = nextObjBuilder.add();
139 - appId);*/ 141 + flowObjectiveService.next(deviceId, nextObjective);
140 - //TODO: Use nextObjective APIs to update the next objective 142 + }
141 } 143 }
142 } 144 }
143 145
......
...@@ -186,17 +186,19 @@ public class DefaultGroupHandler { ...@@ -186,17 +186,19 @@ public class DefaultGroupHandler {
186 tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns 186 tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
187 .getEdgeLabel())); 187 .getEdgeLabel()));
188 } 188 }
189 - /* 189 +
190 - * GroupBucket removeBucket = DefaultGroupBucket. 190 + Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
191 - * createSelectGroupBucket(tBuilder.build()); GroupBuckets 191 + if (nextId != null) {
192 - * removeBuckets = new GroupBuckets( Arrays.asList(removeBucket)); 192 + NextObjective.Builder nextObjBuilder = DefaultNextObjective
193 - * log.debug("portDown in device{}: " + 193 + .builder().withType(NextObjective.Type.SIMPLE).withId(nextId).fromApp(appId);
194 - * "groupService.removeBucketsFromGroup " + "for neighborset{}", 194 +
195 - * deviceId, ns); groupService.removeBucketsFromGroup(deviceId, 195 + nextObjBuilder.addTreatment(tBuilder.build());
196 - * getGroupKey(ns), removeBuckets, getGroupKey(ns), appId); 196 +
197 - */ 197 + NextObjective nextObjective = nextObjBuilder.remove();
198 - //TODO: Use next objective API to update the previously created 198 +
199 - //next objectives. 199 + flowObjectiveService.next(deviceId, nextObjective);
200 + }
201 +
200 } 202 }
201 203
202 devicePortMap.get(portDeviceMap.get(port)).remove(port); 204 devicePortMap.get(portDeviceMap.get(port)).remove(port);
...@@ -333,6 +335,11 @@ public class DefaultGroupHandler { ...@@ -333,6 +335,11 @@ public class DefaultGroupHandler {
333 .builder().withId(nextId) 335 .builder().withId(nextId)
334 .withType(NextObjective.Type.HASHED).fromApp(appId); 336 .withType(NextObjective.Type.HASHED).fromApp(appId);
335 for (DeviceId d : ns.getDeviceIds()) { 337 for (DeviceId d : ns.getDeviceIds()) {
338 + if (devicePortMap.get(d) == null) {
339 + log.warn("Device {} is not in the port map yet", d);
340 + return;
341 + }
342 +
336 for (PortNumber sp : devicePortMap.get(d)) { 343 for (PortNumber sp : devicePortMap.get(d)) {
337 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment 344 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
338 .builder(); 345 .builder();
...@@ -341,7 +348,7 @@ public class DefaultGroupHandler { ...@@ -341,7 +348,7 @@ public class DefaultGroupHandler {
341 .setEthSrc(nodeMacAddr); 348 .setEthSrc(nodeMacAddr);
342 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { 349 if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
343 tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns 350 tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
344 - .getEdgeLabel())); 351 + .getEdgeLabel()));
345 } 352 }
346 nextObjBuilder.addTreatment(tBuilder.build()); 353 nextObjBuilder.addTreatment(tBuilder.build());
347 } 354 }
......
...@@ -24,7 +24,9 @@ import org.onosproject.net.DeviceId; ...@@ -24,7 +24,9 @@ import org.onosproject.net.DeviceId;
24 import org.onosproject.net.Link; 24 import org.onosproject.net.Link;
25 import org.onosproject.net.flow.DefaultTrafficTreatment; 25 import org.onosproject.net.flow.DefaultTrafficTreatment;
26 import org.onosproject.net.flow.TrafficTreatment; 26 import org.onosproject.net.flow.TrafficTreatment;
27 +import org.onosproject.net.flowobjective.DefaultNextObjective;
27 import org.onosproject.net.flowobjective.FlowObjectiveService; 28 import org.onosproject.net.flowobjective.FlowObjectiveService;
29 +import org.onosproject.net.flowobjective.NextObjective;
28 import org.onosproject.net.link.LinkService; 30 import org.onosproject.net.link.LinkService;
29 31
30 /** 32 /**
...@@ -114,18 +116,19 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { ...@@ -114,18 +116,19 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler {
114 .setMpls(MplsLabel. 116 .setMpls(MplsLabel.
115 mplsLabel(ns.getEdgeLabel())); 117 mplsLabel(ns.getEdgeLabel()));
116 } 118 }
117 - /*GroupBucket updatedBucket = DefaultGroupBucket. 119 +
118 - createSelectGroupBucket(tBuilder.build()); 120 +
119 - GroupBuckets updatedBuckets = new GroupBuckets( 121 + Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
120 - Arrays.asList(updatedBucket)); 122 + if (nextId != null) {
121 - log.debug("newPortToExistingNeighborAtEdgeRouter: " 123 + NextObjective.Builder nextObjBuilder = DefaultNextObjective
122 - + "groupService.addBucketsToGroup for neighborset{}", ns); 124 + .builder().withId(nextId)
123 - groupService.addBucketsToGroup(deviceId, 125 + .withType(NextObjective.Type.HASHED).fromApp(appId);
124 - getGroupKey(ns), 126 +
125 - updatedBuckets, 127 + nextObjBuilder.addTreatment(tBuilder.build());
126 - getGroupKey(ns), 128 +
127 - appId);*/ 129 + NextObjective nextObjective = nextObjBuilder.add();
128 - //TODO: Use nextObjective APIs to update the next objective 130 + flowObjectiveService.next(deviceId, nextObjective);
131 + }
129 } 132 }
130 } 133 }
131 134
......
...@@ -73,6 +73,7 @@ import org.onosproject.net.group.GroupService; ...@@ -73,6 +73,7 @@ import org.onosproject.net.group.GroupService;
73 import org.slf4j.Logger; 73 import org.slf4j.Logger;
74 74
75 import java.util.ArrayList; 75 import java.util.ArrayList;
76 +import java.util.Arrays;
76 import java.util.Collection; 77 import java.util.Collection;
77 import java.util.Collections; 78 import java.util.Collections;
78 import java.util.List; 79 import java.util.List;
...@@ -207,61 +208,138 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -207,61 +208,138 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
207 208
208 @Override 209 @Override
209 public void next(NextObjective nextObjective) { 210 public void next(NextObjective nextObjective) {
211 +
212 + if (nextObjective.op() == Objective.Operation.REMOVE) {
213 + if (nextObjective.next() == null) {
214 + removeGroup(nextObjective);
215 + } else {
216 + removeBucketFromGroup(nextObjective);
217 + }
218 + } else if (nextObjective.op() == Objective.Operation.ADD) {
219 + NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id());
220 + if (nextGroup != null) {
221 + addBucketToGroup(nextObjective);
222 + } else {
223 + addGroup(nextObjective);
224 + }
225 + } else {
226 + log.warn("Unsupported operation {}", nextObjective.op());
227 + }
228 +
229 + }
230 +
231 + private void removeGroup(NextObjective nextObjective) {
232 + final GroupKey key = new DefaultGroupKey(
233 + appKryo.serialize(nextObjective.id()));
234 + groupService.removeGroup(deviceId, key, appId);
235 + }
236 +
237 + private void addGroup(NextObjective nextObjective) {
210 switch (nextObjective.type()) { 238 switch (nextObjective.type()) {
211 - case SIMPLE: 239 + case SIMPLE:
212 - log.debug("processing SIMPLE next objective"); 240 + log.debug("processing SIMPLE next objective");
241 + Collection<TrafficTreatment> treatments = nextObjective.next();
242 + if (treatments.size() == 1) {
243 + TrafficTreatment treatment = treatments.iterator().next();
244 + GroupBucket bucket = DefaultGroupBucket
245 + .createIndirectGroupBucket(treatment);
246 + final GroupKey key = new DefaultGroupKey(
247 + appKryo.serialize(nextObjective
248 + .id()));
249 + GroupDescription groupDescription = new DefaultGroupDescription(
250 + deviceId,
251 + GroupDescription.Type.INDIRECT,
252 + new GroupBuckets(
253 + Collections.singletonList(bucket)),
254 + key,
255 + nextObjective.appId());
256 + groupService.addGroup(groupDescription);
257 + pendingGroups.put(key, nextObjective);
258 + }
259 + break;
260 + case HASHED:
261 + log.debug("processing HASHED next objective");
262 + List<GroupBucket> buckets = nextObjective
263 + .next()
264 + .stream()
265 + .map((treatment) -> DefaultGroupBucket
266 + .createSelectGroupBucket(treatment))
267 + .collect(Collectors.toList());
268 + if (!buckets.isEmpty()) {
269 + final GroupKey key = new DefaultGroupKey(
270 + appKryo.serialize(nextObjective
271 + .id()));
272 + GroupDescription groupDescription = new DefaultGroupDescription(
273 + deviceId,
274 + GroupDescription.Type.SELECT,
275 + new GroupBuckets(buckets),
276 + key,
277 + nextObjective.appId());
278 + groupService.addGroup(groupDescription);
279 + pendingGroups.put(key, nextObjective);
280 + }
281 + break;
282 + case BROADCAST:
283 + case FAILOVER:
284 + log.debug("BROADCAST and FAILOVER next objectives not supported");
285 + fail(nextObjective, ObjectiveError.UNSUPPORTED);
286 + log.warn("Unsupported next objective type {}", nextObjective.type());
287 + break;
288 + default:
289 + fail(nextObjective, ObjectiveError.UNKNOWN);
290 + log.warn("Unknown next objective type {}", nextObjective.type());
291 + }
292 + }
293 +
294 + private void addBucketToGroup(NextObjective nextObjective) {
295 + Collection<TrafficTreatment> treatments = nextObjective.next();
296 + TrafficTreatment treatment = treatments.iterator().next();
297 + final GroupKey key = new DefaultGroupKey(
298 + appKryo.serialize(nextObjective
299 + .id()));
300 + Group group = groupService.getGroup(deviceId, key);
301 + if (group == null) {
302 + log.warn("Group is not found in {} for {}", deviceId, key);
303 + return;
304 + }
305 + GroupBucket bucket;
306 + if (group.type() == GroupDescription.Type.INDIRECT) {
307 + bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
308 + } else if (group.type() == GroupDescription.Type.SELECT) {
309 + bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
310 + } else {
311 + log.warn("Unsupported Group type {}", group.type());
312 + return;
313 + }
314 + GroupBuckets bucketsToAdd = new GroupBuckets(Arrays.asList(bucket));
315 + groupService.addBucketsToGroup(deviceId, key, bucketsToAdd, key, appId);
316 + }
317 +
318 + private void removeBucketFromGroup(NextObjective nextObjective) {
319 + NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id());
320 + if (nextGroup != null) {
213 Collection<TrafficTreatment> treatments = nextObjective.next(); 321 Collection<TrafficTreatment> treatments = nextObjective.next();
214 - if (treatments.size() == 1) { 322 + TrafficTreatment treatment = treatments.iterator().next();
215 - TrafficTreatment treatment = treatments.iterator().next(); 323 + final GroupKey key = new DefaultGroupKey(
216 - GroupBucket bucket = DefaultGroupBucket 324 + appKryo.serialize(nextObjective
217 - .createIndirectGroupBucket(treatment); 325 + .id()));
218 - final GroupKey key = new DefaultGroupKey( 326 + Group group = groupService.getGroup(deviceId, key);
219 - appKryo.serialize(nextObjective 327 + if (group == null) {
220 - .id())); 328 + log.warn("Group is not found in {} for {}", deviceId, key);
221 - GroupDescription groupDescription = new DefaultGroupDescription( 329 + return;
222 - deviceId,
223 - GroupDescription.Type.INDIRECT,
224 - new GroupBuckets(
225 - Collections.singletonList(bucket)),
226 - key,
227 - nextObjective.appId());
228 - groupService.addGroup(groupDescription);
229 - pendingGroups.put(key, nextObjective);
230 } 330 }
231 - break; 331 + GroupBucket bucket;
232 - case HASHED: 332 + if (group.type() == GroupDescription.Type.INDIRECT) {
233 - log.debug("processing HASHED next objective"); 333 + bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
234 - List<GroupBucket> buckets = nextObjective 334 + } else if (group.type() == GroupDescription.Type.SELECT) {
235 - .next() 335 + bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
236 - .stream() 336 + } else {
237 - .map((treatment) -> DefaultGroupBucket 337 + log.warn("Unsupported Group type {}", group.type());
238 - .createSelectGroupBucket(treatment)) 338 + return;
239 - .collect(Collectors.toList());
240 - if (!buckets.isEmpty()) {
241 - final GroupKey key = new DefaultGroupKey(
242 - appKryo.serialize(nextObjective
243 - .id()));
244 - GroupDescription groupDescription = new DefaultGroupDescription(
245 - deviceId,
246 - GroupDescription.Type.SELECT,
247 - new GroupBuckets(buckets),
248 - key,
249 - nextObjective.appId());
250 - groupService.addGroup(groupDescription);
251 - pendingGroups.put(key, nextObjective);
252 } 339 }
253 - break; 340 + GroupBuckets removeBuckets = new GroupBuckets(Arrays.asList(bucket));
254 - case BROADCAST: 341 + groupService.removeBucketsFromGroup(deviceId, key, removeBuckets, key, appId);
255 - case FAILOVER:
256 - log.debug("BROADCAST and FAILOVER next objectives not supported");
257 - fail(nextObjective, ObjectiveError.UNSUPPORTED);
258 - log.warn("Unsupported next objective type {}", nextObjective.type());
259 - break;
260 - default:
261 - fail(nextObjective, ObjectiveError.UNKNOWN);
262 - log.warn("Unknown next objective type {}", nextObjective.type());
263 } 342 }
264 -
265 } 343 }
266 344
267 private Collection<FlowRule> processForward(ForwardingObjective fwd) { 345 private Collection<FlowRule> processForward(ForwardingObjective fwd) {
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 <behaviour api="org.onosproject.net.behaviour.Pipeliner" 23 <behaviour api="org.onosproject.net.behaviour.Pipeliner"
24 impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> 24 impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/>
25 </driver> 25 </driver>
26 - <driver name="spring-open-cpqd" manufacturer="Stanford University, Ericsson Research and CPqD Research" hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion="Apr 6 2015 16:10:53"> 26 + <driver name="spring-open-cpqd" manufacturer="Stanford University, Ericsson Research and CPqD Research" hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*">
27 <behaviour api="org.onosproject.net.behaviour.Pipeliner" 27 <behaviour api="org.onosproject.net.behaviour.Pipeliner"
28 impl="org.onosproject.driver.pipeline.SpringOpenTTP"/> 28 impl="org.onosproject.driver.pipeline.SpringOpenTTP"/>
29 </driver> 29 </driver>
......