blob: 55142078255ba050704f17b9618695cb822ff8a3 [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,
71 Integer> subnetNextObjStore) {
72 super(deviceId, appId, config, linkService, flowObjService,
73 nsNextObjStore, subnetNextObjStore);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080074 }
75
76 public PolicyGroupIdentifier createPolicyGroupChain(String id,
77 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -070078 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080079 for (PolicyGroupParams param: params) {
80 List<PortNumber> ports = param.getPorts();
81 if (ports == null) {
82 log.warn("createPolicyGroupChain in sw {} with wrong "
83 + "input parameters", deviceId);
84 return null;
85 }
86
87 int labelStackSize = (param.getLabelStack() != null) ?
88 param.getLabelStack().size() : 0;
89
90 if (labelStackSize > 1) {
91 for (PortNumber sp : ports) {
92 PolicyGroupIdentifier previousGroupkey = null;
93 DeviceId neighbor = portDeviceMap.get(sp);
94 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -070095 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080096 if (idx == (labelStackSize - 1)) {
97 // Innermost Group
98 GroupBucketIdentifier bucketId =
99 new GroupBucketIdentifier(label,
100 previousGroupkey);
101 bucketIds.add(bucketId);
102 } else if (idx == 0) {
103 // Outermost Group
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700104 List<GroupBucket> outBuckets = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800105 GroupBucketIdentifier bucketId =
106 new GroupBucketIdentifier(label, sp);
107 PolicyGroupIdentifier key = new
108 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700109 Collections.singletonList(param),
110 Collections.singletonList(bucketId));
Charles Chan0b4e6182015-11-03 10:42:14 -0800111 MacAddress neighborEthDst;
112 try {
113 neighborEthDst = deviceConfig.getDeviceMac(neighbor);
114 } catch (DeviceConfigNotFoundException e) {
115 log.warn(e.getMessage()
116 + " Skipping createPolicyGroupChain for this label.");
117 continue;
118 }
119
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800120 TrafficTreatment.Builder tBuilder =
121 DefaultTrafficTreatment.builder();
122 tBuilder.setOutput(sp)
Charles Chan0b4e6182015-11-03 10:42:14 -0800123 .setEthDst(neighborEthDst)
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800124 .setEthSrc(nodeMacAddr)
125 .pushMpls()
sangho32a59322015-02-17 12:07:41 -0800126 .setMpls(MplsLabel.mplsLabel(label));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700127 /*outBuckets.add(DefaultGroupBucket.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800128 createSelectGroupBucket(tBuilder.build()));
129 GroupDescription desc = new
130 DefaultGroupDescription(deviceId,
131 GroupDescription.Type.INDIRECT,
132 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700133 //TODO: BoS*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800134 previousGroupkey = key;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700135 //groupService.addGroup(desc);
136 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800137 } else {
138 // Intermediate Groups
139 GroupBucketIdentifier bucketId =
140 new GroupBucketIdentifier(label,
141 previousGroupkey);
142 PolicyGroupIdentifier key = new
143 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700144 Collections.singletonList(param),
145 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800146 // Add to group dependency list
147 dependentGroups.put(previousGroupkey, key);
148 previousGroupkey = key;
149 }
150 }
151 }
152 } else {
153 int label = -1;
154 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700155 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800156 }
157 for (PortNumber sp : ports) {
158 GroupBucketIdentifier bucketId =
159 new GroupBucketIdentifier(label, sp);
160 bucketIds.add(bucketId);
161 }
162 }
163 }
164 PolicyGroupIdentifier innermostGroupkey = null;
165 if (!bucketIds.isEmpty()) {
166 innermostGroupkey = new
167 PolicyGroupIdentifier(id,
168 params,
169 bucketIds);
170 // Add to group dependency list
171 boolean fullyResolved = true;
172 for (GroupBucketIdentifier bucketId:bucketIds) {
173 if (bucketId.type() == BucketOutputType.GROUP) {
174 dependentGroups.put(bucketId.outGroup(),
175 innermostGroupkey);
176 fullyResolved = false;
177 }
178 }
179
180 if (fullyResolved) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700181 List<GroupBucket> outBuckets = new ArrayList<>();
Charles Chan0b4e6182015-11-03 10:42:14 -0800182 for (GroupBucketIdentifier bucketId : bucketIds) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800183 DeviceId neighbor = portDeviceMap.
184 get(bucketId.outPort());
Charles Chan0b4e6182015-11-03 10:42:14 -0800185
186 MacAddress neighborEthDst;
187 try {
188 neighborEthDst = deviceConfig.getDeviceMac(neighbor);
189 } catch (DeviceConfigNotFoundException e) {
190 log.warn(e.getMessage()
191 + " Skipping createPolicyGroupChain for this bucketId.");
192 continue;
193 }
194
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800195 TrafficTreatment.Builder tBuilder =
196 DefaultTrafficTreatment.builder();
197 tBuilder.setOutput(bucketId.outPort())
Charles Chan0b4e6182015-11-03 10:42:14 -0800198 .setEthDst(neighborEthDst)
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700199 .setEthSrc(nodeMacAddr);
200 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
201 tBuilder.pushMpls()
sangho32a59322015-02-17 12:07:41 -0800202 .setMpls(MplsLabel.mplsLabel(bucketId.label()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700203 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800204 //TODO: BoS
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700205 /*outBuckets.add(DefaultGroupBucket.
206 createSelectGroupBucket(tBuilder.build()));*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800207 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700208 /*GroupDescription desc = new
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800209 DefaultGroupDescription(deviceId,
210 GroupDescription.Type.SELECT,
211 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700212 groupService.addGroup(desc);*/
213 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800214 }
215 }
216 return innermostGroupkey;
217 }
218
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700219 //TODO: Use nextObjective APIs to handle the group chains
220 /*@Override
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800221 protected void handleGroupEvent(GroupEvent event) {
222 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
223 if (dependentGroups.get(event.subject().appCookie()) != null) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700224 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800225 dependentGroups.remove(event.subject().appCookie());
226 boolean fullyResolved = true;
227 for (GroupBucketIdentifier bucketId:
228 dependentGroupKey.bucketIds()) {
229 if (bucketId.type() != BucketOutputType.GROUP) {
230 continue;
231 }
232 if (dependentGroups.containsKey(bucketId.outGroup())) {
233 fullyResolved = false;
234 break;
235 }
236 }
237
238 if (fullyResolved) {
239 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
240 for (GroupBucketIdentifier bucketId:
241 dependentGroupKey.bucketIds()) {
242 TrafficTreatment.Builder tBuilder =
243 DefaultTrafficTreatment.builder();
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700244 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
245 tBuilder.pushMpls()
246 .setMpls(MplsLabel.
247 mplsLabel(bucketId.label()));
248 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800249 //TODO: BoS
250 if (bucketId.type() == BucketOutputType.PORT) {
251 DeviceId neighbor = portDeviceMap.
252 get(bucketId.outPort());
253 tBuilder.setOutput(bucketId.outPort())
254 .setEthDst(deviceConfig.
255 getDeviceMac(neighbor))
256 .setEthSrc(nodeMacAddr);
257 } else {
258 if (groupService.
259 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700260 getGroupKey(bucketId.
261 outGroup())) == null) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800262 throw new IllegalStateException();
263 }
264 GroupId indirectGroupId = groupService.
265 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700266 getGroupKey(bucketId.
267 outGroup())).id();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800268 tBuilder.group(indirectGroupId);
269 }
270 outBuckets.add(DefaultGroupBucket.
271 createSelectGroupBucket(tBuilder.build()));
272 }
273 GroupDescription desc = new
274 DefaultGroupDescription(deviceId,
275 GroupDescription.Type.SELECT,
276 new GroupBuckets(outBuckets));
277 groupService.addGroup(desc);
278 }
279 }
280 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700281 }*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800282
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700283 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800284 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700285 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800286 for (PolicyGroupParams param: params) {
287 List<PortNumber> ports = param.getPorts();
288 if (ports == null) {
289 log.warn("generateGroupKey in sw {} with wrong "
290 + "input parameters", deviceId);
291 return null;
292 }
293
294 int labelStackSize = (param.getLabelStack() != null)
295 ? param.getLabelStack().size() : 0;
296
297 if (labelStackSize > 1) {
298 for (PortNumber sp : ports) {
299 PolicyGroupIdentifier previousGroupkey = null;
300 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700301 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800302 if (idx == (labelStackSize - 1)) {
303 // Innermost Group
304 GroupBucketIdentifier bucketId =
305 new GroupBucketIdentifier(label,
306 previousGroupkey);
307 bucketIds.add(bucketId);
308 } else if (idx == 0) {
309 // Outermost Group
310 GroupBucketIdentifier bucketId =
311 new GroupBucketIdentifier(label, sp);
312 PolicyGroupIdentifier key = new
313 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700314 Collections.singletonList(param),
315 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800316 previousGroupkey = key;
317 } else {
318 // Intermediate Groups
319 GroupBucketIdentifier bucketId =
320 new GroupBucketIdentifier(label,
321 previousGroupkey);
322 PolicyGroupIdentifier key = new
323 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700324 Collections.singletonList(param),
325 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800326 previousGroupkey = key;
327 }
328 }
329 }
330 } else {
331 int label = -1;
332 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700333 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800334 }
335 for (PortNumber sp : ports) {
336 GroupBucketIdentifier bucketId =
337 new GroupBucketIdentifier(label, sp);
338 bucketIds.add(bucketId);
339 }
340 }
341 }
342 PolicyGroupIdentifier innermostGroupkey = null;
343 if (!bucketIds.isEmpty()) {
344 innermostGroupkey = new
345 PolicyGroupIdentifier(id,
346 params,
347 bucketIds);
348 }
349 return innermostGroupkey;
350 }
351
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700352 public void removeGroupChain(PolicyGroupIdentifier key) {
Sho SHIMIZU24deb902015-05-11 18:40:48 -0700353 checkArgument(key != null);
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700354 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800355 groupsToBeDeleted.add(key);
356
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700357 Iterator<PolicyGroupIdentifier> it =
358 groupsToBeDeleted.iterator();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800359
360 while (it.hasNext()) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700361 PolicyGroupIdentifier innerMostGroupKey = it.next();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800362 for (GroupBucketIdentifier bucketId:
363 innerMostGroupKey.bucketIds()) {
364 if (bucketId.type() != BucketOutputType.GROUP) {
365 groupsToBeDeleted.add(bucketId.outGroup());
366 }
367 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700368 /*groupService.removeGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700369 getGroupKey(innerMostGroupKey),
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700370 appId);*/
371 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800372 it.remove();
373 }
374 }
375
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700376}