2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.Comparator;
16 import java.util.List;
17 import java.util.Optional;
18 import org.opendaylight.openflowjava.protocol.api.util.BinContent;
19 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.data.ActionConvertorData;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroup;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupModCommand;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupType;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInputBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsList;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsListBuilder;
39 import org.opendaylight.yangtools.yang.common.Uint64;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 * Decodes the SAL - Group Mod Message and encodes into a OF
45 * Library for the OFPT_GROUP_MOD Message. Input:SAL Layer Group command data.
51 * VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(version);
52 * data.setDatapathId(datapathId);
53 * Optional<GroupModInputBuilder> ofGroup = convertorManager.convert(salGroup, data);
57 public class GroupConvertor extends Convertor<Group, GroupModInputBuilder, VersionDatapathIdConvertorData> {
58 private static final List<Class<?>> TYPES = Arrays.asList(Group.class, AddGroupInput.class,
59 RemoveGroupInput.class, UpdatedGroup.class);
62 * Create default empty group mod input builder
63 * Use this method, if result from convertor is empty.
65 * @param version Openflow version
66 * @return default empty group mod input builder
68 public static GroupModInputBuilder defaultResult(final short version) {
69 return new GroupModInputBuilder()
73 private static final Logger LOG = LoggerFactory.getLogger(GroupConvertor.class);
74 private static final Integer DEFAULT_WEIGHT = 0;
75 private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16);
76 private static final Long DEFAULT_WATCH_PORT = OFPP_ANY;
77 private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16);
78 private static final Long DEFAULT_WATCH_GROUP = OFPG_ANY;
79 private static final Comparator<Bucket> COMPARATOR = (bucket1, bucket2) -> {
80 if (bucket1.getBucketId() == null || bucket2.getBucketId() == null) {
83 return bucket1.getBucketId().getValue().compareTo(bucket2.getBucketId().getValue());
86 private List<BucketsList> salToOFBucketList(final Buckets buckets, final short version, final int groupType,
87 final Uint64 datapathid) {
88 final List<BucketsList> bucketLists = new ArrayList<>();
89 final ActionConvertorData data = new ActionConvertorData(version);
90 data.setDatapathId(datapathid);
92 for (org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket groupBucket :
93 buckets.getBucket()) {
94 BucketsListBuilder bucketBuilder = new BucketsListBuilder();
96 salToOFBucketListWeight(groupBucket, bucketBuilder, groupType);
97 salToOFBucketListWatchGroup(groupBucket, bucketBuilder, groupType);
98 salToOFBucketListWatchPort(groupBucket, bucketBuilder, groupType);
100 Optional<List<Action>> bucketActionList = getConvertorExecutor().convert(
101 groupBucket.getAction(), data);
103 bucketBuilder.setAction(bucketActionList.orElse(Collections.emptyList()));
104 BucketsList bucket = bucketBuilder.build();
105 bucketLists.add(bucket);
112 private static void salToOFBucketListWatchPort(final Bucket groupBucket, final BucketsListBuilder bucketBuilder,
113 final int groupType) {
114 if (null != groupBucket.getWatchPort()) {
115 bucketBuilder.setWatchPort(new PortNumber(groupBucket.getWatchPort()));
117 bucketBuilder.setWatchPort(new PortNumber(BinContent.intToUnsignedLong(DEFAULT_WATCH_PORT.intValue())));
118 if (groupType == GroupType.OFPGTFF.getIntValue()) {
119 LOG.error("WatchPort required for this OFPGT_FF");
124 private static void salToOFBucketListWatchGroup(final Bucket groupBucket, final BucketsListBuilder bucketBuilder,
125 final int groupType) {
126 if (null != groupBucket.getWatchGroup()) {
127 bucketBuilder.setWatchGroup(groupBucket.getWatchGroup());
129 bucketBuilder.setWatchGroup(BinContent.intToUnsignedLong(DEFAULT_WATCH_GROUP.intValue()));
130 if (groupType == GroupType.OFPGTFF.getIntValue()) {
131 LOG.error("WatchGroup required for this OFPGT_FF");
136 private static void salToOFBucketListWeight(final Bucket groupBucket, final BucketsListBuilder bucketBuilder,
137 final int groupType) {
138 if (null != groupBucket.getWeight()) {
139 bucketBuilder.setWeight(groupBucket.getWeight());
141 bucketBuilder.setWeight(DEFAULT_WEIGHT);
142 if (groupType == GroupType.OFPGTSELECT.getIntValue()) {
143 LOG.error("Weight value required for this OFPGT_SELECT");
149 public Collection<Class<?>> getTypes() {
154 public GroupModInputBuilder convert(final Group source, final VersionDatapathIdConvertorData data) {
155 GroupModInputBuilder groupModInputBuilder = new GroupModInputBuilder();
156 if (source instanceof AddGroupInput) {
157 groupModInputBuilder.setCommand(GroupModCommand.OFPGCADD);
158 } else if (source instanceof RemoveGroupInput) {
159 groupModInputBuilder.setCommand(GroupModCommand.OFPGCDELETE);
160 } else if (source instanceof UpdatedGroup) {
161 groupModInputBuilder.setCommand(GroupModCommand.OFPGCMODIFY);
164 if (GroupTypes.GroupAll.equals(source.getGroupType())) {
165 groupModInputBuilder.setType(GroupType.OFPGTALL);
168 if (GroupTypes.GroupSelect.equals(source.getGroupType())) {
169 groupModInputBuilder.setType(GroupType.OFPGTSELECT);
172 if (GroupTypes.GroupIndirect.equals(source.getGroupType())) {
173 groupModInputBuilder.setType(GroupType.OFPGTINDIRECT);
176 if (GroupTypes.GroupFf.equals(source.getGroupType())) {
177 groupModInputBuilder.setType(GroupType.OFPGTFF);
180 groupModInputBuilder.setGroupId(new GroupId(source.getGroupId().getValue()));
182 // Only if the bucket is configured for the group then add it
183 // During group deletion do not push the buckets
184 if (groupModInputBuilder.getCommand() != GroupModCommand.OFPGCDELETE) {
185 if (source.getBuckets() != null && source.getBuckets().getBucket().size() != 0) {
187 List<Bucket> bucketList = new ArrayList<>(source.getBuckets().getBucket());
188 Group group = new GroupBuilder(source)
189 .setBuckets(new BucketsBuilder().setBucket(bucketList).build())
191 Collections.sort(group.getBuckets().getBucket(), COMPARATOR);
193 List<BucketsList> bucketLists = salToOFBucketList(group.getBuckets(), data.getVersion(),
194 group.getGroupType().getIntValue(), data.getDatapathId());
195 groupModInputBuilder.setBucketsList(bucketLists);
199 groupModInputBuilder.setVersion(data.getVersion());
200 return groupModInputBuilder;