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