e7e87839bf158e8caf2895c1b328b778ffe03239
[onosfw.git] /
1 /*
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  */
16 package org.onosproject.segmentrouting.grouphandler;
17
18 import static com.google.common.base.Preconditions.checkArgument;
19 import static org.slf4j.LoggerFactory.getLogger;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import org.onlab.packet.MplsLabel;
28 import org.onosproject.core.ApplicationId;
29 import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
30 import org.onosproject.store.service.EventuallyConsistentMap;
31 import org.onosproject.net.DeviceId;
32 import org.onosproject.net.PortNumber;
33 import org.onosproject.net.flow.DefaultTrafficTreatment;
34 import org.onosproject.net.flow.TrafficTreatment;
35 import org.onosproject.net.flowobjective.FlowObjectiveService;
36 import org.onosproject.net.group.GroupBucket;
37 import org.onosproject.net.link.LinkService;
38 import 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  */
44 public class PolicyGroupHandler extends DefaultGroupHandler {
45
46     private final Logger log = getLogger(getClass());
47     private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
48
49     /**
50      * Policy group handler constructor.
51      *
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
56      * @param flowObjService flow objective service object
57      * @param nsNextObjStore next objective store map
58      */
59     public PolicyGroupHandler(DeviceId deviceId,
60                               ApplicationId appId,
61                               DeviceProperties config,
62                               LinkService linkService,
63                               FlowObjectiveService flowObjService,
64                               EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
65                                       Integer> nsNextObjStore) {
66         super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore);
67     }
68
69     public PolicyGroupIdentifier createPolicyGroupChain(String id,
70                                                         List<PolicyGroupParams> params) {
71         List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
72         for (PolicyGroupParams param: params) {
73             List<PortNumber> ports = param.getPorts();
74             if (ports == null) {
75                 log.warn("createPolicyGroupChain in sw {} with wrong "
76                         + "input parameters", deviceId);
77                 return null;
78             }
79
80             int labelStackSize = (param.getLabelStack() != null) ?
81                                       param.getLabelStack().size() : 0;
82
83             if (labelStackSize > 1) {
84                 for (PortNumber sp : ports) {
85                     PolicyGroupIdentifier previousGroupkey = null;
86                     DeviceId neighbor = portDeviceMap.get(sp);
87                     for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
88                         int label = param.getLabelStack().get(idx);
89                         if (idx == (labelStackSize - 1)) {
90                             // Innermost Group
91                             GroupBucketIdentifier bucketId =
92                                     new GroupBucketIdentifier(label,
93                                                               previousGroupkey);
94                             bucketIds.add(bucketId);
95                         } else if (idx == 0) {
96                             // Outermost Group
97                             List<GroupBucket> outBuckets = new ArrayList<>();
98                             GroupBucketIdentifier bucketId =
99                                     new GroupBucketIdentifier(label, sp);
100                             PolicyGroupIdentifier key = new
101                                     PolicyGroupIdentifier(id,
102                                                           Collections.singletonList(param),
103                                                           Collections.singletonList(bucketId));
104                             TrafficTreatment.Builder tBuilder =
105                                     DefaultTrafficTreatment.builder();
106                             tBuilder.setOutput(sp)
107                                     .setEthDst(deviceConfig.
108                                                getDeviceMac(neighbor))
109                                     .setEthSrc(nodeMacAddr)
110                                     .pushMpls()
111                                     .setMpls(MplsLabel.mplsLabel(label));
112                             /*outBuckets.add(DefaultGroupBucket.
113                                            createSelectGroupBucket(tBuilder.build()));
114                             GroupDescription desc = new
115                                     DefaultGroupDescription(deviceId,
116                                                             GroupDescription.Type.INDIRECT,
117                                                             new GroupBuckets(outBuckets));
118                             //TODO: BoS*/
119                             previousGroupkey = key;
120                             //groupService.addGroup(desc);
121                             //TODO: Use nextObjective APIs here
122                         } else {
123                             // Intermediate Groups
124                             GroupBucketIdentifier bucketId =
125                                     new GroupBucketIdentifier(label,
126                                                               previousGroupkey);
127                             PolicyGroupIdentifier key = new
128                                     PolicyGroupIdentifier(id,
129                                                           Collections.singletonList(param),
130                                                           Collections.singletonList(bucketId));
131                             // Add to group dependency list
132                             dependentGroups.put(previousGroupkey, key);
133                             previousGroupkey = key;
134                         }
135                     }
136                 }
137             } else {
138                 int label = -1;
139                 if (labelStackSize == 1) {
140                     label = param.getLabelStack().get(0);
141                 }
142                 for (PortNumber sp : ports) {
143                     GroupBucketIdentifier bucketId =
144                             new GroupBucketIdentifier(label, sp);
145                     bucketIds.add(bucketId);
146                 }
147             }
148         }
149         PolicyGroupIdentifier innermostGroupkey = null;
150         if (!bucketIds.isEmpty()) {
151             innermostGroupkey = new
152                     PolicyGroupIdentifier(id,
153                                           params,
154                                           bucketIds);
155             // Add to group dependency list
156             boolean fullyResolved = true;
157             for (GroupBucketIdentifier bucketId:bucketIds) {
158                 if (bucketId.type() == BucketOutputType.GROUP) {
159                     dependentGroups.put(bucketId.outGroup(),
160                                         innermostGroupkey);
161                     fullyResolved = false;
162                 }
163             }
164
165             if (fullyResolved) {
166                 List<GroupBucket> outBuckets = new ArrayList<>();
167                 for (GroupBucketIdentifier bucketId:bucketIds) {
168                     DeviceId neighbor = portDeviceMap.
169                             get(bucketId.outPort());
170                     TrafficTreatment.Builder tBuilder =
171                             DefaultTrafficTreatment.builder();
172                     tBuilder.setOutput(bucketId.outPort())
173                             .setEthDst(deviceConfig.
174                                        getDeviceMac(neighbor))
175                             .setEthSrc(nodeMacAddr);
176                     if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
177                         tBuilder.pushMpls()
178                             .setMpls(MplsLabel.mplsLabel(bucketId.label()));
179                     }
180                     //TODO: BoS
181                     /*outBuckets.add(DefaultGroupBucket.
182                                    createSelectGroupBucket(tBuilder.build()));*/
183                 }
184                 /*GroupDescription desc = new
185                         DefaultGroupDescription(deviceId,
186                                                 GroupDescription.Type.SELECT,
187                                                 new GroupBuckets(outBuckets));
188                 groupService.addGroup(desc);*/
189                 //TODO: Use nextObjective APIs here
190             }
191         }
192         return innermostGroupkey;
193     }
194
195     //TODO: Use nextObjective APIs to handle the group chains
196     /*@Override
197     protected void handleGroupEvent(GroupEvent event) {
198         if (event.type() == GroupEvent.Type.GROUP_ADDED) {
199             if (dependentGroups.get(event.subject().appCookie()) != null) {
200                 PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
201                 dependentGroups.remove(event.subject().appCookie());
202                 boolean fullyResolved = true;
203                 for (GroupBucketIdentifier bucketId:
204                             dependentGroupKey.bucketIds()) {
205                     if (bucketId.type() != BucketOutputType.GROUP) {
206                         continue;
207                     }
208                     if (dependentGroups.containsKey(bucketId.outGroup())) {
209                         fullyResolved = false;
210                         break;
211                     }
212                 }
213
214                 if (fullyResolved) {
215                     List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
216                     for (GroupBucketIdentifier bucketId:
217                                 dependentGroupKey.bucketIds()) {
218                         TrafficTreatment.Builder tBuilder =
219                                 DefaultTrafficTreatment.builder();
220                         if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
221                             tBuilder.pushMpls()
222                                     .setMpls(MplsLabel.
223                                              mplsLabel(bucketId.label()));
224                         }
225                         //TODO: BoS
226                         if (bucketId.type() == BucketOutputType.PORT) {
227                             DeviceId neighbor = portDeviceMap.
228                                         get(bucketId.outPort());
229                             tBuilder.setOutput(bucketId.outPort())
230                                     .setEthDst(deviceConfig.
231                                                getDeviceMac(neighbor))
232                                      .setEthSrc(nodeMacAddr);
233                         } else {
234                             if (groupService.
235                                     getGroup(deviceId,
236                                              getGroupKey(bucketId.
237                                                        outGroup())) == null) {
238                                 throw new IllegalStateException();
239                             }
240                             GroupId indirectGroupId = groupService.
241                                     getGroup(deviceId,
242                                              getGroupKey(bucketId.
243                                                          outGroup())).id();
244                             tBuilder.group(indirectGroupId);
245                         }
246                         outBuckets.add(DefaultGroupBucket.
247                                        createSelectGroupBucket(tBuilder.build()));
248                     }
249                     GroupDescription desc = new
250                             DefaultGroupDescription(deviceId,
251                                                     GroupDescription.Type.SELECT,
252                                                     new GroupBuckets(outBuckets));
253                     groupService.addGroup(desc);
254                 }
255             }
256         }
257     }*/
258
259     public PolicyGroupIdentifier generatePolicyGroupKey(String id,
260                                    List<PolicyGroupParams> params) {
261         List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
262         for (PolicyGroupParams param: params) {
263             List<PortNumber> ports = param.getPorts();
264             if (ports == null) {
265                 log.warn("generateGroupKey in sw {} with wrong "
266                         + "input parameters", deviceId);
267                 return null;
268             }
269
270             int labelStackSize = (param.getLabelStack() != null)
271                     ? param.getLabelStack().size() : 0;
272
273             if (labelStackSize > 1) {
274                 for (PortNumber sp : ports) {
275                     PolicyGroupIdentifier previousGroupkey = null;
276                     for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
277                         int label = param.getLabelStack().get(idx);
278                         if (idx == (labelStackSize - 1)) {
279                             // Innermost Group
280                             GroupBucketIdentifier bucketId =
281                                     new GroupBucketIdentifier(label,
282                                                               previousGroupkey);
283                             bucketIds.add(bucketId);
284                         } else if (idx == 0) {
285                             // Outermost Group
286                             GroupBucketIdentifier bucketId =
287                                     new GroupBucketIdentifier(label, sp);
288                             PolicyGroupIdentifier key = new
289                                     PolicyGroupIdentifier(id,
290                                                           Collections.singletonList(param),
291                                                           Collections.singletonList(bucketId));
292                             previousGroupkey = key;
293                         } else {
294                             // Intermediate Groups
295                             GroupBucketIdentifier bucketId =
296                                     new GroupBucketIdentifier(label,
297                                                               previousGroupkey);
298                             PolicyGroupIdentifier key = new
299                                     PolicyGroupIdentifier(id,
300                                                           Collections.singletonList(param),
301                                                           Collections.singletonList(bucketId));
302                             previousGroupkey = key;
303                         }
304                     }
305                 }
306             } else {
307                 int label = -1;
308                 if (labelStackSize == 1) {
309                     label = param.getLabelStack().get(0);
310                 }
311                 for (PortNumber sp : ports) {
312                     GroupBucketIdentifier bucketId =
313                             new GroupBucketIdentifier(label, sp);
314                     bucketIds.add(bucketId);
315                 }
316             }
317         }
318         PolicyGroupIdentifier innermostGroupkey = null;
319         if (!bucketIds.isEmpty()) {
320             innermostGroupkey = new
321                     PolicyGroupIdentifier(id,
322                                           params,
323                                           bucketIds);
324         }
325         return innermostGroupkey;
326     }
327
328     public void removeGroupChain(PolicyGroupIdentifier key) {
329         checkArgument(key != null);
330         List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
331         groupsToBeDeleted.add(key);
332
333         Iterator<PolicyGroupIdentifier> it =
334                 groupsToBeDeleted.iterator();
335
336         while (it.hasNext()) {
337             PolicyGroupIdentifier innerMostGroupKey = it.next();
338             for (GroupBucketIdentifier bucketId:
339                         innerMostGroupKey.bucketIds()) {
340                 if (bucketId.type() != BucketOutputType.GROUP) {
341                     groupsToBeDeleted.add(bucketId.outGroup());
342                 }
343             }
344             /*groupService.removeGroup(deviceId,
345                                      getGroupKey(innerMostGroupKey),
346                                      appId);*/
347             //TODO: Use nextObjective APIs here
348             it.remove();
349         }
350     }
351
352 }