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 next objective store map
59 public PolicyGroupHandler(DeviceId deviceId,
61 DeviceProperties config,
62 LinkService linkService,
63 FlowObjectiveService flowObjService,
64 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
65 Integer> nsNextObjStore) {
66 super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore);
69 public PolicyGroupIdentifier createPolicyGroupChain(String id,
70 List<PolicyGroupParams> params) {
71 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
72 for (PolicyGroupParams param: params) {
73 List<PortNumber> ports = param.getPorts();
75 log.warn("createPolicyGroupChain in sw {} with wrong "
76 + "input parameters", deviceId);
80 int labelStackSize = (param.getLabelStack() != null) ?
81 param.getLabelStack().size() : 0;
83 if (labelStackSize > 1) {
84 for (PortNumber sp : ports) {
85 PolicyGroupIdentifier previousGroupkey = null;
86 DeviceId neighbor = portDeviceMap.get(sp);
87 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
88 int label = param.getLabelStack().get(idx);
89 if (idx == (labelStackSize - 1)) {
91 GroupBucketIdentifier bucketId =
92 new GroupBucketIdentifier(label,
94 bucketIds.add(bucketId);
95 } else if (idx == 0) {
97 List<GroupBucket> outBuckets = new ArrayList<>();
98 GroupBucketIdentifier bucketId =
99 new GroupBucketIdentifier(label, sp);
100 PolicyGroupIdentifier key = new
101 PolicyGroupIdentifier(id,
102 Collections.singletonList(param),
103 Collections.singletonList(bucketId));
104 TrafficTreatment.Builder tBuilder =
105 DefaultTrafficTreatment.builder();
106 tBuilder.setOutput(sp)
107 .setEthDst(deviceConfig.
108 getDeviceMac(neighbor))
109 .setEthSrc(nodeMacAddr)
111 .setMpls(MplsLabel.mplsLabel(label));
112 /*outBuckets.add(DefaultGroupBucket.
113 createSelectGroupBucket(tBuilder.build()));
114 GroupDescription desc = new
115 DefaultGroupDescription(deviceId,
116 GroupDescription.Type.INDIRECT,
117 new GroupBuckets(outBuckets));
119 previousGroupkey = key;
120 //groupService.addGroup(desc);
121 //TODO: Use nextObjective APIs here
123 // Intermediate Groups
124 GroupBucketIdentifier bucketId =
125 new GroupBucketIdentifier(label,
127 PolicyGroupIdentifier key = new
128 PolicyGroupIdentifier(id,
129 Collections.singletonList(param),
130 Collections.singletonList(bucketId));
131 // Add to group dependency list
132 dependentGroups.put(previousGroupkey, key);
133 previousGroupkey = key;
139 if (labelStackSize == 1) {
140 label = param.getLabelStack().get(0);
142 for (PortNumber sp : ports) {
143 GroupBucketIdentifier bucketId =
144 new GroupBucketIdentifier(label, sp);
145 bucketIds.add(bucketId);
149 PolicyGroupIdentifier innermostGroupkey = null;
150 if (!bucketIds.isEmpty()) {
151 innermostGroupkey = new
152 PolicyGroupIdentifier(id,
155 // Add to group dependency list
156 boolean fullyResolved = true;
157 for (GroupBucketIdentifier bucketId:bucketIds) {
158 if (bucketId.type() == BucketOutputType.GROUP) {
159 dependentGroups.put(bucketId.outGroup(),
161 fullyResolved = false;
166 List<GroupBucket> outBuckets = new ArrayList<>();
167 for (GroupBucketIdentifier bucketId:bucketIds) {
168 DeviceId neighbor = portDeviceMap.
169 get(bucketId.outPort());
170 TrafficTreatment.Builder tBuilder =
171 DefaultTrafficTreatment.builder();
172 tBuilder.setOutput(bucketId.outPort())
173 .setEthDst(deviceConfig.
174 getDeviceMac(neighbor))
175 .setEthSrc(nodeMacAddr);
176 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
178 .setMpls(MplsLabel.mplsLabel(bucketId.label()));
181 /*outBuckets.add(DefaultGroupBucket.
182 createSelectGroupBucket(tBuilder.build()));*/
184 /*GroupDescription desc = new
185 DefaultGroupDescription(deviceId,
186 GroupDescription.Type.SELECT,
187 new GroupBuckets(outBuckets));
188 groupService.addGroup(desc);*/
189 //TODO: Use nextObjective APIs here
192 return innermostGroupkey;
195 //TODO: Use nextObjective APIs to handle the group chains
197 protected void handleGroupEvent(GroupEvent event) {
198 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
199 if (dependentGroups.get(event.subject().appCookie()) != null) {
200 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
201 dependentGroups.remove(event.subject().appCookie());
202 boolean fullyResolved = true;
203 for (GroupBucketIdentifier bucketId:
204 dependentGroupKey.bucketIds()) {
205 if (bucketId.type() != BucketOutputType.GROUP) {
208 if (dependentGroups.containsKey(bucketId.outGroup())) {
209 fullyResolved = false;
215 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
216 for (GroupBucketIdentifier bucketId:
217 dependentGroupKey.bucketIds()) {
218 TrafficTreatment.Builder tBuilder =
219 DefaultTrafficTreatment.builder();
220 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
223 mplsLabel(bucketId.label()));
226 if (bucketId.type() == BucketOutputType.PORT) {
227 DeviceId neighbor = portDeviceMap.
228 get(bucketId.outPort());
229 tBuilder.setOutput(bucketId.outPort())
230 .setEthDst(deviceConfig.
231 getDeviceMac(neighbor))
232 .setEthSrc(nodeMacAddr);
236 getGroupKey(bucketId.
237 outGroup())) == null) {
238 throw new IllegalStateException();
240 GroupId indirectGroupId = groupService.
242 getGroupKey(bucketId.
244 tBuilder.group(indirectGroupId);
246 outBuckets.add(DefaultGroupBucket.
247 createSelectGroupBucket(tBuilder.build()));
249 GroupDescription desc = new
250 DefaultGroupDescription(deviceId,
251 GroupDescription.Type.SELECT,
252 new GroupBuckets(outBuckets));
253 groupService.addGroup(desc);
259 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
260 List<PolicyGroupParams> params) {
261 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
262 for (PolicyGroupParams param: params) {
263 List<PortNumber> ports = param.getPorts();
265 log.warn("generateGroupKey in sw {} with wrong "
266 + "input parameters", deviceId);
270 int labelStackSize = (param.getLabelStack() != null)
271 ? param.getLabelStack().size() : 0;
273 if (labelStackSize > 1) {
274 for (PortNumber sp : ports) {
275 PolicyGroupIdentifier previousGroupkey = null;
276 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
277 int label = param.getLabelStack().get(idx);
278 if (idx == (labelStackSize - 1)) {
280 GroupBucketIdentifier bucketId =
281 new GroupBucketIdentifier(label,
283 bucketIds.add(bucketId);
284 } else if (idx == 0) {
286 GroupBucketIdentifier bucketId =
287 new GroupBucketIdentifier(label, sp);
288 PolicyGroupIdentifier key = new
289 PolicyGroupIdentifier(id,
290 Collections.singletonList(param),
291 Collections.singletonList(bucketId));
292 previousGroupkey = key;
294 // Intermediate Groups
295 GroupBucketIdentifier bucketId =
296 new GroupBucketIdentifier(label,
298 PolicyGroupIdentifier key = new
299 PolicyGroupIdentifier(id,
300 Collections.singletonList(param),
301 Collections.singletonList(bucketId));
302 previousGroupkey = key;
308 if (labelStackSize == 1) {
309 label = param.getLabelStack().get(0);
311 for (PortNumber sp : ports) {
312 GroupBucketIdentifier bucketId =
313 new GroupBucketIdentifier(label, sp);
314 bucketIds.add(bucketId);
318 PolicyGroupIdentifier innermostGroupkey = null;
319 if (!bucketIds.isEmpty()) {
320 innermostGroupkey = new
321 PolicyGroupIdentifier(id,
325 return innermostGroupkey;
328 public void removeGroupChain(PolicyGroupIdentifier key) {
329 checkArgument(key != null);
330 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
331 groupsToBeDeleted.add(key);
333 Iterator<PolicyGroupIdentifier> it =
334 groupsToBeDeleted.iterator();
336 while (it.hasNext()) {
337 PolicyGroupIdentifier innerMostGroupKey = it.next();
338 for (GroupBucketIdentifier bucketId:
339 innerMostGroupKey.bucketIds()) {
340 if (bucketId.type() != BucketOutputType.GROUP) {
341 groupsToBeDeleted.add(bucketId.outGroup());
344 /*groupService.removeGroup(deviceId,
345 getGroupKey(innerMostGroupKey),
347 //TODO: Use nextObjective APIs here