blob: 4b0d518c14451617ababed1bfb55b175df9b527e [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
Charles Chan0b4e6182015-11-03 10:42:14 -080027import org.onlab.packet.MacAddress;
sangho32a59322015-02-17 12:07:41 -080028import org.onlab.packet.MplsLabel;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080029import org.onosproject.core.ApplicationId;
Charles Chan188ebf52015-12-23 00:15:11 -080030import org.onosproject.segmentrouting.SegmentRoutingManager;
Charles Chan0b4e6182015-11-03 10:42:14 -080031import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
32import org.onosproject.segmentrouting.config.DeviceProperties;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070033import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070034import org.onosproject.store.service.EventuallyConsistentMap;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080035import org.onosproject.net.DeviceId;
36import org.onosproject.net.PortNumber;
37import org.onosproject.net.flow.DefaultTrafficTreatment;
38import org.onosproject.net.flow.TrafficTreatment;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070039import org.onosproject.net.flowobjective.FlowObjectiveService;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080040import org.onosproject.net.group.GroupBucket;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080041import 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());
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -070051 private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080052
53 /**
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070054 * Policy group handler constructor.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080055 *
56 * @param deviceId device identifier
57 * @param appId application identifier
58 * @param config interface to retrieve the device properties
59 * @param linkService link service object
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070060 * @param flowObjService flow objective service object
Charles Chanc42e84e2015-10-20 16:24:19 -070061 * @param nsNextObjStore NeighborSet next objective store map
62 * @param subnetNextObjStore subnet next objective store map
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080063 */
Charles Chan188ebf52015-12-23 00:15:11 -080064 // TODO Access stores through srManager
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080065 public PolicyGroupHandler(DeviceId deviceId,
66 ApplicationId appId,
67 DeviceProperties config,
68 LinkService linkService,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070069 FlowObjectiveService flowObjService,
Thomas Vachuska6cdbdd82015-05-15 09:10:58 -070070 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
Charles Chanc42e84e2015-10-20 16:24:19 -070071 Integer> nsNextObjStore,
72 EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
Saurav Das4ce45962015-11-24 23:21:05 -080073 Integer> subnetNextObjStore,
74 EventuallyConsistentMap<PortNextObjectiveStoreKey,
Charles Chan188ebf52015-12-23 00:15:11 -080075 Integer> portNextObjStore,
76 SegmentRoutingManager srManager) {
Charles Chanc42e84e2015-10-20 16:24:19 -070077 super(deviceId, appId, config, linkService, flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -080078 nsNextObjStore, subnetNextObjStore, portNextObjStore, srManager);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080079 }
80
81 public PolicyGroupIdentifier createPolicyGroupChain(String id,
82 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -070083 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080084 for (PolicyGroupParams param: params) {
85 List<PortNumber> ports = param.getPorts();
86 if (ports == null) {
87 log.warn("createPolicyGroupChain in sw {} with wrong "
88 + "input parameters", deviceId);
89 return null;
90 }
91
92 int labelStackSize = (param.getLabelStack() != null) ?
93 param.getLabelStack().size() : 0;
94
95 if (labelStackSize > 1) {
96 for (PortNumber sp : ports) {
97 PolicyGroupIdentifier previousGroupkey = null;
98 DeviceId neighbor = portDeviceMap.get(sp);
99 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700100 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800101 if (idx == (labelStackSize - 1)) {
102 // Innermost Group
103 GroupBucketIdentifier bucketId =
104 new GroupBucketIdentifier(label,
105 previousGroupkey);
106 bucketIds.add(bucketId);
107 } else if (idx == 0) {
108 // Outermost Group
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700109 List<GroupBucket> outBuckets = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800110 GroupBucketIdentifier bucketId =
111 new GroupBucketIdentifier(label, sp);
112 PolicyGroupIdentifier key = new
113 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700114 Collections.singletonList(param),
115 Collections.singletonList(bucketId));
Charles Chan0b4e6182015-11-03 10:42:14 -0800116 MacAddress neighborEthDst;
117 try {
118 neighborEthDst = deviceConfig.getDeviceMac(neighbor);
119 } catch (DeviceConfigNotFoundException e) {
120 log.warn(e.getMessage()
121 + " Skipping createPolicyGroupChain for this label.");
122 continue;
123 }
124
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800125 TrafficTreatment.Builder tBuilder =
126 DefaultTrafficTreatment.builder();
127 tBuilder.setOutput(sp)
Charles Chan0b4e6182015-11-03 10:42:14 -0800128 .setEthDst(neighborEthDst)
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800129 .setEthSrc(nodeMacAddr)
130 .pushMpls()
sangho32a59322015-02-17 12:07:41 -0800131 .setMpls(MplsLabel.mplsLabel(label));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700132 /*outBuckets.add(DefaultGroupBucket.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800133 createSelectGroupBucket(tBuilder.build()));
134 GroupDescription desc = new
135 DefaultGroupDescription(deviceId,
136 GroupDescription.Type.INDIRECT,
137 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700138 //TODO: BoS*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800139 previousGroupkey = key;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700140 //groupService.addGroup(desc);
141 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800142 } else {
143 // Intermediate Groups
144 GroupBucketIdentifier bucketId =
145 new GroupBucketIdentifier(label,
146 previousGroupkey);
147 PolicyGroupIdentifier key = new
148 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700149 Collections.singletonList(param),
150 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800151 // Add to group dependency list
152 dependentGroups.put(previousGroupkey, key);
153 previousGroupkey = key;
154 }
155 }
156 }
157 } else {
158 int label = -1;
159 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700160 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800161 }
162 for (PortNumber sp : ports) {
163 GroupBucketIdentifier bucketId =
164 new GroupBucketIdentifier(label, sp);
165 bucketIds.add(bucketId);
166 }
167 }
168 }
169 PolicyGroupIdentifier innermostGroupkey = null;
170 if (!bucketIds.isEmpty()) {
171 innermostGroupkey = new
172 PolicyGroupIdentifier(id,
173 params,
174 bucketIds);
175 // Add to group dependency list
176 boolean fullyResolved = true;
177 for (GroupBucketIdentifier bucketId:bucketIds) {
178 if (bucketId.type() == BucketOutputType.GROUP) {
179 dependentGroups.put(bucketId.outGroup(),
180 innermostGroupkey);
181 fullyResolved = false;
182 }
183 }
184
185 if (fullyResolved) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700186 List<GroupBucket> outBuckets = new ArrayList<>();
Charles Chan0b4e6182015-11-03 10:42:14 -0800187 for (GroupBucketIdentifier bucketId : bucketIds) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800188 DeviceId neighbor = portDeviceMap.
189 get(bucketId.outPort());
Charles Chan0b4e6182015-11-03 10:42:14 -0800190
191 MacAddress neighborEthDst;
192 try {
193 neighborEthDst = deviceConfig.getDeviceMac(neighbor);
194 } catch (DeviceConfigNotFoundException e) {
195 log.warn(e.getMessage()
196 + " Skipping createPolicyGroupChain for this bucketId.");
197 continue;
198 }
199
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800200 TrafficTreatment.Builder tBuilder =
201 DefaultTrafficTreatment.builder();
202 tBuilder.setOutput(bucketId.outPort())
Charles Chan0b4e6182015-11-03 10:42:14 -0800203 .setEthDst(neighborEthDst)
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700204 .setEthSrc(nodeMacAddr);
205 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
206 tBuilder.pushMpls()
sangho32a59322015-02-17 12:07:41 -0800207 .setMpls(MplsLabel.mplsLabel(bucketId.label()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700208 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800209 //TODO: BoS
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700210 /*outBuckets.add(DefaultGroupBucket.
211 createSelectGroupBucket(tBuilder.build()));*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800212 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700213 /*GroupDescription desc = new
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800214 DefaultGroupDescription(deviceId,
215 GroupDescription.Type.SELECT,
216 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700217 groupService.addGroup(desc);*/
218 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800219 }
220 }
221 return innermostGroupkey;
222 }
223
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700224 //TODO: Use nextObjective APIs to handle the group chains
225 /*@Override
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800226 protected void handleGroupEvent(GroupEvent event) {
227 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
228 if (dependentGroups.get(event.subject().appCookie()) != null) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700229 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800230 dependentGroups.remove(event.subject().appCookie());
231 boolean fullyResolved = true;
232 for (GroupBucketIdentifier bucketId:
233 dependentGroupKey.bucketIds()) {
234 if (bucketId.type() != BucketOutputType.GROUP) {
235 continue;
236 }
237 if (dependentGroups.containsKey(bucketId.outGroup())) {
238 fullyResolved = false;
239 break;
240 }
241 }
242
243 if (fullyResolved) {
244 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
245 for (GroupBucketIdentifier bucketId:
246 dependentGroupKey.bucketIds()) {
247 TrafficTreatment.Builder tBuilder =
248 DefaultTrafficTreatment.builder();
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700249 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
250 tBuilder.pushMpls()
251 .setMpls(MplsLabel.
252 mplsLabel(bucketId.label()));
253 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800254 //TODO: BoS
255 if (bucketId.type() == BucketOutputType.PORT) {
256 DeviceId neighbor = portDeviceMap.
257 get(bucketId.outPort());
258 tBuilder.setOutput(bucketId.outPort())
259 .setEthDst(deviceConfig.
260 getDeviceMac(neighbor))
261 .setEthSrc(nodeMacAddr);
262 } else {
263 if (groupService.
264 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700265 getGroupKey(bucketId.
266 outGroup())) == null) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800267 throw new IllegalStateException();
268 }
269 GroupId indirectGroupId = groupService.
270 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700271 getGroupKey(bucketId.
272 outGroup())).id();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800273 tBuilder.group(indirectGroupId);
274 }
275 outBuckets.add(DefaultGroupBucket.
276 createSelectGroupBucket(tBuilder.build()));
277 }
278 GroupDescription desc = new
279 DefaultGroupDescription(deviceId,
280 GroupDescription.Type.SELECT,
281 new GroupBuckets(outBuckets));
282 groupService.addGroup(desc);
283 }
284 }
285 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700286 }*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800287
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700288 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800289 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700290 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800291 for (PolicyGroupParams param: params) {
292 List<PortNumber> ports = param.getPorts();
293 if (ports == null) {
294 log.warn("generateGroupKey in sw {} with wrong "
295 + "input parameters", deviceId);
296 return null;
297 }
298
299 int labelStackSize = (param.getLabelStack() != null)
300 ? param.getLabelStack().size() : 0;
301
302 if (labelStackSize > 1) {
303 for (PortNumber sp : ports) {
304 PolicyGroupIdentifier previousGroupkey = null;
305 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700306 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800307 if (idx == (labelStackSize - 1)) {
308 // Innermost Group
309 GroupBucketIdentifier bucketId =
310 new GroupBucketIdentifier(label,
311 previousGroupkey);
312 bucketIds.add(bucketId);
313 } else if (idx == 0) {
314 // Outermost Group
315 GroupBucketIdentifier bucketId =
316 new GroupBucketIdentifier(label, sp);
317 PolicyGroupIdentifier key = new
318 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700319 Collections.singletonList(param),
320 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800321 previousGroupkey = key;
322 } else {
323 // Intermediate Groups
324 GroupBucketIdentifier bucketId =
325 new GroupBucketIdentifier(label,
326 previousGroupkey);
327 PolicyGroupIdentifier key = new
328 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700329 Collections.singletonList(param),
330 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800331 previousGroupkey = key;
332 }
333 }
334 }
335 } else {
336 int label = -1;
337 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700338 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800339 }
340 for (PortNumber sp : ports) {
341 GroupBucketIdentifier bucketId =
342 new GroupBucketIdentifier(label, sp);
343 bucketIds.add(bucketId);
344 }
345 }
346 }
347 PolicyGroupIdentifier innermostGroupkey = null;
348 if (!bucketIds.isEmpty()) {
349 innermostGroupkey = new
350 PolicyGroupIdentifier(id,
351 params,
352 bucketIds);
353 }
354 return innermostGroupkey;
355 }
356
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700357 public void removeGroupChain(PolicyGroupIdentifier key) {
Sho SHIMIZU24deb902015-05-11 18:40:48 -0700358 checkArgument(key != null);
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700359 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800360 groupsToBeDeleted.add(key);
361
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700362 Iterator<PolicyGroupIdentifier> it =
363 groupsToBeDeleted.iterator();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800364
365 while (it.hasNext()) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700366 PolicyGroupIdentifier innerMostGroupKey = it.next();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800367 for (GroupBucketIdentifier bucketId:
368 innerMostGroupKey.bucketIds()) {
369 if (bucketId.type() != BucketOutputType.GROUP) {
370 groupsToBeDeleted.add(bucketId.outGroup());
371 }
372 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700373 /*groupService.removeGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700374 getGroupKey(innerMostGroupKey),
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700375 appId);*/
376 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800377 it.remove();
378 }
379 }
380
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700381}