blob: 2ba7c19def6781aa98e1e4ce5816fa5c83b505d9 [file] [log] [blame]
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -08003 *
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 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 /**
Charles Chane849c192016-01-11 18:28:54 -080053 * Constructs policy group handler.
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 Chane849c192016-01-11 18:28:54 -080060 * @param srManager segment routing manager
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080061 */
62 public PolicyGroupHandler(DeviceId deviceId,
63 ApplicationId appId,
64 DeviceProperties config,
65 LinkService linkService,
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070066 FlowObjectiveService flowObjService,
Charles Chan188ebf52015-12-23 00:15:11 -080067 SegmentRoutingManager srManager) {
Charles Chane849c192016-01-11 18:28:54 -080068 super(deviceId, appId, config, linkService, flowObjService, srManager);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080069 }
70
Charles Chane849c192016-01-11 18:28:54 -080071 /**
72 * Creates policy group chain.
73 *
74 * @param id unique identifier associated with the policy group
75 * @param params a list of policy group params
76 * @return policy group identifier
77 */
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -080078 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
Charles Chane849c192016-01-11 18:28:54 -0800222 /*
223 @Override
224 protected void handleGroupEvent(GroupEvent event) {}
225 */
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800226
Charles Chane849c192016-01-11 18:28:54 -0800227 /**
228 * Generates policy group key.
229 *
230 * @param id unique identifier associated with the policy group
231 * @param params a list of policy group params
232 * @return policy group identifier
233 */
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700234 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800235 List<PolicyGroupParams> params) {
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700236 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800237 for (PolicyGroupParams param: params) {
238 List<PortNumber> ports = param.getPorts();
239 if (ports == null) {
240 log.warn("generateGroupKey in sw {} with wrong "
241 + "input parameters", deviceId);
242 return null;
243 }
244
245 int labelStackSize = (param.getLabelStack() != null)
246 ? param.getLabelStack().size() : 0;
247
248 if (labelStackSize > 1) {
249 for (PortNumber sp : ports) {
250 PolicyGroupIdentifier previousGroupkey = null;
251 for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700252 int label = param.getLabelStack().get(idx);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800253 if (idx == (labelStackSize - 1)) {
254 // Innermost Group
255 GroupBucketIdentifier bucketId =
256 new GroupBucketIdentifier(label,
257 previousGroupkey);
258 bucketIds.add(bucketId);
259 } else if (idx == 0) {
260 // Outermost Group
261 GroupBucketIdentifier bucketId =
262 new GroupBucketIdentifier(label, sp);
263 PolicyGroupIdentifier key = new
264 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700265 Collections.singletonList(param),
266 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800267 previousGroupkey = key;
268 } else {
269 // Intermediate Groups
270 GroupBucketIdentifier bucketId =
271 new GroupBucketIdentifier(label,
272 previousGroupkey);
273 PolicyGroupIdentifier key = new
274 PolicyGroupIdentifier(id,
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700275 Collections.singletonList(param),
276 Collections.singletonList(bucketId));
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800277 previousGroupkey = key;
278 }
279 }
280 }
281 } else {
282 int label = -1;
283 if (labelStackSize == 1) {
Sho SHIMIZUbaddcbe2015-05-11 18:42:18 -0700284 label = param.getLabelStack().get(0);
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800285 }
286 for (PortNumber sp : ports) {
287 GroupBucketIdentifier bucketId =
288 new GroupBucketIdentifier(label, sp);
289 bucketIds.add(bucketId);
290 }
291 }
292 }
293 PolicyGroupIdentifier innermostGroupkey = null;
294 if (!bucketIds.isEmpty()) {
295 innermostGroupkey = new
296 PolicyGroupIdentifier(id,
297 params,
298 bucketIds);
299 }
300 return innermostGroupkey;
301 }
302
Charles Chane849c192016-01-11 18:28:54 -0800303 /**
304 * Removes policy group chain.
305 *
306 * @param key policy group identifier
307 */
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700308 public void removeGroupChain(PolicyGroupIdentifier key) {
Sho SHIMIZU24deb902015-05-11 18:40:48 -0700309 checkArgument(key != null);
Sho SHIMIZU8b4b9f02015-05-11 18:37:27 -0700310 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800311 groupsToBeDeleted.add(key);
312
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700313 Iterator<PolicyGroupIdentifier> it =
314 groupsToBeDeleted.iterator();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800315
316 while (it.hasNext()) {
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700317 PolicyGroupIdentifier innerMostGroupKey = it.next();
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800318 for (GroupBucketIdentifier bucketId:
319 innerMostGroupKey.bucketIds()) {
320 if (bucketId.type() != BucketOutputType.GROUP) {
321 groupsToBeDeleted.add(bucketId.outGroup());
322 }
323 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700324 /*groupService.removeGroup(deviceId,
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700325 getGroupKey(innerMostGroupKey),
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700326 appId);*/
327 //TODO: Use nextObjective APIs here
Srikanth Vavilapallied12ae52015-02-09 14:43:19 -0800328 it.remove();
329 }
330 }
331
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700332}