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