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 {
private boolean repopulateRoutingRulesForRoutes(Set<ArrayList<DeviceId>> routes) {
rulePopulator.resetCounter();
for (ArrayList<DeviceId> link: routes) {
// When only the source device is defined, reinstall routes to all other devices
if (link.size() == 1) {
ECMPShortestPathGraph ecmpSpg = new ECMPShortestPathGraph(link.get(0), srManager);
if (populateEcmpRoutingRules(link.get(0), ecmpSpg)) {
......
......@@ -173,6 +173,11 @@ public class RoutingRulePopulator {
TrafficTreatment treatment = tbuilder.build();
TrafficSelector selector = sbuilder.build();
if (srManager.getNextObjectiveId(deviceId, ns) <= 0) {
log.warn("No next objective in {} for ns: {}", deviceId, ns);
return false;
}
ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
.builder()
.fromApp(srManager.appId)
......@@ -183,7 +188,7 @@ public class RoutingRulePopulator {
.withPriority(100)
.withFlag(ForwardingObjective.Flag.SPECIFIC);
log.debug("Installing IPv4 forwarding objective "
+ "for router IP/subnet {} in switch {}",
+ "for router IP/subnet {} in switch {}",
ipPrefix,
deviceId);
srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add());
......
......@@ -304,6 +304,10 @@ public class SegmentRoutingManager {
private void processLinkRemoved(Link link) {
log.debug("A link {} was removed", link.toString());
DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
if (groupHandler != null) {
groupHandler.portDown(link.src().port());
}
defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
}
......
......@@ -25,7 +25,9 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.link.LinkService;
/**
......@@ -126,18 +128,18 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
.setMpls(MplsLabel.
mplsLabel(ns.getEdgeLabel()));
}
/*GroupBucket updatedBucket = DefaultGroupBucket.
createSelectGroupBucket(tBuilder.build());
GroupBuckets updatedBuckets = new GroupBuckets(
Arrays.asList(updatedBucket));
log.debug("newPortToExistingNeighborAtEdgeRouter: "
+ "groupService.addBucketsToGroup for neighborset{}", ns);
groupService.addBucketsToGroup(deviceId,
getGroupKey(ns),
updatedBuckets,
getGroupKey(ns),
appId);*/
//TODO: Use nextObjective APIs to update the next objective
Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
if (nextId != null) {
NextObjective.Builder nextObjBuilder = DefaultNextObjective
.builder().withId(nextId)
.withType(NextObjective.Type.HASHED).fromApp(appId);
nextObjBuilder.addTreatment(tBuilder.build());
NextObjective nextObjective = nextObjBuilder.add();
flowObjectiveService.next(deviceId, nextObjective);
}
}
}
......
......@@ -186,17 +186,19 @@ public class DefaultGroupHandler {
tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
.getEdgeLabel()));
}
/*
* GroupBucket removeBucket = DefaultGroupBucket.
* createSelectGroupBucket(tBuilder.build()); GroupBuckets
* removeBuckets = new GroupBuckets( Arrays.asList(removeBucket));
* log.debug("portDown in device{}: " +
* "groupService.removeBucketsFromGroup " + "for neighborset{}",
* deviceId, ns); groupService.removeBucketsFromGroup(deviceId,
* getGroupKey(ns), removeBuckets, getGroupKey(ns), appId);
*/
//TODO: Use next objective API to update the previously created
//next objectives.
Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
if (nextId != null) {
NextObjective.Builder nextObjBuilder = DefaultNextObjective
.builder().withType(NextObjective.Type.SIMPLE).withId(nextId).fromApp(appId);
nextObjBuilder.addTreatment(tBuilder.build());
NextObjective nextObjective = nextObjBuilder.remove();
flowObjectiveService.next(deviceId, nextObjective);
}
}
devicePortMap.get(portDeviceMap.get(port)).remove(port);
......@@ -333,6 +335,11 @@ public class DefaultGroupHandler {
.builder().withId(nextId)
.withType(NextObjective.Type.HASHED).fromApp(appId);
for (DeviceId d : ns.getDeviceIds()) {
if (devicePortMap.get(d) == null) {
log.warn("Device {} is not in the port map yet", d);
return;
}
for (PortNumber sp : devicePortMap.get(d)) {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
.builder();
......@@ -341,7 +348,7 @@ public class DefaultGroupHandler {
.setEthSrc(nodeMacAddr);
if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns
.getEdgeLabel()));
.getEdgeLabel()));
}
nextObjBuilder.addTreatment(tBuilder.build());
}
......
......@@ -24,7 +24,9 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.link.LinkService;
/**
......@@ -114,18 +116,19 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler {
.setMpls(MplsLabel.
mplsLabel(ns.getEdgeLabel()));
}
/*GroupBucket updatedBucket = DefaultGroupBucket.
createSelectGroupBucket(tBuilder.build());
GroupBuckets updatedBuckets = new GroupBuckets(
Arrays.asList(updatedBucket));
log.debug("newPortToExistingNeighborAtEdgeRouter: "
+ "groupService.addBucketsToGroup for neighborset{}", ns);
groupService.addBucketsToGroup(deviceId,
getGroupKey(ns),
updatedBuckets,
getGroupKey(ns),
appId);*/
//TODO: Use nextObjective APIs to update the next objective
Integer nextId = deviceNextObjectiveIds.get(getGroupKey(ns));
if (nextId != null) {
NextObjective.Builder nextObjBuilder = DefaultNextObjective
.builder().withId(nextId)
.withType(NextObjective.Type.HASHED).fromApp(appId);
nextObjBuilder.addTreatment(tBuilder.build());
NextObjective nextObjective = nextObjBuilder.add();
flowObjectiveService.next(deviceId, nextObjective);
}
}
}
......
......@@ -73,6 +73,7 @@ import org.onosproject.net.group.GroupService;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
......@@ -207,61 +208,138 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
@Override
public void next(NextObjective nextObjective) {
if (nextObjective.op() == Objective.Operation.REMOVE) {
if (nextObjective.next() == null) {
removeGroup(nextObjective);
} else {
removeBucketFromGroup(nextObjective);
}
} else if (nextObjective.op() == Objective.Operation.ADD) {
NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id());
if (nextGroup != null) {
addBucketToGroup(nextObjective);
} else {
addGroup(nextObjective);
}
} else {
log.warn("Unsupported operation {}", nextObjective.op());
}
}
private void removeGroup(NextObjective nextObjective) {
final GroupKey key = new DefaultGroupKey(
appKryo.serialize(nextObjective.id()));
groupService.removeGroup(deviceId, key, appId);
}
private void addGroup(NextObjective nextObjective) {
switch (nextObjective.type()) {
case SIMPLE:
log.debug("processing SIMPLE next objective");
case SIMPLE:
log.debug("processing SIMPLE next objective");
Collection<TrafficTreatment> treatments = nextObjective.next();
if (treatments.size() == 1) {
TrafficTreatment treatment = treatments.iterator().next();
GroupBucket bucket = DefaultGroupBucket
.createIndirectGroupBucket(treatment);
final GroupKey key = new DefaultGroupKey(
appKryo.serialize(nextObjective
.id()));
GroupDescription groupDescription = new DefaultGroupDescription(
deviceId,
GroupDescription.Type.INDIRECT,
new GroupBuckets(
Collections.singletonList(bucket)),
key,
nextObjective.appId());
groupService.addGroup(groupDescription);
pendingGroups.put(key, nextObjective);
}
break;
case HASHED:
log.debug("processing HASHED next objective");
List<GroupBucket> buckets = nextObjective
.next()
.stream()
.map((treatment) -> DefaultGroupBucket
.createSelectGroupBucket(treatment))
.collect(Collectors.toList());
if (!buckets.isEmpty()) {
final GroupKey key = new DefaultGroupKey(
appKryo.serialize(nextObjective
.id()));
GroupDescription groupDescription = new DefaultGroupDescription(
deviceId,
GroupDescription.Type.SELECT,
new GroupBuckets(buckets),
key,
nextObjective.appId());
groupService.addGroup(groupDescription);
pendingGroups.put(key, nextObjective);
}
break;
case BROADCAST:
case FAILOVER:
log.debug("BROADCAST and FAILOVER next objectives not supported");
fail(nextObjective, ObjectiveError.UNSUPPORTED);
log.warn("Unsupported next objective type {}", nextObjective.type());
break;
default:
fail(nextObjective, ObjectiveError.UNKNOWN);
log.warn("Unknown next objective type {}", nextObjective.type());
}
}
private void addBucketToGroup(NextObjective nextObjective) {
Collection<TrafficTreatment> treatments = nextObjective.next();
TrafficTreatment treatment = treatments.iterator().next();
final GroupKey key = new DefaultGroupKey(
appKryo.serialize(nextObjective
.id()));
Group group = groupService.getGroup(deviceId, key);
if (group == null) {
log.warn("Group is not found in {} for {}", deviceId, key);
return;
}
GroupBucket bucket;
if (group.type() == GroupDescription.Type.INDIRECT) {
bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
} else if (group.type() == GroupDescription.Type.SELECT) {
bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
} else {
log.warn("Unsupported Group type {}", group.type());
return;
}
GroupBuckets bucketsToAdd = new GroupBuckets(Arrays.asList(bucket));
groupService.addBucketsToGroup(deviceId, key, bucketsToAdd, key, appId);
}
private void removeBucketFromGroup(NextObjective nextObjective) {
NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id());
if (nextGroup != null) {
Collection<TrafficTreatment> treatments = nextObjective.next();
if (treatments.size() == 1) {
TrafficTreatment treatment = treatments.iterator().next();
GroupBucket bucket = DefaultGroupBucket
.createIndirectGroupBucket(treatment);
final GroupKey key = new DefaultGroupKey(
appKryo.serialize(nextObjective
.id()));
GroupDescription groupDescription = new DefaultGroupDescription(
deviceId,
GroupDescription.Type.INDIRECT,
new GroupBuckets(
Collections.singletonList(bucket)),
key,
nextObjective.appId());
groupService.addGroup(groupDescription);
pendingGroups.put(key, nextObjective);
TrafficTreatment treatment = treatments.iterator().next();
final GroupKey key = new DefaultGroupKey(
appKryo.serialize(nextObjective
.id()));
Group group = groupService.getGroup(deviceId, key);
if (group == null) {
log.warn("Group is not found in {} for {}", deviceId, key);
return;
}
break;
case HASHED:
log.debug("processing HASHED next objective");
List<GroupBucket> buckets = nextObjective
.next()
.stream()
.map((treatment) -> DefaultGroupBucket
.createSelectGroupBucket(treatment))
.collect(Collectors.toList());
if (!buckets.isEmpty()) {
final GroupKey key = new DefaultGroupKey(
appKryo.serialize(nextObjective
.id()));
GroupDescription groupDescription = new DefaultGroupDescription(
deviceId,
GroupDescription.Type.SELECT,
new GroupBuckets(buckets),
key,
nextObjective.appId());
groupService.addGroup(groupDescription);
pendingGroups.put(key, nextObjective);
GroupBucket bucket;
if (group.type() == GroupDescription.Type.INDIRECT) {
bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
} else if (group.type() == GroupDescription.Type.SELECT) {
bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
} else {
log.warn("Unsupported Group type {}", group.type());
return;
}
break;
case BROADCAST:
case FAILOVER:
log.debug("BROADCAST and FAILOVER next objectives not supported");
fail(nextObjective, ObjectiveError.UNSUPPORTED);
log.warn("Unsupported next objective type {}", nextObjective.type());
break;
default:
fail(nextObjective, ObjectiveError.UNKNOWN);
log.warn("Unknown next objective type {}", nextObjective.type());
GroupBuckets removeBuckets = new GroupBuckets(Arrays.asList(bucket));
groupService.removeBucketsFromGroup(deviceId, key, removeBuckets, key, appId);
}
}
private Collection<FlowRule> processForward(ForwardingObjective fwd) {
......
......@@ -23,7 +23,7 @@
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/>
</driver>
<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">
<driver name="spring-open-cpqd" manufacturer="Stanford University, Ericsson Research and CPqD Research" hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.SpringOpenTTP"/>
</driver>
......