blob: 0cd5743786b8caeefb5397f193991f8ec1f6d8bc [file] [log] [blame]
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.segmentrouting.grouphandler;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.onlab.packet.MplsLabel;
import org.onosproject.core.ApplicationId;
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.group.DefaultGroupBucket;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupService;
import org.onosproject.net.link.LinkService;
/**
* Default ECMP group handler creation module for an edge device.
* This component creates a set of ECMP groups for every neighbor
* that this device is connected to.
* For example, consider a network of 4 devices: D0 (Segment ID: 100),
* D1 (Segment ID: 101), D2 (Segment ID: 102) and D3 (Segment ID: 103),
* where D0 and D3 are edge devices and D1 and D2 are transit devices.
* Assume device D0 is connected to 2 neighbors (D1 and D2 ).
* The following groups will be created in D0:
* 1) all ports to D1 + with no label push,
* 2) all ports to D1 + with label 102 pushed,
* 3) all ports to D1 + with label 103 pushed,
* 4) all ports to D2 + with no label push,
* 5) all ports to D2 + with label 101 pushed,
* 6) all ports to D2 + with label 103 pushed,
* 7) all ports to D1 and D2 + with label 103 pushed
*/
public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
protected DefaultEdgeGroupHandler(DeviceId deviceId,
ApplicationId appId,
DeviceProperties config,
LinkService linkService,
GroupService groupService) {
super(deviceId, appId, config, linkService, groupService);
}
@Override
public void createGroups() {
log.debug("Creating default groups "
+ "for edge device {}", deviceId);
Set<DeviceId> neighbors = devicePortMap.keySet();
if (neighbors == null || neighbors.isEmpty()) {
return;
}
// Create all possible Neighbor sets from this router
Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(neighbors);
log.trace("createGroupsAtEdgeRouter: The size of neighbor powerset "
+ "for sw {} is {}", deviceId, powerSet.size());
Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
for (Set<DeviceId> combo : powerSet) {
if (combo.isEmpty()) {
continue;
}
List<Integer> groupSegmentIds =
getSegmentIdsTobePairedWithNeighborSet(combo);
for (Integer sId : groupSegmentIds) {
NeighborSet ns = new NeighborSet(combo, sId);
log.trace("createGroupsAtEdgeRouter: sw {} "
+ "combo {} sId {} ns {}",
deviceId, combo, sId, ns);
nsSet.add(ns);
}
}
log.trace("createGroupsAtEdgeRouter: The neighborset "
+ "with label for sw {} is {}",
deviceId, nsSet);
createGroupsFromNeighborsets(nsSet);
}
@Override
protected void newNeighbor(Link newNeighborLink) {
log.debug("New Neighbor: Updating groups "
+ "for edge device {}", deviceId);
// Recompute neighbor power set
addNeighborAtPort(newNeighborLink.dst().deviceId(),
newNeighborLink.src().port());
// Compute new neighbor sets due to the addition of new neighbor
Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
newNeighborLink.dst().deviceId(),
devicePortMap.keySet());
createGroupsFromNeighborsets(nsSet);
}
@Override
protected void newPortToExistingNeighbor(Link newNeighborLink) {
log.debug("New port to existing neighbor: Updating "
+ "groups for edge device {}", deviceId);
addNeighborAtPort(newNeighborLink.dst().deviceId(),
newNeighborLink.src().port());
Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
newNeighborLink.dst().deviceId(),
devicePortMap.keySet());
for (NeighborSet ns : nsSet) {
// Create the new bucket to be updated
TrafficTreatment.Builder tBuilder =
DefaultTrafficTreatment.builder();
tBuilder.setOutput(newNeighborLink.src().port())
.setEthDst(deviceConfig.getDeviceMac(
newNeighborLink.dst().deviceId()))
.setEthSrc(nodeMacAddr);
if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
tBuilder.pushMpls()
.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);
}
}
@Override
protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent(
DeviceId impactedNeighbor,
Set<DeviceId> updatedNeighbors) {
Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);
Set<DeviceId> tmp = new HashSet<DeviceId>();
tmp.addAll(updatedNeighbors);
tmp.remove(impactedNeighbor);
Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);
// Compute the impacted neighbor sets
powerSet.removeAll(tmpPowerSet);
Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
for (Set<DeviceId> combo : powerSet) {
if (combo.isEmpty()) {
continue;
}
List<Integer> groupSegmentIds =
getSegmentIdsTobePairedWithNeighborSet(combo);
for (Integer sId : groupSegmentIds) {
NeighborSet ns = new NeighborSet(combo, sId);
log.trace("computeImpactedNeighborsetForPortEvent: sw {} "
+ "combo {} sId {} ns {}",
deviceId, combo, sId, ns);
nsSet.add(ns);
}
}
log.trace("computeImpactedNeighborsetForPortEvent: The neighborset "
+ "with label for sw {} is {}",
deviceId, nsSet);
return nsSet;
}
}