blob: 4f57bd3365cef5859abca8c00809e45a2a733106 [file] [log] [blame]
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16package org.onosproject.grouphandler;
17
18import static org.slf4j.LoggerFactory.getLogger;
19
20import java.util.ArrayList;
21import java.util.Arrays;
22import java.util.HashMap;
23import java.util.Iterator;
24import java.util.List;
25
26import org.onosproject.core.ApplicationId;
27import org.onosproject.core.GroupId;
28import org.onosproject.grouphandler.GroupBucketIdentifier.BucketOutputType;
29import org.onosproject.net.DeviceId;
30import org.onosproject.net.PortNumber;
31import org.onosproject.net.flow.DefaultTrafficTreatment;
32import org.onosproject.net.flow.TrafficTreatment;
33import org.onosproject.net.group.DefaultGroupBucket;
34import org.onosproject.net.group.DefaultGroupDescription;
35import org.onosproject.net.group.GroupBucket;
36import org.onosproject.net.group.GroupBuckets;
37import org.onosproject.net.group.GroupDescription;
38import org.onosproject.net.group.GroupEvent;
39import org.onosproject.net.group.GroupKey;
40import org.onosproject.net.group.GroupService;
41import org.onosproject.net.link.LinkService;
42import org.slf4j.Logger;
43
44/**
45 * A module to create group chains based on the specified device
46 * ports and label stack to be applied on each port.
47 */
48public class PolicyGroupHandler extends DefaultGroupHandler {
49
50 private final Logger log = getLogger(getClass());
51 private HashMap<GroupKey, GroupKey> dependentGroups =
52 new HashMap<GroupKey, GroupKey>();
53
54 /**
55 * Creates policy group handler object.
56 *
57 * @param deviceId device identifier
58 * @param appId application identifier
59 * @param config interface to retrieve the device properties
60 * @param linkService link service object
61 * @param groupService group service object
62 * @return policy group handler type
63 */
64 public PolicyGroupHandler(DeviceId deviceId,
65 ApplicationId appId,
66 DeviceProperties config,
67 LinkService linkService,
68 GroupService groupService) {
69 super(deviceId, appId, config, linkService, groupService);
70 }
71
72 public PolicyGroupIdentifier createPolicyGroupChain(String id,
73 List<PolicyGroupParams> params) {
74 List<GroupBucketIdentifier> bucketIds = new ArrayList<GroupBucketIdentifier>();
75 for (PolicyGroupParams param: params) {
76 List<PortNumber> ports = param.getPorts();
77 if (ports == null) {
78 log.warn("createPolicyGroupChain in sw {} with wrong "
79 + "input parameters", deviceId);
80 return null;
81 }
82
83 int labelStackSize = (param.getLabelStack() != null) ?
84 param.getLabelStack().size() : 0;
85
86 if (labelStackSize > 1) {
87 for (PortNumber sp : ports) {
88 PolicyGroupIdentifier previousGroupkey = null;
89 DeviceId neighbor = portDeviceMap.get(sp);
90 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
91 int label = param.getLabelStack().get(idx).intValue();
92 if (idx == (labelStackSize - 1)) {
93 // Innermost Group
94 GroupBucketIdentifier bucketId =
95 new GroupBucketIdentifier(label,
96 previousGroupkey);
97 bucketIds.add(bucketId);
98 } else if (idx == 0) {
99 // Outermost Group
100 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
101 GroupBucketIdentifier bucketId =
102 new GroupBucketIdentifier(label, sp);
103 PolicyGroupIdentifier key = new
104 PolicyGroupIdentifier(id,
105 Arrays.asList(param),
106 Arrays.asList(bucketId));
107 TrafficTreatment.Builder tBuilder =
108 DefaultTrafficTreatment.builder();
109 tBuilder.setOutput(sp)
110 .setEthDst(deviceConfig.
111 getDeviceMac(neighbor))
112 .setEthSrc(nodeMacAddr)
113 .pushMpls()
114 .setMpls(label);
115 outBuckets.add(DefaultGroupBucket.
116 createSelectGroupBucket(tBuilder.build()));
117 GroupDescription desc = new
118 DefaultGroupDescription(deviceId,
119 GroupDescription.Type.INDIRECT,
120 new GroupBuckets(outBuckets));
121 //TODO: BoS
122 previousGroupkey = key;
123 groupService.addGroup(desc);
124 } else {
125 // Intermediate Groups
126 GroupBucketIdentifier bucketId =
127 new GroupBucketIdentifier(label,
128 previousGroupkey);
129 PolicyGroupIdentifier key = new
130 PolicyGroupIdentifier(id,
131 Arrays.asList(param),
132 Arrays.asList(bucketId));
133 // Add to group dependency list
134 dependentGroups.put(previousGroupkey, key);
135 previousGroupkey = key;
136 }
137 }
138 }
139 } else {
140 int label = -1;
141 if (labelStackSize == 1) {
142 label = param.getLabelStack().get(0).intValue();
143 }
144 for (PortNumber sp : ports) {
145 GroupBucketIdentifier bucketId =
146 new GroupBucketIdentifier(label, sp);
147 bucketIds.add(bucketId);
148 }
149 }
150 }
151 PolicyGroupIdentifier innermostGroupkey = null;
152 if (!bucketIds.isEmpty()) {
153 innermostGroupkey = new
154 PolicyGroupIdentifier(id,
155 params,
156 bucketIds);
157 // Add to group dependency list
158 boolean fullyResolved = true;
159 for (GroupBucketIdentifier bucketId:bucketIds) {
160 if (bucketId.type() == BucketOutputType.GROUP) {
161 dependentGroups.put(bucketId.outGroup(),
162 innermostGroupkey);
163 fullyResolved = false;
164 }
165 }
166
167 if (fullyResolved) {
168 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
169 for (GroupBucketIdentifier bucketId:bucketIds) {
170 DeviceId neighbor = portDeviceMap.
171 get(bucketId.outPort());
172 TrafficTreatment.Builder tBuilder =
173 DefaultTrafficTreatment.builder();
174 tBuilder.setOutput(bucketId.outPort())
175 .setEthDst(deviceConfig.
176 getDeviceMac(neighbor))
177 .setEthSrc(nodeMacAddr)
178 .pushMpls()
179 .setMpls(bucketId.label());
180 //TODO: BoS
181 outBuckets.add(DefaultGroupBucket.
182 createSelectGroupBucket(tBuilder.build()));
183 }
184 GroupDescription desc = new
185 DefaultGroupDescription(deviceId,
186 GroupDescription.Type.SELECT,
187 new GroupBuckets(outBuckets));
188 groupService.addGroup(desc);
189 }
190 }
191 return innermostGroupkey;
192 }
193
194 @Override
195 protected void handleGroupEvent(GroupEvent event) {
196 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
197 if (dependentGroups.get(event.subject().appCookie()) != null) {
198 PolicyGroupIdentifier dependentGroupKey = (PolicyGroupIdentifier)
199 dependentGroups.get(event.subject().appCookie());
200 dependentGroups.remove(event.subject().appCookie());
201 boolean fullyResolved = true;
202 for (GroupBucketIdentifier bucketId:
203 dependentGroupKey.bucketIds()) {
204 if (bucketId.type() != BucketOutputType.GROUP) {
205 continue;
206 }
207 if (dependentGroups.containsKey(bucketId.outGroup())) {
208 fullyResolved = false;
209 break;
210 }
211 }
212
213 if (fullyResolved) {
214 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
215 for (GroupBucketIdentifier bucketId:
216 dependentGroupKey.bucketIds()) {
217 TrafficTreatment.Builder tBuilder =
218 DefaultTrafficTreatment.builder();
219 tBuilder.pushMpls()
220 .setMpls(bucketId.label());
221 //TODO: BoS
222 if (bucketId.type() == BucketOutputType.PORT) {
223 DeviceId neighbor = portDeviceMap.
224 get(bucketId.outPort());
225 tBuilder.setOutput(bucketId.outPort())
226 .setEthDst(deviceConfig.
227 getDeviceMac(neighbor))
228 .setEthSrc(nodeMacAddr);
229 } else {
230 if (groupService.
231 getGroup(deviceId,
232 bucketId.outGroup()) == null) {
233 throw new IllegalStateException();
234 }
235 GroupId indirectGroupId = groupService.
236 getGroup(deviceId,
237 bucketId.outGroup()).id();
238 tBuilder.group(indirectGroupId);
239 }
240 outBuckets.add(DefaultGroupBucket.
241 createSelectGroupBucket(tBuilder.build()));
242 }
243 GroupDescription desc = new
244 DefaultGroupDescription(deviceId,
245 GroupDescription.Type.SELECT,
246 new GroupBuckets(outBuckets));
247 groupService.addGroup(desc);
248 }
249 }
250 }
251 }
252
253 public GroupKey generatePolicyGroupKey(String id,
254 List<PolicyGroupParams> params) {
255 List<GroupBucketIdentifier> bucketIds = new ArrayList<GroupBucketIdentifier>();
256 for (PolicyGroupParams param: params) {
257 List<PortNumber> ports = param.getPorts();
258 if (ports == null) {
259 log.warn("generateGroupKey in sw {} with wrong "
260 + "input parameters", deviceId);
261 return null;
262 }
263
264 int labelStackSize = (param.getLabelStack() != null)
265 ? param.getLabelStack().size() : 0;
266
267 if (labelStackSize > 1) {
268 for (PortNumber sp : ports) {
269 PolicyGroupIdentifier previousGroupkey = null;
270 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
271 int label = param.getLabelStack().get(idx).intValue();
272 if (idx == (labelStackSize - 1)) {
273 // Innermost Group
274 GroupBucketIdentifier bucketId =
275 new GroupBucketIdentifier(label,
276 previousGroupkey);
277 bucketIds.add(bucketId);
278 } else if (idx == 0) {
279 // Outermost Group
280 GroupBucketIdentifier bucketId =
281 new GroupBucketIdentifier(label, sp);
282 PolicyGroupIdentifier key = new
283 PolicyGroupIdentifier(id,
284 Arrays.asList(param),
285 Arrays.asList(bucketId));
286 previousGroupkey = key;
287 } else {
288 // Intermediate Groups
289 GroupBucketIdentifier bucketId =
290 new GroupBucketIdentifier(label,
291 previousGroupkey);
292 PolicyGroupIdentifier key = new
293 PolicyGroupIdentifier(id,
294 Arrays.asList(param),
295 Arrays.asList(bucketId));
296 previousGroupkey = key;
297 }
298 }
299 }
300 } else {
301 int label = -1;
302 if (labelStackSize == 1) {
303 label = param.getLabelStack().get(0).intValue();
304 }
305 for (PortNumber sp : ports) {
306 GroupBucketIdentifier bucketId =
307 new GroupBucketIdentifier(label, sp);
308 bucketIds.add(bucketId);
309 }
310 }
311 }
312 PolicyGroupIdentifier innermostGroupkey = null;
313 if (!bucketIds.isEmpty()) {
314 innermostGroupkey = new
315 PolicyGroupIdentifier(id,
316 params,
317 bucketIds);
318 }
319 return innermostGroupkey;
320 }
321
322 public void removeGroupChain(GroupKey key) {
323 if (!(key instanceof PolicyGroupIdentifier)) {
324 throw new IllegalArgumentException();
325 }
326 List<GroupKey> groupsToBeDeleted = new ArrayList<GroupKey>();
327 groupsToBeDeleted.add(key);
328
329 Iterator<GroupKey> it = groupsToBeDeleted.iterator();
330
331 while (it.hasNext()) {
332 PolicyGroupIdentifier innerMostGroupKey =
333 (PolicyGroupIdentifier) it.next();
334 for (GroupBucketIdentifier bucketId:
335 innerMostGroupKey.bucketIds()) {
336 if (bucketId.type() != BucketOutputType.GROUP) {
337 groupsToBeDeleted.add(bucketId.outGroup());
338 }
339 }
340 groupService.removeGroup(deviceId, innerMostGroupKey, appId);
341 it.remove();
342 }
343 }
344
345}