blob: e47a662599a1c8cf05f20874ab466c2689b5e078 [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
Charles Chanc42e84e2015-10-20 16:24:19 -070057 * @param nsNextObjStore NeighborSet next objective store map
58 * @param subnetNextObjStore subnet next objective store map
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080059 */
60 public PolicyGroupHandler(DeviceId deviceId,
61 ApplicationId appId,
62 DeviceProperties config,
63 LinkService linkService,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070064 FlowObjectiveService flowObjService,
Thomas Vachuska6cdbdd82015-05-15 09:10:58 -070065 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
Charles Chanc42e84e2015-10-20 16:24:19 -070066 Integer> nsNextObjStore,
67 EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
68 Integer> subnetNextObjStore) {
69 super(deviceId, appId, config, linkService, flowObjService,
70 nsNextObjStore, subnetNextObjStore);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080071 }
72
73 public PolicyGroupIdentifier createPolicyGroupChain(String id,
74 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -070075 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080076 for (PolicyGroupParams param: params) {
77 List<PortNumber> ports = param.getPorts();
78 if (ports == null) {
79 log.warn("createPolicyGroupChain in sw {} with wrong "
80 + "input parameters", deviceId);
81 return null;
82 }
83
84 int labelStackSize = (param.getLabelStack() != null) ?
85 param.getLabelStack().size() : 0;
86
87 if (labelStackSize > 1) {
88 for (PortNumber sp : ports) {
89 PolicyGroupIdentifier previousGroupkey = null;
90 DeviceId neighbor = portDeviceMap.get(sp);
91 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -070092 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080093 if (idx == (labelStackSize - 1)) {
94 // Innermost Group
95 GroupBucketIdentifier bucketId =
96 new GroupBucketIdentifier(label,
97 previousGroupkey);
98 bucketIds.add(bucketId);
99 } else if (idx == 0) {
100 // Outermost Group
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700101 List<GroupBucket> outBuckets = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800102 GroupBucketIdentifier bucketId =
103 new GroupBucketIdentifier(label, sp);
104 PolicyGroupIdentifier key = new
105 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700106 Collections.singletonList(param),
107 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800108 TrafficTreatment.Builder tBuilder =
109 DefaultTrafficTreatment.builder();
110 tBuilder.setOutput(sp)
111 .setEthDst(deviceConfig.
112 getDeviceMac(neighbor))
113 .setEthSrc(nodeMacAddr)
114 .pushMpls()
sangho32a59322015-02-17 12:07:41 -0800115 .setMpls(MplsLabel.mplsLabel(label));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700116 /*outBuckets.add(DefaultGroupBucket.
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800117 createSelectGroupBucket(tBuilder.build()));
118 GroupDescription desc = new
119 DefaultGroupDescription(deviceId,
120 GroupDescription.Type.INDIRECT,
121 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700122 //TODO: BoS*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800123 previousGroupkey = key;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700124 //groupService.addGroup(desc);
125 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800126 } else {
127 // Intermediate Groups
128 GroupBucketIdentifier bucketId =
129 new GroupBucketIdentifier(label,
130 previousGroupkey);
131 PolicyGroupIdentifier key = new
132 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700133 Collections.singletonList(param),
134 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800135 // Add to group dependency list
136 dependentGroups.put(previousGroupkey, key);
137 previousGroupkey = key;
138 }
139 }
140 }
141 } else {
142 int label = -1;
143 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700144 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800145 }
146 for (PortNumber sp : ports) {
147 GroupBucketIdentifier bucketId =
148 new GroupBucketIdentifier(label, sp);
149 bucketIds.add(bucketId);
150 }
151 }
152 }
153 PolicyGroupIdentifier innermostGroupkey = null;
154 if (!bucketIds.isEmpty()) {
155 innermostGroupkey = new
156 PolicyGroupIdentifier(id,
157 params,
158 bucketIds);
159 // Add to group dependency list
160 boolean fullyResolved = true;
161 for (GroupBucketIdentifier bucketId:bucketIds) {
162 if (bucketId.type() == BucketOutputType.GROUP) {
163 dependentGroups.put(bucketId.outGroup(),
164 innermostGroupkey);
165 fullyResolved = false;
166 }
167 }
168
169 if (fullyResolved) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700170 List<GroupBucket> outBuckets = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800171 for (GroupBucketIdentifier bucketId:bucketIds) {
172 DeviceId neighbor = portDeviceMap.
173 get(bucketId.outPort());
174 TrafficTreatment.Builder tBuilder =
175 DefaultTrafficTreatment.builder();
176 tBuilder.setOutput(bucketId.outPort())
177 .setEthDst(deviceConfig.
178 getDeviceMac(neighbor))
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700179 .setEthSrc(nodeMacAddr);
180 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
181 tBuilder.pushMpls()
sangho32a59322015-02-17 12:07:41 -0800182 .setMpls(MplsLabel.mplsLabel(bucketId.label()));
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700183 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800184 //TODO: BoS
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700185 /*outBuckets.add(DefaultGroupBucket.
186 createSelectGroupBucket(tBuilder.build()));*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800187 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700188 /*GroupDescription desc = new
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800189 DefaultGroupDescription(deviceId,
190 GroupDescription.Type.SELECT,
191 new GroupBuckets(outBuckets));
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700192 groupService.addGroup(desc);*/
193 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800194 }
195 }
196 return innermostGroupkey;
197 }
198
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700199 //TODO: Use nextObjective APIs to handle the group chains
200 /*@Override
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800201 protected void handleGroupEvent(GroupEvent event) {
202 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
203 if (dependentGroups.get(event.subject().appCookie()) != null) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700204 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800205 dependentGroups.remove(event.subject().appCookie());
206 boolean fullyResolved = true;
207 for (GroupBucketIdentifier bucketId:
208 dependentGroupKey.bucketIds()) {
209 if (bucketId.type() != BucketOutputType.GROUP) {
210 continue;
211 }
212 if (dependentGroups.containsKey(bucketId.outGroup())) {
213 fullyResolved = false;
214 break;
215 }
216 }
217
218 if (fullyResolved) {
219 List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
220 for (GroupBucketIdentifier bucketId:
221 dependentGroupKey.bucketIds()) {
222 TrafficTreatment.Builder tBuilder =
223 DefaultTrafficTreatment.builder();
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700224 if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
225 tBuilder.pushMpls()
226 .setMpls(MplsLabel.
227 mplsLabel(bucketId.label()));
228 }
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800229 //TODO: BoS
230 if (bucketId.type() == BucketOutputType.PORT) {
231 DeviceId neighbor = portDeviceMap.
232 get(bucketId.outPort());
233 tBuilder.setOutput(bucketId.outPort())
234 .setEthDst(deviceConfig.
235 getDeviceMac(neighbor))
236 .setEthSrc(nodeMacAddr);
237 } else {
238 if (groupService.
239 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700240 getGroupKey(bucketId.
241 outGroup())) == null) {
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800242 throw new IllegalStateException();
243 }
244 GroupId indirectGroupId = groupService.
245 getGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700246 getGroupKey(bucketId.
247 outGroup())).id();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800248 tBuilder.group(indirectGroupId);
249 }
250 outBuckets.add(DefaultGroupBucket.
251 createSelectGroupBucket(tBuilder.build()));
252 }
253 GroupDescription desc = new
254 DefaultGroupDescription(deviceId,
255 GroupDescription.Type.SELECT,
256 new GroupBuckets(outBuckets));
257 groupService.addGroup(desc);
258 }
259 }
260 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700261 }*/
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800262
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700263 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800264 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700265 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800266 for (PolicyGroupParams param: params) {
267 List<PortNumber> ports = param.getPorts();
268 if (ports == null) {
269 log.warn("generateGroupKey in sw {} with wrong "
270 + "input parameters", deviceId);
271 return null;
272 }
273
274 int labelStackSize = (param.getLabelStack() != null)
275 ? param.getLabelStack().size() : 0;
276
277 if (labelStackSize > 1) {
278 for (PortNumber sp : ports) {
279 PolicyGroupIdentifier previousGroupkey = null;
280 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700281 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800282 if (idx == (labelStackSize - 1)) {
283 // Innermost Group
284 GroupBucketIdentifier bucketId =
285 new GroupBucketIdentifier(label,
286 previousGroupkey);
287 bucketIds.add(bucketId);
288 } else if (idx == 0) {
289 // Outermost Group
290 GroupBucketIdentifier bucketId =
291 new GroupBucketIdentifier(label, sp);
292 PolicyGroupIdentifier key = new
293 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700294 Collections.singletonList(param),
295 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800296 previousGroupkey = key;
297 } else {
298 // Intermediate Groups
299 GroupBucketIdentifier bucketId =
300 new GroupBucketIdentifier(label,
301 previousGroupkey);
302 PolicyGroupIdentifier key = new
303 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700304 Collections.singletonList(param),
305 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800306 previousGroupkey = key;
307 }
308 }
309 }
310 } else {
311 int label = -1;
312 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700313 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800314 }
315 for (PortNumber sp : ports) {
316 GroupBucketIdentifier bucketId =
317 new GroupBucketIdentifier(label, sp);
318 bucketIds.add(bucketId);
319 }
320 }
321 }
322 PolicyGroupIdentifier innermostGroupkey = null;
323 if (!bucketIds.isEmpty()) {
324 innermostGroupkey = new
325 PolicyGroupIdentifier(id,
326 params,
327 bucketIds);
328 }
329 return innermostGroupkey;
330 }
331
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700332 public void removeGroupChain(PolicyGroupIdentifier key) {
Sho SHIMIZU24deb902015-05-11 18:40:48 -0700333 checkArgument(key != null);
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700334 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800335 groupsToBeDeleted.add(key);
336
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700337 Iterator<PolicyGroupIdentifier> it =
338 groupsToBeDeleted.iterator();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800339
340 while (it.hasNext()) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700341 PolicyGroupIdentifier innerMostGroupKey = it.next();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800342 for (GroupBucketIdentifier bucketId:
343 innerMostGroupKey.bucketIds()) {
344 if (bucketId.type() != BucketOutputType.GROUP) {
345 groupsToBeDeleted.add(bucketId.outGroup());
346 }
347 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700348 /*groupService.removeGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700349 getGroupKey(innerMostGroupKey),
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700350 appId);*/
351 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800352 it.remove();
353 }
354 }
355
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700356}