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.MacAddress;
28 import org.onlab.packet.MplsLabel;
29 import org.onosproject.core.ApplicationId;
30 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
31 import org.onosproject.segmentrouting.config.DeviceProperties;
32 import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
33 import org.onosproject.store.service.EventuallyConsistentMap;
34 import org.onosproject.net.DeviceId;
35 import org.onosproject.net.PortNumber;
36 import org.onosproject.net.flow.DefaultTrafficTreatment;
37 import org.onosproject.net.flow.TrafficTreatment;
38 import org.onosproject.net.flowobjective.FlowObjectiveService;
39 import org.onosproject.net.group.GroupBucket;
40 import org.onosproject.net.link.LinkService;
41 import org.slf4j.Logger;
44 * A module to create group chains based on the specified device
45 * ports and label stack to be applied on each port.
47 public class PolicyGroupHandler extends DefaultGroupHandler {
49 private final Logger log = getLogger(getClass());
50 private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
53 * Policy group handler constructor.
55 * @param deviceId device identifier
56 * @param appId application identifier
57 * @param config interface to retrieve the device properties
58 * @param linkService link service object
59 * @param flowObjService flow objective service object
60 * @param nsNextObjStore NeighborSet next objective store map
61 * @param subnetNextObjStore subnet next objective store map
63 public PolicyGroupHandler(DeviceId deviceId,
65 DeviceProperties config,
66 LinkService linkService,
67 FlowObjectiveService flowObjService,
68 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
69 Integer> nsNextObjStore,
70 EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
71 Integer> subnetNextObjStore) {
72 super(deviceId, appId, config, linkService, flowObjService,
73 nsNextObjStore, subnetNextObjStore);
76 public PolicyGroupIdentifier createPolicyGroupChain(String id,
77 List<PolicyGroupParams> params) {
78 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
79 for (PolicyGroupParams param: params) {
80 List<PortNumber> ports = param.getPorts();
82 log.warn("createPolicyGroupChain in sw {} with wrong "
83 + "input parameters", deviceId);
87 int labelStackSize = (param.getLabelStack() != null) ?
88 param.getLabelStack().size() : 0;
90 if (labelStackSize > 1) {
91 for (PortNumber sp : ports) {
92 PolicyGroupIdentifier previousGroupkey = null;
93 DeviceId neighbor = portDeviceMap.get(sp);
94 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
95 int label = param.getLabelStack().get(idx);
96 if (idx == (labelStackSize - 1)) {
98 GroupBucketIdentifier bucketId =
99 new GroupBucketIdentifier(label,
101 bucketIds.add(bucketId);
102 } else if (idx == 0) {
104 List<GroupBucket> outBuckets = new ArrayList<>();
105 GroupBucketIdentifier bucketId =
106 new GroupBucketIdentifier(label, sp);
107 PolicyGroupIdentifier key = new
108 PolicyGroupIdentifier(id,
109 Collections.singletonList(param),
110 Collections.singletonList(bucketId));
111 MacAddress neighborEthDst;
113 neighborEthDst = deviceConfig.getDeviceMac(neighbor);
114 } catch (DeviceConfigNotFoundException e) {
115 log.warn(e.getMessage()
116 + " Skipping createPolicyGroupChain for this label.");
120 TrafficTreatment.Builder tBuilder =
121 DefaultTrafficTreatment.builder();
122 tBuilder.setOutput(sp)
123 .setEthDst(neighborEthDst)
124 .setEthSrc(nodeMacAddr)
126 .setMpls(MplsLabel.mplsLabel(label));
127 /*outBuckets.add(DefaultGroupBucket.
128 createSelectGroupBucket(tBuilder.build()));
129 GroupDescription desc = new
130 DefaultGroupDescription(deviceId,
131 GroupDescription.Type.INDIRECT,
132 new GroupBuckets(outBuckets));
134 previousGroupkey = key;
135 //groupService.addGroup(desc);
136 //TODO: Use nextObjective APIs here
138 // Intermediate Groups
139 GroupBucketIdentifier bucketId =
140 new GroupBucketIdentifier(label,
142 PolicyGroupIdentifier key = new
143 PolicyGroupIdentifier(id,
144 Collections.singletonList(param),
145 Collections.singletonList(bucketId));
146 // Add to group dependency list
147 dependentGroups.put(previousGroupkey, key);
148 previousGroupkey = key;
154 if (labelStackSize == 1) {
155 label = param.getLabelStack().get(0);
157 for (PortNumber sp : ports) {
158 GroupBucketIdentifier bucketId =
159 new GroupBucketIdentifier(label, sp);
160 bucketIds.add(bucketId);
164 PolicyGroupIdentifier innermostGroupkey = null;
165 if (!bucketIds.isEmpty()) {
166 innermostGroupkey = new
167 PolicyGroupIdentifier(id,
170 // Add to group dependency list
171 boolean fullyResolved = true;
172 for (GroupBucketIdentifier bucketId:bucketIds) {
173 if (bucketId.type() == BucketOutputType.GROUP) {
174 dependentGroups.put(bucketId.outGroup(),
176 fullyResolved = false;
181 List<GroupBucket> outBuckets = new ArrayList<>();
182 for (GroupBucketIdentifier bucketId : bucketIds) {
183 DeviceId neighbor = portDeviceMap.
184 get(bucketId.outPort());
186 MacAddress neighborEthDst;
188 neighborEthDst = deviceConfig.getDeviceMac(neighbor);
189 } catch (DeviceConfigNotFoundException e) {
190 log.warn(e.getMessage()
191 + " Skipping createPolicyGroupChain for this bucketId.");
195 TrafficTreatment.Builder tBuilder =
196 DefaultTrafficTreatment.builder();
197 tBuilder.setOutput(bucketId.outPort())
198 .setEthDst(neighborEthDst)
199 .setEthSrc(nodeMacAddr);
200 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
202 .setMpls(MplsLabel.mplsLabel(bucketId.label()));
205 /*outBuckets.add(DefaultGroupBucket.
206 createSelectGroupBucket(tBuilder.build()));*/
208 /*GroupDescription desc = new
209 DefaultGroupDescription(deviceId,
210 GroupDescription.Type.SELECT,
211 new GroupBuckets(outBuckets));
212 groupService.addGroup(desc);*/
213 //TODO: Use nextObjective APIs here
216 return innermostGroupkey;
219 //TODO: Use nextObjective APIs to handle the group chains
221 protected void handleGroupEvent(GroupEvent event) {
222 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
223 if (dependentGroups.get(event.subject().appCookie()) != null) {
224 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
225 dependentGroups.remove(event.subject().appCookie());
226 boolean fullyResolved = true;
227 for (GroupBucketIdentifier bucketId:
228 dependentGroupKey.bucketIds()) {
229 if (bucketId.type() != BucketOutputType.GROUP) {
232 if (dependentGroups.containsKey(bucketId.outGroup())) {
233 fullyResolved = false;
239 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
240 for (GroupBucketIdentifier bucketId:
241 dependentGroupKey.bucketIds()) {
242 TrafficTreatment.Builder tBuilder =
243 DefaultTrafficTreatment.builder();
244 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
247 mplsLabel(bucketId.label()));
250 if (bucketId.type() == BucketOutputType.PORT) {
251 DeviceId neighbor = portDeviceMap.
252 get(bucketId.outPort());
253 tBuilder.setOutput(bucketId.outPort())
254 .setEthDst(deviceConfig.
255 getDeviceMac(neighbor))
256 .setEthSrc(nodeMacAddr);
260 getGroupKey(bucketId.
261 outGroup())) == null) {
262 throw new IllegalStateException();
264 GroupId indirectGroupId = groupService.
266 getGroupKey(bucketId.
268 tBuilder.group(indirectGroupId);
270 outBuckets.add(DefaultGroupBucket.
271 createSelectGroupBucket(tBuilder.build()));
273 GroupDescription desc = new
274 DefaultGroupDescription(deviceId,
275 GroupDescription.Type.SELECT,
276 new GroupBuckets(outBuckets));
277 groupService.addGroup(desc);
283 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
284 List<PolicyGroupParams> params) {
285 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
286 for (PolicyGroupParams param: params) {
287 List<PortNumber> ports = param.getPorts();
289 log.warn("generateGroupKey in sw {} with wrong "
290 + "input parameters", deviceId);
294 int labelStackSize = (param.getLabelStack() != null)
295 ? param.getLabelStack().size() : 0;
297 if (labelStackSize > 1) {
298 for (PortNumber sp : ports) {
299 PolicyGroupIdentifier previousGroupkey = null;
300 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
301 int label = param.getLabelStack().get(idx);
302 if (idx == (labelStackSize - 1)) {
304 GroupBucketIdentifier bucketId =
305 new GroupBucketIdentifier(label,
307 bucketIds.add(bucketId);
308 } else if (idx == 0) {
310 GroupBucketIdentifier bucketId =
311 new GroupBucketIdentifier(label, sp);
312 PolicyGroupIdentifier key = new
313 PolicyGroupIdentifier(id,
314 Collections.singletonList(param),
315 Collections.singletonList(bucketId));
316 previousGroupkey = key;
318 // Intermediate Groups
319 GroupBucketIdentifier bucketId =
320 new GroupBucketIdentifier(label,
322 PolicyGroupIdentifier key = new
323 PolicyGroupIdentifier(id,
324 Collections.singletonList(param),
325 Collections.singletonList(bucketId));
326 previousGroupkey = key;
332 if (labelStackSize == 1) {
333 label = param.getLabelStack().get(0);
335 for (PortNumber sp : ports) {
336 GroupBucketIdentifier bucketId =
337 new GroupBucketIdentifier(label, sp);
338 bucketIds.add(bucketId);
342 PolicyGroupIdentifier innermostGroupkey = null;
343 if (!bucketIds.isEmpty()) {
344 innermostGroupkey = new
345 PolicyGroupIdentifier(id,
349 return innermostGroupkey;
352 public void removeGroupChain(PolicyGroupIdentifier key) {
353 checkArgument(key != null);
354 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
355 groupsToBeDeleted.add(key);
357 Iterator<PolicyGroupIdentifier> it =
358 groupsToBeDeleted.iterator();
360 while (it.hasNext()) {
361 PolicyGroupIdentifier innerMostGroupKey = it.next();
362 for (GroupBucketIdentifier bucketId:
363 innerMostGroupKey.bucketIds()) {
364 if (bucketId.type() != BucketOutputType.GROUP) {
365 groupsToBeDeleted.add(bucketId.outGroup());
368 /*groupService.removeGroup(deviceId,
369 getGroupKey(innerMostGroupKey),
371 //TODO: Use nextObjective APIs here