blob: 124ffa723d98d028c911825e20ea85ad8140d1ac [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.HashSet;
import java.util.List;
import java.util.Set;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.link.LinkService;
import org.onosproject.segmentrouting.SegmentRoutingManager;
import org.onosproject.segmentrouting.config.DeviceProperties;
/**
* 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, // direct attach case, seen
* 2) all ports to D1 + with label 102 pushed, // this is not needed
* 3) all ports to D1 + with label 103 pushed, // maybe needed, sometimes seen
* 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 // ecmp case
* 8) what about ecmp no label case
*/
public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
protected DefaultEdgeGroupHandler(DeviceId deviceId,
ApplicationId appId,
DeviceProperties config,
LinkService linkService,
FlowObjectiveService flowObjService,
SegmentRoutingManager srManager) {
super(deviceId, appId, config, linkService, flowObjService, srManager);
}
@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<>();
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()));
}
Integer nextId = deviceNextObjectiveIds.get(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);
}
}*/
}
@Override
protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent(
DeviceId impactedNeighbor,
Set<DeviceId> updatedNeighbors) {
Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);
Set<DeviceId> tmp = new HashSet<>();
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<>();
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;
}
}