| /* |
| * 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.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) |
| .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, ns, updatedBuckets, 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; |
| } |
| |
| } |