blob: 9f35c742f845b9ede6b5694d1518bdd1e81de0d0 [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 */
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070016package org.onosproject.segmentrouting.grouphandler;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080017
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;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070029import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080030import 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;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080040import 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());
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070051 private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups =
52 new HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080053
54 /**
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070055 * Policy group handler constructor.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080056 *
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
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080062 */
63 public PolicyGroupHandler(DeviceId deviceId,
64 ApplicationId appId,
65 DeviceProperties config,
66 LinkService linkService,
67 GroupService groupService) {
68 super(deviceId, appId, config, linkService, groupService);
69 }
70
71 public PolicyGroupIdentifier createPolicyGroupChain(String id,
72 List<PolicyGroupParams> params) {
73 List<GroupBucketIdentifier> bucketIds = new ArrayList<GroupBucketIdentifier>();
74 for (PolicyGroupParams param: params) {
75 List<PortNumber> ports = param.getPorts();
76 if (ports == null) {
77 log.warn("createPolicyGroupChain in sw {} with wrong "
78 + "input parameters", deviceId);
79 return null;
80 }
81
82 int labelStackSize = (param.getLabelStack() != null) ?
83 param.getLabelStack().size() : 0;
84
85 if (labelStackSize > 1) {
86 for (PortNumber sp : ports) {
87 PolicyGroupIdentifier previousGroupkey = null;
88 DeviceId neighbor = portDeviceMap.get(sp);
89 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
90 int label = param.getLabelStack().get(idx).intValue();
91 if (idx == (labelStackSize - 1)) {
92 // Innermost Group
93 GroupBucketIdentifier bucketId =
94 new GroupBucketIdentifier(label,
95 previousGroupkey);
96 bucketIds.add(bucketId);
97 } else if (idx == 0) {
98 // Outermost Group
99 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
100 GroupBucketIdentifier bucketId =
101 new GroupBucketIdentifier(label, sp);
102 PolicyGroupIdentifier key = new
103 PolicyGroupIdentifier(id,
104 Arrays.asList(param),
105 Arrays.asList(bucketId));
106 TrafficTreatment.Builder tBuilder =
107 DefaultTrafficTreatment.builder();
108 tBuilder.setOutput(sp)
109 .setEthDst(deviceConfig.
110 getDeviceMac(neighbor))
111 .setEthSrc(nodeMacAddr)
112 .pushMpls()
sangho32a59322015-02-17 12:07:41 -0800113 .setMpls(MplsLabel.mplsLabel(label));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800114 outBuckets.add(DefaultGroupBucket.
115 createSelectGroupBucket(tBuilder.build()));
116 GroupDescription desc = new
117 DefaultGroupDescription(deviceId,
118 GroupDescription.Type.INDIRECT,
119 new GroupBuckets(outBuckets));
120 //TODO: BoS
121 previousGroupkey = key;
122 groupService.addGroup(desc);
123 } else {
124 // Intermediate Groups
125 GroupBucketIdentifier bucketId =
126 new GroupBucketIdentifier(label,
127 previousGroupkey);
128 PolicyGroupIdentifier key = new
129 PolicyGroupIdentifier(id,
130 Arrays.asList(param),
131 Arrays.asList(bucketId));
132 // Add to group dependency list
133 dependentGroups.put(previousGroupkey, key);
134 previousGroupkey = key;
135 }
136 }
137 }
138 } else {
139 int label = -1;
140 if (labelStackSize == 1) {
141 label = param.getLabelStack().get(0).intValue();
142 }
143 for (PortNumber sp : ports) {
144 GroupBucketIdentifier bucketId =
145 new GroupBucketIdentifier(label, sp);
146 bucketIds.add(bucketId);
147 }
148 }
149 }
150 PolicyGroupIdentifier innermostGroupkey = null;
151 if (!bucketIds.isEmpty()) {
152 innermostGroupkey = new
153 PolicyGroupIdentifier(id,
154 params,
155 bucketIds);
156 // Add to group dependency list
157 boolean fullyResolved = true;
158 for (GroupBucketIdentifier bucketId:bucketIds) {
159 if (bucketId.type() == BucketOutputType.GROUP) {
160 dependentGroups.put(bucketId.outGroup(),
161 innermostGroupkey);
162 fullyResolved = false;
163 }
164 }
165
166 if (fullyResolved) {
167 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
168 for (GroupBucketIdentifier bucketId:bucketIds) {
169 DeviceId neighbor = portDeviceMap.
170 get(bucketId.outPort());
171 TrafficTreatment.Builder tBuilder =
172 DefaultTrafficTreatment.builder();
173 tBuilder.setOutput(bucketId.outPort())
174 .setEthDst(deviceConfig.
175 getDeviceMac(neighbor))
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700176 .setEthSrc(nodeMacAddr);
177 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
178 tBuilder.pushMpls()
sangho32a59322015-02-17 12:07:41 -0800179 .setMpls(MplsLabel.mplsLabel(bucketId.label()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700180 }
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) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700199 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800200 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();
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700219 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
220 tBuilder.pushMpls()
221 .setMpls(MplsLabel.
222 mplsLabel(bucketId.label()));
223 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800224 //TODO: BoS
225 if (bucketId.type() == BucketOutputType.PORT) {
226 DeviceId neighbor = portDeviceMap.
227 get(bucketId.outPort());
228 tBuilder.setOutput(bucketId.outPort())
229 .setEthDst(deviceConfig.
230 getDeviceMac(neighbor))
231 .setEthSrc(nodeMacAddr);
232 } else {
233 if (groupService.
234 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700235 getGroupKey(bucketId.
236 outGroup())) == null) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800237 throw new IllegalStateException();
238 }
239 GroupId indirectGroupId = groupService.
240 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700241 getGroupKey(bucketId.
242 outGroup())).id();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800243 tBuilder.group(indirectGroupId);
244 }
245 outBuckets.add(DefaultGroupBucket.
246 createSelectGroupBucket(tBuilder.build()));
247 }
248 GroupDescription desc = new
249 DefaultGroupDescription(deviceId,
250 GroupDescription.Type.SELECT,
251 new GroupBuckets(outBuckets));
252 groupService.addGroup(desc);
253 }
254 }
255 }
256 }
257
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700258 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800259 List<PolicyGroupParams> params) {
260 List<GroupBucketIdentifier> bucketIds = new ArrayList<GroupBucketIdentifier>();
261 for (PolicyGroupParams param: params) {
262 List<PortNumber> ports = param.getPorts();
263 if (ports == null) {
264 log.warn("generateGroupKey in sw {} with wrong "
265 + "input parameters", deviceId);
266 return null;
267 }
268
269 int labelStackSize = (param.getLabelStack() != null)
270 ? param.getLabelStack().size() : 0;
271
272 if (labelStackSize > 1) {
273 for (PortNumber sp : ports) {
274 PolicyGroupIdentifier previousGroupkey = null;
275 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
276 int label = param.getLabelStack().get(idx).intValue();
277 if (idx == (labelStackSize - 1)) {
278 // Innermost Group
279 GroupBucketIdentifier bucketId =
280 new GroupBucketIdentifier(label,
281 previousGroupkey);
282 bucketIds.add(bucketId);
283 } else if (idx == 0) {
284 // Outermost Group
285 GroupBucketIdentifier bucketId =
286 new GroupBucketIdentifier(label, sp);
287 PolicyGroupIdentifier key = new
288 PolicyGroupIdentifier(id,
289 Arrays.asList(param),
290 Arrays.asList(bucketId));
291 previousGroupkey = key;
292 } else {
293 // Intermediate Groups
294 GroupBucketIdentifier bucketId =
295 new GroupBucketIdentifier(label,
296 previousGroupkey);
297 PolicyGroupIdentifier key = new
298 PolicyGroupIdentifier(id,
299 Arrays.asList(param),
300 Arrays.asList(bucketId));
301 previousGroupkey = key;
302 }
303 }
304 }
305 } else {
306 int label = -1;
307 if (labelStackSize == 1) {
308 label = param.getLabelStack().get(0).intValue();
309 }
310 for (PortNumber sp : ports) {
311 GroupBucketIdentifier bucketId =
312 new GroupBucketIdentifier(label, sp);
313 bucketIds.add(bucketId);
314 }
315 }
316 }
317 PolicyGroupIdentifier innermostGroupkey = null;
318 if (!bucketIds.isEmpty()) {
319 innermostGroupkey = new
320 PolicyGroupIdentifier(id,
321 params,
322 bucketIds);
323 }
324 return innermostGroupkey;
325 }
326
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700327 public void removeGroupChain(PolicyGroupIdentifier key) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800328 if (!(key instanceof PolicyGroupIdentifier)) {
329 throw new IllegalArgumentException();
330 }
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700331 List<PolicyGroupIdentifier> groupsToBeDeleted =
332 new ArrayList<PolicyGroupIdentifier>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800333 groupsToBeDeleted.add(key);
334
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700335 Iterator<PolicyGroupIdentifier> it =
336 groupsToBeDeleted.iterator();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800337
338 while (it.hasNext()) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700339 PolicyGroupIdentifier innerMostGroupKey = it.next();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800340 for (GroupBucketIdentifier bucketId:
341 innerMostGroupKey.bucketIds()) {
342 if (bucketId.type() != BucketOutputType.GROUP) {
343 groupsToBeDeleted.add(bucketId.outGroup());
344 }
345 }
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700346 groupService.removeGroup(deviceId,
347 getGroupKey(innerMostGroupKey),
348 appId);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800349 it.remove();
350 }
351 }
352
353}