blob: eee8c593e108e4be12896e74e7bdf6f6ce769f0f [file] [log] [blame]
Carmelo Casconeefc0a922016-06-14 14:32:33 -07001/*
2 * Copyright 2016-present 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
17package org.onosproject.bmv2.demo.app.ecmp;
18
19import com.google.common.collect.Maps;
20import org.onlab.util.ImmutableByteSequence;
21import org.onosproject.bmv2.api.context.Bmv2ActionModel;
22import org.onosproject.bmv2.api.runtime.Bmv2Action;
23import org.onosproject.bmv2.api.runtime.Bmv2ExtensionTreatment;
24import org.onosproject.bmv2.api.utils.Bmv2TranslatorUtils;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.PortNumber;
27import org.onosproject.net.flow.instructions.ExtensionTreatment;
28
29import java.util.Map;
30import java.util.Set;
31
32import static org.onosproject.bmv2.api.utils.Bmv2TranslatorUtils.fitByteSequence;
33import static org.onosproject.bmv2.demo.app.ecmp.EcmpFabricApp.ECMP_CONTEXT;
34import static org.onosproject.bmv2.demo.app.ecmp.EcmpInterpreter.*;
35
36/**
37 * Builder of ECMP extension treatments.
38 */
39public class EcmpGroupTreatmentBuilder {
40
41 private static final Map<DeviceId, Map<Set<PortNumber>, Short>> DEVICE_GROUP_ID_MAP = Maps.newHashMap();
42 private int groupId;
43 private int groupSize;
44
45 /**
46 * Sets the group ID.
47 *
48 * @param groupId an integer value
49 * @return this
50 */
51 public EcmpGroupTreatmentBuilder withGroupId(int groupId) {
52 this.groupId = groupId;
53 return this;
54 }
55
56 /**
57 * Sets the group size.
58 *
59 * @param groupSize an integer value
60 * @return this
61 */
62 public EcmpGroupTreatmentBuilder withGroupSize(int groupSize) {
63 this.groupSize = groupSize;
64 return this;
65 }
66
67 /**
68 * Returns a new extension treatment.
69 *
70 * @return an extension treatment
71 */
72 public ExtensionTreatment build() {
73 Bmv2ActionModel actionModel = ECMP_CONTEXT.configuration().action(ECMP_GROUP);
74 int groupIdBitWidth = actionModel.runtimeData(GROUP_ID).bitWidth();
75 int groupSizeBitWidth = actionModel.runtimeData(GROUP_SIZE).bitWidth();
76
77 try {
78 ImmutableByteSequence groupIdBs = fitByteSequence(ImmutableByteSequence.copyFrom(groupId), groupIdBitWidth);
79 ImmutableByteSequence groupSizeBs = fitByteSequence(ImmutableByteSequence.copyFrom(groupSize),
80 groupSizeBitWidth);
81
82 return new Bmv2ExtensionTreatment(Bmv2Action.builder()
83 .withName(ECMP_GROUP)
84 .addParameter(groupIdBs)
85 .addParameter(groupSizeBs)
86 .build());
87
88 } catch (Bmv2TranslatorUtils.ByteSequenceFitException e) {
89 throw new RuntimeException(e);
90 }
91 }
92
93 /**
94 * Returns a group ID for the given device and set of ports.
95 *
96 * @param deviceId a device ID
97 * @param ports a set of ports
98 * @return an integer value
99 */
100 public static int groupIdOf(DeviceId deviceId, Set<PortNumber> ports) {
101 DEVICE_GROUP_ID_MAP.putIfAbsent(deviceId, Maps.newHashMap());
102 // Counts the number of unique portNumber sets for each deviceId.
103 // Each distinct set of portNumbers will have a unique ID.
104 return DEVICE_GROUP_ID_MAP.get(deviceId).computeIfAbsent(ports, (pp) ->
105 (short) (DEVICE_GROUP_ID_MAP.get(deviceId).size() + 1));
106 }
107}