blob: ef143dc7b945628d0f15bad8d4c20eb7d0221e4e [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 Chan0b4e6182015-11-03 10:42:14 -080030import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
31import org.onosproject.segmentrouting.config.DeviceProperties;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070032import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070033import org.onosproject.store.service.EventuallyConsistentMap;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080034import org.onosproject.net.DeviceId;
35import org.onosproject.net.PortNumber;
36import org.onosproject.net.flow.DefaultTrafficTreatment;
37import org.onosproject.net.flow.TrafficTreatment;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070038import org.onosproject.net.flowobjective.FlowObjectiveService;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080039import org.onosproject.net.group.GroupBucket;
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080040import org.onosproject.net.link.LinkService;
41import org.slf4j.Logger;
42
43/**
44 * A module to create group chains based on the specified device
45 * ports and label stack to be applied on each port.
46 */
47public class PolicyGroupHandler extends DefaultGroupHandler {
48
49 private final Logger log = getLogger(getClass());
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -070050 private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080051
52 /**
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070053 * Policy group handler constructor.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080054 *
55 * @param deviceId device identifier
56 * @param appId application identifier
57 * @param config interface to retrieve the device properties
58 * @param linkService link service object
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070059 * @param flowObjService flow objective service object
Charles Chanc42e84e2015-10-20 16:24:19 -070060 * @param nsNextObjStore NeighborSet next objective store map
61 * @param subnetNextObjStore subnet next objective store map
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080062 */
63 public PolicyGroupHandler(DeviceId deviceId,
64 ApplicationId appId,
65 DeviceProperties config,
66 LinkService linkService,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070067 FlowObjectiveService flowObjService,
Thomas Vachuska6cdbdd82015-05-15 09:10:58 -070068 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
Charles Chanc42e84e2015-10-20 16:24:19 -070069 Integer> nsNextObjStore,
70 EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
Saurav Das4ce45962015-11-24 23:21:05 -080071 Integer> subnetNextObjStore,
72 EventuallyConsistentMap<PortNextObjectiveStoreKey,
73 Integer> portNextObjStore) {
Charles Chanc42e84e2015-10-20 16:24:19 -070074 super(deviceId, appId, config, linkService, flowObjService,
Saurav Das4ce45962015-11-24 23:21:05 -080075 nsNextObjStore, subnetNextObjStore, portNextObjStore);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080076 }
77
78 public PolicyGroupIdentifier createPolicyGroupChain(String id,
79 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -070080 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080081 for (PolicyGroupParams param: params) {
82 List<PortNumber> ports = param.getPorts();
83 if (ports == null) {
84 log.warn("createPolicyGroupChain in sw {} with wrong "
85 + "input parameters", deviceId);
86 return null;
87 }
88
89 int labelStackSize = (param.getLabelStack() != null) ?
90 param.getLabelStack().size() : 0;
91
92 if (labelStackSize > 1) {
93 for (PortNumber sp : ports) {
94 PolicyGroupIdentifier previousGroupkey = null;
95 DeviceId neighbor = portDeviceMap.get(sp);
96 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -070097 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080098 if (idx == (labelStackSize - 1)) {
99 // Innermost Group
100 GroupBucketIdentifier bucketId =
101 new GroupBucketIdentifier(label,
102 previousGroupkey);
103 bucketIds.add(bucketId);
104 } else if (idx == 0) {
105 // Outermost Group
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700106 List<GroupBucket> outBuckets = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800107 GroupBucketIdentifier bucketId =
108 new GroupBucketIdentifier(label, sp);
109 PolicyGroupIdentifier key = new
110 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700111 Collections.singletonList(param),
112 Collections.singletonList(bucketId));
Charles Chan0b4e6182015-11-03 10:42:14 -0800113 MacAddress neighborEthDst;
114 try {
115 neighborEthDst = deviceConfig.getDeviceMac(neighbor);
116 } catch (DeviceConfigNotFoundException e) {
117 log.warn(e.getMessage()
118 + " Skipping createPolicyGroupChain for this label.");
119 continue;
120 }
121
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800122 TrafficTreatment.Builder tBuilder =
123 DefaultTrafficTreatment.builder();
124 tBuilder.setOutput(sp)
Charles Chan0b4e6182015-11-03 10:42:14 -0800125 .setEthDst(neighborEthDst)
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800126 .setEthSrc(nodeMacAddr)
127 .pushMpls()
sangho32a59322015-02-17 12:07:41 -0800128 .setMpls(MplsLabel.mplsLabel(label));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700129 /*outBuckets.add(DefaultGroupBucket.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800130 createSelectGroupBucket(tBuilder.build()));
131 GroupDescription desc = new
132 DefaultGroupDescription(deviceId,
133 GroupDescription.Type.INDIRECT,
134 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700135 //TODO: BoS*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800136 previousGroupkey = key;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700137 //groupService.addGroup(desc);
138 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800139 } else {
140 // Intermediate Groups
141 GroupBucketIdentifier bucketId =
142 new GroupBucketIdentifier(label,
143 previousGroupkey);
144 PolicyGroupIdentifier key = new
145 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700146 Collections.singletonList(param),
147 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800148 // Add to group dependency list
149 dependentGroups.put(previousGroupkey, key);
150 previousGroupkey = key;
151 }
152 }
153 }
154 } else {
155 int label = -1;
156 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700157 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800158 }
159 for (PortNumber sp : ports) {
160 GroupBucketIdentifier bucketId =
161 new GroupBucketIdentifier(label, sp);
162 bucketIds.add(bucketId);
163 }
164 }
165 }
166 PolicyGroupIdentifier innermostGroupkey = null;
167 if (!bucketIds.isEmpty()) {
168 innermostGroupkey = new
169 PolicyGroupIdentifier(id,
170 params,
171 bucketIds);
172 // Add to group dependency list
173 boolean fullyResolved = true;
174 for (GroupBucketIdentifier bucketId:bucketIds) {
175 if (bucketId.type() == BucketOutputType.GROUP) {
176 dependentGroups.put(bucketId.outGroup(),
177 innermostGroupkey);
178 fullyResolved = false;
179 }
180 }
181
182 if (fullyResolved) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700183 List<GroupBucket> outBuckets = new ArrayList<>();
Charles Chan0b4e6182015-11-03 10:42:14 -0800184 for (GroupBucketIdentifier bucketId : bucketIds) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800185 DeviceId neighbor = portDeviceMap.
186 get(bucketId.outPort());
Charles Chan0b4e6182015-11-03 10:42:14 -0800187
188 MacAddress neighborEthDst;
189 try {
190 neighborEthDst = deviceConfig.getDeviceMac(neighbor);
191 } catch (DeviceConfigNotFoundException e) {
192 log.warn(e.getMessage()
193 + " Skipping createPolicyGroupChain for this bucketId.");
194 continue;
195 }
196
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800197 TrafficTreatment.Builder tBuilder =
198 DefaultTrafficTreatment.builder();
199 tBuilder.setOutput(bucketId.outPort())
Charles Chan0b4e6182015-11-03 10:42:14 -0800200 .setEthDst(neighborEthDst)
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700201 .setEthSrc(nodeMacAddr);
202 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
203 tBuilder.pushMpls()
sangho32a59322015-02-17 12:07:41 -0800204 .setMpls(MplsLabel.mplsLabel(bucketId.label()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700205 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800206 //TODO: BoS
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700207 /*outBuckets.add(DefaultGroupBucket.
208 createSelectGroupBucket(tBuilder.build()));*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800209 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700210 /*GroupDescription desc = new
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800211 DefaultGroupDescription(deviceId,
212 GroupDescription.Type.SELECT,
213 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700214 groupService.addGroup(desc);*/
215 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800216 }
217 }
218 return innermostGroupkey;
219 }
220
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700221 //TODO: Use nextObjective APIs to handle the group chains
222 /*@Override
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800223 protected void handleGroupEvent(GroupEvent event) {
224 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
225 if (dependentGroups.get(event.subject().appCookie()) != null) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700226 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800227 dependentGroups.remove(event.subject().appCookie());
228 boolean fullyResolved = true;
229 for (GroupBucketIdentifier bucketId:
230 dependentGroupKey.bucketIds()) {
231 if (bucketId.type() != BucketOutputType.GROUP) {
232 continue;
233 }
234 if (dependentGroups.containsKey(bucketId.outGroup())) {
235 fullyResolved = false;
236 break;
237 }
238 }
239
240 if (fullyResolved) {
241 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
242 for (GroupBucketIdentifier bucketId:
243 dependentGroupKey.bucketIds()) {
244 TrafficTreatment.Builder tBuilder =
245 DefaultTrafficTreatment.builder();
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700246 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
247 tBuilder.pushMpls()
248 .setMpls(MplsLabel.
249 mplsLabel(bucketId.label()));
250 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800251 //TODO: BoS
252 if (bucketId.type() == BucketOutputType.PORT) {
253 DeviceId neighbor = portDeviceMap.
254 get(bucketId.outPort());
255 tBuilder.setOutput(bucketId.outPort())
256 .setEthDst(deviceConfig.
257 getDeviceMac(neighbor))
258 .setEthSrc(nodeMacAddr);
259 } else {
260 if (groupService.
261 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700262 getGroupKey(bucketId.
263 outGroup())) == null) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800264 throw new IllegalStateException();
265 }
266 GroupId indirectGroupId = groupService.
267 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700268 getGroupKey(bucketId.
269 outGroup())).id();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800270 tBuilder.group(indirectGroupId);
271 }
272 outBuckets.add(DefaultGroupBucket.
273 createSelectGroupBucket(tBuilder.build()));
274 }
275 GroupDescription desc = new
276 DefaultGroupDescription(deviceId,
277 GroupDescription.Type.SELECT,
278 new GroupBuckets(outBuckets));
279 groupService.addGroup(desc);
280 }
281 }
282 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700283 }*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800284
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700285 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800286 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700287 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800288 for (PolicyGroupParams param: params) {
289 List<PortNumber> ports = param.getPorts();
290 if (ports == null) {
291 log.warn("generateGroupKey in sw {} with wrong "
292 + "input parameters", deviceId);
293 return null;
294 }
295
296 int labelStackSize = (param.getLabelStack() != null)
297 ? param.getLabelStack().size() : 0;
298
299 if (labelStackSize > 1) {
300 for (PortNumber sp : ports) {
301 PolicyGroupIdentifier previousGroupkey = null;
302 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700303 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800304 if (idx == (labelStackSize - 1)) {
305 // Innermost Group
306 GroupBucketIdentifier bucketId =
307 new GroupBucketIdentifier(label,
308 previousGroupkey);
309 bucketIds.add(bucketId);
310 } else if (idx == 0) {
311 // Outermost Group
312 GroupBucketIdentifier bucketId =
313 new GroupBucketIdentifier(label, sp);
314 PolicyGroupIdentifier key = new
315 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700316 Collections.singletonList(param),
317 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800318 previousGroupkey = key;
319 } else {
320 // Intermediate Groups
321 GroupBucketIdentifier bucketId =
322 new GroupBucketIdentifier(label,
323 previousGroupkey);
324 PolicyGroupIdentifier key = new
325 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700326 Collections.singletonList(param),
327 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800328 previousGroupkey = key;
329 }
330 }
331 }
332 } else {
333 int label = -1;
334 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700335 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800336 }
337 for (PortNumber sp : ports) {
338 GroupBucketIdentifier bucketId =
339 new GroupBucketIdentifier(label, sp);
340 bucketIds.add(bucketId);
341 }
342 }
343 }
344 PolicyGroupIdentifier innermostGroupkey = null;
345 if (!bucketIds.isEmpty()) {
346 innermostGroupkey = new
347 PolicyGroupIdentifier(id,
348 params,
349 bucketIds);
350 }
351 return innermostGroupkey;
352 }
353
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700354 public void removeGroupChain(PolicyGroupIdentifier key) {
Sho SHIMIZU24deb902015-05-11 18:40:48 -0700355 checkArgument(key != null);
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700356 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800357 groupsToBeDeleted.add(key);
358
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700359 Iterator<PolicyGroupIdentifier> it =
360 groupsToBeDeleted.iterator();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800361
362 while (it.hasNext()) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700363 PolicyGroupIdentifier innerMostGroupKey = it.next();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800364 for (GroupBucketIdentifier bucketId:
365 innerMostGroupKey.bucketIds()) {
366 if (bucketId.type() != BucketOutputType.GROUP) {
367 groupsToBeDeleted.add(bucketId.outGroup());
368 }
369 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700370 /*groupService.removeGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700371 getGroupKey(innerMostGroupKey),
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700372 appId);*/
373 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800374 it.remove();
375 }
376 }
377
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700378}