2  * Copyright 2015 Open Networking Laboratory
 
   4  * Licensed under the Apache License, Version 2.0 (the "License");
 
   5  * you may not use this file except in compliance with the License.
 
   6  * You may obtain a copy of the License at
 
   8  *     http://www.apache.org/licenses/LICENSE-2.0
 
  10  * Unless required by applicable law or agreed to in writing, software
 
  11  * distributed under the License is distributed on an "AS IS" BASIS,
 
  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  13  * See the License for the specific language governing permissions and
 
  14  * limitations under the License.
 
  16 package org.onosproject.segmentrouting.grouphandler;
 
  18 import static com.google.common.base.Preconditions.checkArgument;
 
  19 import static org.slf4j.LoggerFactory.getLogger;
 
  21 import java.util.ArrayList;
 
  22 import java.util.Collections;
 
  23 import java.util.HashMap;
 
  24 import java.util.Iterator;
 
  25 import java.util.List;
 
  27 import org.onlab.packet.MplsLabel;
 
  28 import org.onosproject.core.ApplicationId;
 
  29 import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
 
  30 import org.onosproject.store.service.EventuallyConsistentMap;
 
  31 import org.onosproject.net.DeviceId;
 
  32 import org.onosproject.net.PortNumber;
 
  33 import org.onosproject.net.flow.DefaultTrafficTreatment;
 
  34 import org.onosproject.net.flow.TrafficTreatment;
 
  35 import org.onosproject.net.flowobjective.FlowObjectiveService;
 
  36 import org.onosproject.net.group.GroupBucket;
 
  37 import org.onosproject.net.link.LinkService;
 
  38 import org.slf4j.Logger;
 
  41  * A module to create group chains based on the specified device
 
  42  * ports and label stack to be applied on each port.
 
  44 public class PolicyGroupHandler extends DefaultGroupHandler {
 
  46     private final Logger log = getLogger(getClass());
 
  47     private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
 
  50      * Policy group handler constructor.
 
  52      * @param deviceId device identifier
 
  53      * @param appId application identifier
 
  54      * @param config interface to retrieve the device properties
 
  55      * @param linkService link service object
 
  56      * @param flowObjService flow objective service object
 
  57      * @param nsNextObjStore NeighborSet next objective store map
 
  58      * @param subnetNextObjStore subnet next objective store map
 
  60     public PolicyGroupHandler(DeviceId deviceId,
 
  62                               DeviceProperties config,
 
  63                               LinkService linkService,
 
  64                               FlowObjectiveService flowObjService,
 
  65                               EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
 
  66                                       Integer> nsNextObjStore,
 
  67                               EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
 
  68                                       Integer> subnetNextObjStore) {
 
  69         super(deviceId, appId, config, linkService, flowObjService,
 
  70               nsNextObjStore, subnetNextObjStore);
 
  73     public PolicyGroupIdentifier createPolicyGroupChain(String id,
 
  74                                                         List<PolicyGroupParams> params) {
 
  75         List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
 
  76         for (PolicyGroupParams param: params) {
 
  77             List<PortNumber> ports = param.getPorts();
 
  79                 log.warn("createPolicyGroupChain in sw {} with wrong "
 
  80                         + "input parameters", deviceId);
 
  84             int labelStackSize = (param.getLabelStack() != null) ?
 
  85                                       param.getLabelStack().size() : 0;
 
  87             if (labelStackSize > 1) {
 
  88                 for (PortNumber sp : ports) {
 
  89                     PolicyGroupIdentifier previousGroupkey = null;
 
  90                     DeviceId neighbor = portDeviceMap.get(sp);
 
  91                     for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
 
  92                         int label = param.getLabelStack().get(idx);
 
  93                         if (idx == (labelStackSize - 1)) {
 
  95                             GroupBucketIdentifier bucketId =
 
  96                                     new GroupBucketIdentifier(label,
 
  98                             bucketIds.add(bucketId);
 
  99                         } else if (idx == 0) {
 
 101                             List<GroupBucket> outBuckets = new ArrayList<>();
 
 102                             GroupBucketIdentifier bucketId =
 
 103                                     new GroupBucketIdentifier(label, sp);
 
 104                             PolicyGroupIdentifier key = new
 
 105                                     PolicyGroupIdentifier(id,
 
 106                                                           Collections.singletonList(param),
 
 107                                                           Collections.singletonList(bucketId));
 
 108                             TrafficTreatment.Builder tBuilder =
 
 109                                     DefaultTrafficTreatment.builder();
 
 110                             tBuilder.setOutput(sp)
 
 111                                     .setEthDst(deviceConfig.
 
 112                                                getDeviceMac(neighbor))
 
 113                                     .setEthSrc(nodeMacAddr)
 
 115                                     .setMpls(MplsLabel.mplsLabel(label));
 
 116                             /*outBuckets.add(DefaultGroupBucket.
 
 117                                            createSelectGroupBucket(tBuilder.build()));
 
 118                             GroupDescription desc = new
 
 119                                     DefaultGroupDescription(deviceId,
 
 120                                                             GroupDescription.Type.INDIRECT,
 
 121                                                             new GroupBuckets(outBuckets));
 
 123                             previousGroupkey = key;
 
 124                             //groupService.addGroup(desc);
 
 125                             //TODO: Use nextObjective APIs here
 
 127                             // Intermediate Groups
 
 128                             GroupBucketIdentifier bucketId =
 
 129                                     new GroupBucketIdentifier(label,
 
 131                             PolicyGroupIdentifier key = new
 
 132                                     PolicyGroupIdentifier(id,
 
 133                                                           Collections.singletonList(param),
 
 134                                                           Collections.singletonList(bucketId));
 
 135                             // Add to group dependency list
 
 136                             dependentGroups.put(previousGroupkey, key);
 
 137                             previousGroupkey = key;
 
 143                 if (labelStackSize == 1) {
 
 144                     label = param.getLabelStack().get(0);
 
 146                 for (PortNumber sp : ports) {
 
 147                     GroupBucketIdentifier bucketId =
 
 148                             new GroupBucketIdentifier(label, sp);
 
 149                     bucketIds.add(bucketId);
 
 153         PolicyGroupIdentifier innermostGroupkey = null;
 
 154         if (!bucketIds.isEmpty()) {
 
 155             innermostGroupkey = new
 
 156                     PolicyGroupIdentifier(id,
 
 159             // Add to group dependency list
 
 160             boolean fullyResolved = true;
 
 161             for (GroupBucketIdentifier bucketId:bucketIds) {
 
 162                 if (bucketId.type() == BucketOutputType.GROUP) {
 
 163                     dependentGroups.put(bucketId.outGroup(),
 
 165                     fullyResolved = false;
 
 170                 List<GroupBucket> outBuckets = new ArrayList<>();
 
 171                 for (GroupBucketIdentifier bucketId:bucketIds) {
 
 172                     DeviceId neighbor = portDeviceMap.
 
 173                             get(bucketId.outPort());
 
 174                     TrafficTreatment.Builder tBuilder =
 
 175                             DefaultTrafficTreatment.builder();
 
 176                     tBuilder.setOutput(bucketId.outPort())
 
 177                             .setEthDst(deviceConfig.
 
 178                                        getDeviceMac(neighbor))
 
 179                             .setEthSrc(nodeMacAddr);
 
 180                     if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
 
 182                             .setMpls(MplsLabel.mplsLabel(bucketId.label()));
 
 185                     /*outBuckets.add(DefaultGroupBucket.
 
 186                                    createSelectGroupBucket(tBuilder.build()));*/
 
 188                 /*GroupDescription desc = new
 
 189                         DefaultGroupDescription(deviceId,
 
 190                                                 GroupDescription.Type.SELECT,
 
 191                                                 new GroupBuckets(outBuckets));
 
 192                 groupService.addGroup(desc);*/
 
 193                 //TODO: Use nextObjective APIs here
 
 196         return innermostGroupkey;
 
 199     //TODO: Use nextObjective APIs to handle the group chains
 
 201     protected void handleGroupEvent(GroupEvent event) {
 
 202         if (event.type() == GroupEvent.Type.GROUP_ADDED) {
 
 203             if (dependentGroups.get(event.subject().appCookie()) != null) {
 
 204                 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
 
 205                 dependentGroups.remove(event.subject().appCookie());
 
 206                 boolean fullyResolved = true;
 
 207                 for (GroupBucketIdentifier bucketId:
 
 208                             dependentGroupKey.bucketIds()) {
 
 209                     if (bucketId.type() != BucketOutputType.GROUP) {
 
 212                     if (dependentGroups.containsKey(bucketId.outGroup())) {
 
 213                         fullyResolved = false;
 
 219                     List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
 
 220                     for (GroupBucketIdentifier bucketId:
 
 221                                 dependentGroupKey.bucketIds()) {
 
 222                         TrafficTreatment.Builder tBuilder =
 
 223                                 DefaultTrafficTreatment.builder();
 
 224                         if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
 
 227                                              mplsLabel(bucketId.label()));
 
 230                         if (bucketId.type() == BucketOutputType.PORT) {
 
 231                             DeviceId neighbor = portDeviceMap.
 
 232                                         get(bucketId.outPort());
 
 233                             tBuilder.setOutput(bucketId.outPort())
 
 234                                     .setEthDst(deviceConfig.
 
 235                                                getDeviceMac(neighbor))
 
 236                                      .setEthSrc(nodeMacAddr);
 
 240                                              getGroupKey(bucketId.
 
 241                                                        outGroup())) == null) {
 
 242                                 throw new IllegalStateException();
 
 244                             GroupId indirectGroupId = groupService.
 
 246                                              getGroupKey(bucketId.
 
 248                             tBuilder.group(indirectGroupId);
 
 250                         outBuckets.add(DefaultGroupBucket.
 
 251                                        createSelectGroupBucket(tBuilder.build()));
 
 253                     GroupDescription desc = new
 
 254                             DefaultGroupDescription(deviceId,
 
 255                                                     GroupDescription.Type.SELECT,
 
 256                                                     new GroupBuckets(outBuckets));
 
 257                     groupService.addGroup(desc);
 
 263     public PolicyGroupIdentifier generatePolicyGroupKey(String id,
 
 264                                    List<PolicyGroupParams> params) {
 
 265         List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
 
 266         for (PolicyGroupParams param: params) {
 
 267             List<PortNumber> ports = param.getPorts();
 
 269                 log.warn("generateGroupKey in sw {} with wrong "
 
 270                         + "input parameters", deviceId);
 
 274             int labelStackSize = (param.getLabelStack() != null)
 
 275                     ? param.getLabelStack().size() : 0;
 
 277             if (labelStackSize > 1) {
 
 278                 for (PortNumber sp : ports) {
 
 279                     PolicyGroupIdentifier previousGroupkey = null;
 
 280                     for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
 
 281                         int label = param.getLabelStack().get(idx);
 
 282                         if (idx == (labelStackSize - 1)) {
 
 284                             GroupBucketIdentifier bucketId =
 
 285                                     new GroupBucketIdentifier(label,
 
 287                             bucketIds.add(bucketId);
 
 288                         } else if (idx == 0) {
 
 290                             GroupBucketIdentifier bucketId =
 
 291                                     new GroupBucketIdentifier(label, sp);
 
 292                             PolicyGroupIdentifier key = new
 
 293                                     PolicyGroupIdentifier(id,
 
 294                                                           Collections.singletonList(param),
 
 295                                                           Collections.singletonList(bucketId));
 
 296                             previousGroupkey = key;
 
 298                             // Intermediate Groups
 
 299                             GroupBucketIdentifier bucketId =
 
 300                                     new GroupBucketIdentifier(label,
 
 302                             PolicyGroupIdentifier key = new
 
 303                                     PolicyGroupIdentifier(id,
 
 304                                                           Collections.singletonList(param),
 
 305                                                           Collections.singletonList(bucketId));
 
 306                             previousGroupkey = key;
 
 312                 if (labelStackSize == 1) {
 
 313                     label = param.getLabelStack().get(0);
 
 315                 for (PortNumber sp : ports) {
 
 316                     GroupBucketIdentifier bucketId =
 
 317                             new GroupBucketIdentifier(label, sp);
 
 318                     bucketIds.add(bucketId);
 
 322         PolicyGroupIdentifier innermostGroupkey = null;
 
 323         if (!bucketIds.isEmpty()) {
 
 324             innermostGroupkey = new
 
 325                     PolicyGroupIdentifier(id,
 
 329         return innermostGroupkey;
 
 332     public void removeGroupChain(PolicyGroupIdentifier key) {
 
 333         checkArgument(key != null);
 
 334         List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
 
 335         groupsToBeDeleted.add(key);
 
 337         Iterator<PolicyGroupIdentifier> it =
 
 338                 groupsToBeDeleted.iterator();
 
 340         while (it.hasNext()) {
 
 341             PolicyGroupIdentifier innerMostGroupKey = it.next();
 
 342             for (GroupBucketIdentifier bucketId:
 
 343                         innerMostGroupKey.bucketIds()) {
 
 344                 if (bucketId.type() != BucketOutputType.GROUP) {
 
 345                     groupsToBeDeleted.add(bucketId.outGroup());
 
 348             /*groupService.removeGroup(deviceId,
 
 349                                      getGroupKey(innerMostGroupKey),
 
 351             //TODO: Use nextObjective APIs here