blob: 6623696ef85da6aab50cdc1a0820f8a6eb011f43 [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
Sho SHIMIZU24deb902015-05-11 18:40:48 -070018import static com.google.common.base.Preconditions.checkArgument;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080019import static org.slf4j.LoggerFactory.getLogger;
20
21import java.util.ArrayList;
Sho SHIMIZU98ffca82015-05-11 08:39:24 -070022import java.util.Collections;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080023import java.util.HashMap;
24import java.util.Iterator;
25import java.util.List;
26
sangho32a59322015-02-17 12:07:41 -080027import org.onlab.packet.MplsLabel;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080028import org.onosproject.core.ApplicationId;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070029import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070030import org.onosproject.store.service.EventuallyConsistentMap;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080031import org.onosproject.net.DeviceId;
32import org.onosproject.net.PortNumber;
33import org.onosproject.net.flow.DefaultTrafficTreatment;
34import org.onosproject.net.flow.TrafficTreatment;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070035import org.onosproject.net.flowobjective.FlowObjectiveService;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080036import org.onosproject.net.group.GroupBucket;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080037import org.onosproject.net.link.LinkService;
38import org.slf4j.Logger;
39
40/**
41 * A module to create group chains based on the specified device
42 * ports and label stack to be applied on each port.
43 */
44public class PolicyGroupHandler extends DefaultGroupHandler {
45
46 private final Logger log = getLogger(getClass());
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -070047 private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080048
49 /**
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070050 * Policy group handler constructor.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080051 *
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
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070056 * @param flowObjService flow objective service object
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080057 */
58 public PolicyGroupHandler(DeviceId deviceId,
59 ApplicationId appId,
60 DeviceProperties config,
61 LinkService linkService,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070062 FlowObjectiveService flowObjService,
63 EventuallyConsistentMap<
64 NeighborSetNextObjectiveStoreKey,
65 Integer> nsNextObjStore) {
66 super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080067 }
68
69 public PolicyGroupIdentifier createPolicyGroupChain(String id,
70 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -070071 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080072 for (PolicyGroupParams param: params) {
73 List<PortNumber> ports = param.getPorts();
74 if (ports == null) {
75 log.warn("createPolicyGroupChain in sw {} with wrong "
76 + "input parameters", deviceId);
77 return null;
78 }
79
80 int labelStackSize = (param.getLabelStack() != null) ?
81 param.getLabelStack().size() : 0;
82
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++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -070088 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080089 if (idx == (labelStackSize - 1)) {
90 // Innermost Group
91 GroupBucketIdentifier bucketId =
92 new GroupBucketIdentifier(label,
93 previousGroupkey);
94 bucketIds.add(bucketId);
95 } else if (idx == 0) {
96 // Outermost Group
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -070097 List<GroupBucket> outBuckets = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080098 GroupBucketIdentifier bucketId =
99 new GroupBucketIdentifier(label, sp);
100 PolicyGroupIdentifier key = new
101 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700102 Collections.singletonList(param),
103 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800104 TrafficTreatment.Builder tBuilder =
105 DefaultTrafficTreatment.builder();
106 tBuilder.setOutput(sp)
107 .setEthDst(deviceConfig.
108 getDeviceMac(neighbor))
109 .setEthSrc(nodeMacAddr)
110 .pushMpls()
sangho32a59322015-02-17 12:07:41 -0800111 .setMpls(MplsLabel.mplsLabel(label));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700112 /*outBuckets.add(DefaultGroupBucket.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800113 createSelectGroupBucket(tBuilder.build()));
114 GroupDescription desc = new
115 DefaultGroupDescription(deviceId,
116 GroupDescription.Type.INDIRECT,
117 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700118 //TODO: BoS*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800119 previousGroupkey = key;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700120 //groupService.addGroup(desc);
121 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800122 } else {
123 // Intermediate Groups
124 GroupBucketIdentifier bucketId =
125 new GroupBucketIdentifier(label,
126 previousGroupkey);
127 PolicyGroupIdentifier key = new
128 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700129 Collections.singletonList(param),
130 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800131 // Add to group dependency list
132 dependentGroups.put(previousGroupkey, key);
133 previousGroupkey = key;
134 }
135 }
136 }
137 } else {
138 int label = -1;
139 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700140 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800141 }
142 for (PortNumber sp : ports) {
143 GroupBucketIdentifier bucketId =
144 new GroupBucketIdentifier(label, sp);
145 bucketIds.add(bucketId);
146 }
147 }
148 }
149 PolicyGroupIdentifier innermostGroupkey = null;
150 if (!bucketIds.isEmpty()) {
151 innermostGroupkey = new
152 PolicyGroupIdentifier(id,
153 params,
154 bucketIds);
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(),
160 innermostGroupkey);
161 fullyResolved = false;
162 }
163 }
164
165 if (fullyResolved) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700166 List<GroupBucket> outBuckets = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800167 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))
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700175 .setEthSrc(nodeMacAddr);
176 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
177 tBuilder.pushMpls()
sangho32a59322015-02-17 12:07:41 -0800178 .setMpls(MplsLabel.mplsLabel(bucketId.label()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700179 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800180 //TODO: BoS
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700181 /*outBuckets.add(DefaultGroupBucket.
182 createSelectGroupBucket(tBuilder.build()));*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800183 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700184 /*GroupDescription desc = new
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800185 DefaultGroupDescription(deviceId,
186 GroupDescription.Type.SELECT,
187 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700188 groupService.addGroup(desc);*/
189 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800190 }
191 }
192 return innermostGroupkey;
193 }
194
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700195 //TODO: Use nextObjective APIs to handle the group chains
196 /*@Override
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800197 protected void handleGroupEvent(GroupEvent event) {
198 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
199 if (dependentGroups.get(event.subject().appCookie()) != null) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700200 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800201 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();
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700220 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
221 tBuilder.pushMpls()
222 .setMpls(MplsLabel.
223 mplsLabel(bucketId.label()));
224 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800225 //TODO: BoS
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);
233 } else {
234 if (groupService.
235 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700236 getGroupKey(bucketId.
237 outGroup())) == null) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800238 throw new IllegalStateException();
239 }
240 GroupId indirectGroupId = groupService.
241 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700242 getGroupKey(bucketId.
243 outGroup())).id();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800244 tBuilder.group(indirectGroupId);
245 }
246 outBuckets.add(DefaultGroupBucket.
247 createSelectGroupBucket(tBuilder.build()));
248 }
249 GroupDescription desc = new
250 DefaultGroupDescription(deviceId,
251 GroupDescription.Type.SELECT,
252 new GroupBuckets(outBuckets));
253 groupService.addGroup(desc);
254 }
255 }
256 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700257 }*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800258
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700259 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800260 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700261 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800262 for (PolicyGroupParams param: params) {
263 List<PortNumber> ports = param.getPorts();
264 if (ports == null) {
265 log.warn("generateGroupKey in sw {} with wrong "
266 + "input parameters", deviceId);
267 return null;
268 }
269
270 int labelStackSize = (param.getLabelStack() != null)
271 ? param.getLabelStack().size() : 0;
272
273 if (labelStackSize > 1) {
274 for (PortNumber sp : ports) {
275 PolicyGroupIdentifier previousGroupkey = null;
276 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700277 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800278 if (idx == (labelStackSize - 1)) {
279 // Innermost Group
280 GroupBucketIdentifier bucketId =
281 new GroupBucketIdentifier(label,
282 previousGroupkey);
283 bucketIds.add(bucketId);
284 } else if (idx == 0) {
285 // Outermost Group
286 GroupBucketIdentifier bucketId =
287 new GroupBucketIdentifier(label, sp);
288 PolicyGroupIdentifier key = new
289 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700290 Collections.singletonList(param),
291 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800292 previousGroupkey = key;
293 } else {
294 // Intermediate Groups
295 GroupBucketIdentifier bucketId =
296 new GroupBucketIdentifier(label,
297 previousGroupkey);
298 PolicyGroupIdentifier key = new
299 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700300 Collections.singletonList(param),
301 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800302 previousGroupkey = key;
303 }
304 }
305 }
306 } else {
307 int label = -1;
308 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700309 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800310 }
311 for (PortNumber sp : ports) {
312 GroupBucketIdentifier bucketId =
313 new GroupBucketIdentifier(label, sp);
314 bucketIds.add(bucketId);
315 }
316 }
317 }
318 PolicyGroupIdentifier innermostGroupkey = null;
319 if (!bucketIds.isEmpty()) {
320 innermostGroupkey = new
321 PolicyGroupIdentifier(id,
322 params,
323 bucketIds);
324 }
325 return innermostGroupkey;
326 }
327
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700328 public void removeGroupChain(PolicyGroupIdentifier key) {
Sho SHIMIZU24deb902015-05-11 18:40:48 -0700329 checkArgument(key != null);
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700330 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800331 groupsToBeDeleted.add(key);
332
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700333 Iterator<PolicyGroupIdentifier> it =
334 groupsToBeDeleted.iterator();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800335
336 while (it.hasNext()) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700337 PolicyGroupIdentifier innerMostGroupKey = it.next();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800338 for (GroupBucketIdentifier bucketId:
339 innerMostGroupKey.bucketIds()) {
340 if (bucketId.type() != BucketOutputType.GROUP) {
341 groupsToBeDeleted.add(bucketId.outGroup());
342 }
343 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700344 /*groupService.removeGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700345 getGroupKey(innerMostGroupKey),
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700346 appId);*/
347 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800348 it.remove();
349 }
350 }
351
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700352}