BUG-2664 - Buckets in groups are not ordered
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / GroupConvertor.java
1 /**
2  * Copyright (c) 2014 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.Comparator;
14 import java.util.List;
15
16 import org.opendaylight.openflowjava.protocol.api.util.BinContent;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroup;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupModCommand;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsList;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsListBuilder;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 /**
35  * This Utility class decodes the SAL - Group Mod Message and encodes into a OF
36  * Library for the OFPT_GROUP_MOD Message. Input:SAL Layer Group command data.
37  * Output:GroupModInput Message.
38  *
39  *
40  */
41 public final class GroupConvertor {
42
43     private static final Logger LOG = LoggerFactory.getLogger(GroupConvertor.class);
44
45     private static final Integer DEFAULT_WEIGHT = 0;
46     private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
47     private static final Long DEFAULT_WATCH_PORT = OFPP_ANY;
48     private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
49     private static final Long DEFAULT_WATCH_GROUP = OFPG_ANY;
50     private static final Comparator<Bucket> comparator = new Comparator<Bucket>(){
51         @Override
52         public int compare(Bucket bucket1,
53                            Bucket bucket2) {
54             if(bucket1.getBucketId() == null || bucket2.getBucketId() == null) return 0;
55             return  bucket1.getBucketId().getValue().compareTo(bucket2.getBucketId().getValue());
56         }
57     };
58
59     private GroupConvertor() {
60
61     }
62
63     public static GroupModInputBuilder toGroupModInput(
64
65     org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group source, short version,BigInteger datapathid) {
66         List<BucketsList> bucketLists = null;
67         GroupModInputBuilder groupModInputBuilder = new GroupModInputBuilder();
68         if (source instanceof AddGroupInput) {
69             groupModInputBuilder.setCommand(GroupModCommand.OFPGCADD);
70         } else if (source instanceof RemoveGroupInput) {
71             groupModInputBuilder.setCommand(GroupModCommand.OFPGCDELETE);
72         } else if (source instanceof UpdatedGroup) {
73             groupModInputBuilder.setCommand(GroupModCommand.OFPGCMODIFY);
74         }
75
76         if (GroupTypes.GroupAll.equals(source.getGroupType())) {
77             groupModInputBuilder.setType(GroupType.OFPGTALL);
78         }
79
80         if (GroupTypes.GroupSelect.equals(source.getGroupType())) {
81             groupModInputBuilder.setType(GroupType.OFPGTSELECT);
82         }
83
84         if (GroupTypes.GroupIndirect.equals(source.getGroupType())) {
85             groupModInputBuilder.setType(GroupType.OFPGTINDIRECT);
86         }
87
88         if (GroupTypes.GroupFf.equals(source.getGroupType())) {
89             groupModInputBuilder.setType(GroupType.OFPGTFF);
90         }
91
92         groupModInputBuilder.setGroupId(new GroupId(source.getGroupId().getValue()));
93         // Only if the bucket is configured for the group then add it
94         if ((source.getBuckets() != null) && (source.getBuckets().getBucket().size() != 0)) {
95
96             Collections.sort(source.getBuckets().getBucket(), comparator);
97
98             bucketLists = salToOFBucketList(source.getBuckets(), version, source.getGroupType().getIntValue(),datapathid);
99             groupModInputBuilder.setBucketsList(bucketLists);
100         }
101         groupModInputBuilder.setVersion(version);
102         return groupModInputBuilder;
103
104     }
105
106     private static List<BucketsList> salToOFBucketList(Buckets buckets, short version, int groupType,BigInteger datapathid) {
107         final List<BucketsList> bucketLists = new ArrayList<>();
108         for (org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket groupBucket : buckets
109                 .getBucket()) {
110             BucketsListBuilder bucketBuilder = new BucketsListBuilder();
111
112             salToOFBucketListWeight(groupBucket, bucketBuilder, groupType);
113             salToOFBucketListWatchGroup(groupBucket, bucketBuilder, groupType);
114             salToOFBucketListWatchPort(groupBucket, bucketBuilder, groupType);
115
116             List<Action> bucketActionList = ActionConvertor.getActions(groupBucket.getAction(), version, datapathid, null);
117             bucketBuilder.setAction(bucketActionList);
118             BucketsList bucket = bucketBuilder.build();
119             bucketLists.add(bucket);
120         }
121         return bucketLists;
122
123     }
124
125     private static void salToOFBucketListWatchPort(Bucket groupBucket, BucketsListBuilder bucketBuilder, int groupType) {
126         if (null != groupBucket.getWatchPort()) {
127             bucketBuilder.setWatchPort(new PortNumber(groupBucket.getWatchPort()));
128         } else {
129             bucketBuilder.setWatchPort(new PortNumber(BinContent.intToUnsignedLong(DEFAULT_WATCH_PORT.intValue())));
130             if (groupType == GroupType.OFPGTFF.getIntValue()) {
131                 LOG.error("WatchPort required for this OFPGT_FF");
132             }
133         }
134     }
135
136     private static void salToOFBucketListWatchGroup(Bucket groupBucket, BucketsListBuilder bucketBuilder, int groupType) {
137         if (null != groupBucket.getWatchGroup()) {
138             bucketBuilder.setWatchGroup(groupBucket.getWatchGroup());
139         } else {
140             bucketBuilder.setWatchGroup(BinContent.intToUnsignedLong(DEFAULT_WATCH_GROUP.intValue()));
141             if (groupType == GroupType.OFPGTFF.getIntValue()) {
142                 LOG.error("WatchGroup required for this OFPGT_FF");
143             }
144         }
145     }
146
147     private static void salToOFBucketListWeight(Bucket groupBucket, BucketsListBuilder bucketBuilder, int groupType) {
148         if (null != groupBucket.getWeight()) {
149             bucketBuilder.setWeight(groupBucket.getWeight().intValue());
150         } else {
151             bucketBuilder.setWeight(DEFAULT_WEIGHT);
152             if (groupType == GroupType.OFPGTSELECT.getIntValue()) {
153                 LOG.error("Weight value required for this OFPGT_SELECT");
154             }
155         }
156     }
157
158 }