blob: 6623696ef85da6aab50cdc1a0820f8a6eb011f43 [file] [log] [blame]
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -07001/*
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.segmentrouting.grouphandler;
17
Sho SHIMIZU11ead6e2015-05-11 18:40:48 -070018import static com.google.common.base.Preconditions.checkArgument;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070019import static org.slf4j.LoggerFactory.getLogger;
20
21import java.util.ArrayList;
Sho SHIMIZU84684a52015-05-11 08:39:24 -070022import java.util.Collections;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070023import java.util.HashMap;
24import java.util.Iterator;
25import java.util.List;
26
27import org.onlab.packet.MplsLabel;
28import org.onosproject.core.ApplicationId;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070029import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070030import org.onosproject.store.service.EventuallyConsistentMap;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070031import org.onosproject.net.DeviceId;
32import org.onosproject.net.PortNumber;
33import org.onosproject.net.flow.DefaultTrafficTreatment;
34import org.onosproject.net.flow.TrafficTreatment;
Srikanth Vavilapalli64505482015-04-21 13:04:13 -070035import org.onosproject.net.flowobjective.FlowObjectiveService;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070036import org.onosproject.net.group.GroupBucket;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070037import 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 SHIMIZU6ac2f4d2015-05-11 18:37:27 -070047 private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070048
49 /**
50 * Policy group handler constructor.
51 *
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 Vavilapalli64505482015-04-21 13:04:13 -070056 * @param flowObjService flow objective service object
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070057 */
58 public PolicyGroupHandler(DeviceId deviceId,
59 ApplicationId appId,
60 DeviceProperties config,
61 LinkService linkService,
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070062 FlowObjectiveService flowObjService,
63 EventuallyConsistentMap<
64 NeighborSetNextObjectiveStoreKey,
65 Integer> nsNextObjStore) {
66 super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070067 }
68
69 public PolicyGroupIdentifier createPolicyGroupChain(String id,
70 List<PolicyGroupParams> params) {
Sho SHIMIZU6ac2f4d2015-05-11 18:37:27 -070071 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070072 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 SHIMIZUcc2a4ba2015-05-11 18:42:18 -070088 int label = param.getLabelStack().get(idx);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070089 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 SHIMIZU6ac2f4d2015-05-11 18:37:27 -070097 List<GroupBucket> outBuckets = new ArrayList<>();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070098 GroupBucketIdentifier bucketId =
99 new GroupBucketIdentifier(label, sp);
100 PolicyGroupIdentifier key = new
101 PolicyGroupIdentifier(id,
Sho SHIMIZU84684a52015-05-11 08:39:24 -0700102 Collections.singletonList(param),
103 Collections.singletonList(bucketId));
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700104 TrafficTreatment.Builder tBuilder =
105 DefaultTrafficTreatment.builder();
106 tBuilder.setOutput(sp)
107 .setEthDst(deviceConfig.
108 getDeviceMac(neighbor))
109 .setEthSrc(nodeMacAddr)
110 .pushMpls()
111 .setMpls(MplsLabel.mplsLabel(label));
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700112 /*outBuckets.add(DefaultGroupBucket.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700113 createSelectGroupBucket(tBuilder.build()));
114 GroupDescription desc = new
115 DefaultGroupDescription(deviceId,
116 GroupDescription.Type.INDIRECT,
117 new GroupBuckets(outBuckets));
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700118 //TODO: BoS*/
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700119 previousGroupkey = key;
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700120 //groupService.addGroup(desc);
121 //TODO: Use nextObjective APIs here
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700122 } else {
123 // Intermediate Groups
124 GroupBucketIdentifier bucketId =
125 new GroupBucketIdentifier(label,
126 previousGroupkey);
127 PolicyGroupIdentifier key = new
128 PolicyGroupIdentifier(id,
Sho SHIMIZU84684a52015-05-11 08:39:24 -0700129 Collections.singletonList(param),
130 Collections.singletonList(bucketId));
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700131 // 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 SHIMIZUcc2a4ba2015-05-11 18:42:18 -0700140 label = param.getLabelStack().get(0);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700141 }
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 SHIMIZU6ac2f4d2015-05-11 18:37:27 -0700166 List<GroupBucket> outBuckets = new ArrayList<>();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700167 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) {
177 tBuilder.pushMpls()
178 .setMpls(MplsLabel.mplsLabel(bucketId.label()));
179 }
180 //TODO: BoS
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700181 /*outBuckets.add(DefaultGroupBucket.
182 createSelectGroupBucket(tBuilder.build()));*/
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700183 }
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700184 /*GroupDescription desc = new
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700185 DefaultGroupDescription(deviceId,
186 GroupDescription.Type.SELECT,
187 new GroupBuckets(outBuckets));
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700188 groupService.addGroup(desc);*/
189 //TODO: Use nextObjective APIs here
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700190 }
191 }
192 return innermostGroupkey;
193 }
194
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700195 //TODO: Use nextObjective APIs to handle the group chains
196 /*@Override
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700197 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) {
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 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
221 tBuilder.pushMpls()
222 .setMpls(MplsLabel.
223 mplsLabel(bucketId.label()));
224 }
225 //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,
236 getGroupKey(bucketId.
237 outGroup())) == null) {
238 throw new IllegalStateException();
239 }
240 GroupId indirectGroupId = groupService.
241 getGroup(deviceId,
242 getGroupKey(bucketId.
243 outGroup())).id();
244 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 Vavilapalli64505482015-04-21 13:04:13 -0700257 }*/
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700258
259 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
260 List<PolicyGroupParams> params) {
Sho SHIMIZU6ac2f4d2015-05-11 18:37:27 -0700261 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700262 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 SHIMIZUcc2a4ba2015-05-11 18:42:18 -0700277 int label = param.getLabelStack().get(idx);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700278 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 SHIMIZU84684a52015-05-11 08:39:24 -0700290 Collections.singletonList(param),
291 Collections.singletonList(bucketId));
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700292 previousGroupkey = key;
293 } else {
294 // Intermediate Groups
295 GroupBucketIdentifier bucketId =
296 new GroupBucketIdentifier(label,
297 previousGroupkey);
298 PolicyGroupIdentifier key = new
299 PolicyGroupIdentifier(id,
Sho SHIMIZU84684a52015-05-11 08:39:24 -0700300 Collections.singletonList(param),
301 Collections.singletonList(bucketId));
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700302 previousGroupkey = key;
303 }
304 }
305 }
306 } else {
307 int label = -1;
308 if (labelStackSize == 1) {
Sho SHIMIZUcc2a4ba2015-05-11 18:42:18 -0700309 label = param.getLabelStack().get(0);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700310 }
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
328 public void removeGroupChain(PolicyGroupIdentifier key) {
Sho SHIMIZU11ead6e2015-05-11 18:40:48 -0700329 checkArgument(key != null);
Sho SHIMIZU6ac2f4d2015-05-11 18:37:27 -0700330 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700331 groupsToBeDeleted.add(key);
332
333 Iterator<PolicyGroupIdentifier> it =
334 groupsToBeDeleted.iterator();
335
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());
342 }
343 }
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700344 /*groupService.removeGroup(deviceId,
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700345 getGroupKey(innerMostGroupKey),
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700346 appId);*/
347 //TODO: Use nextObjective APIs here
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700348 it.remove();
349 }
350 }
351
Sho SHIMIZU84684a52015-05-11 08:39:24 -0700352}