blob: 7b798c0ac1ec5b7ff36e28bc846edce2bee43905 [file] [log] [blame]
Carmelo Cascone87b9b392017-10-02 18:33:20 +02001/*
2 * Copyright 2017-present Open Networking Foundation
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.net.pi.impl;
18
19import org.onosproject.net.Device;
20import org.onosproject.net.group.Group;
21import org.onosproject.net.group.GroupBucket;
22import org.onosproject.net.pi.model.PiPipeconf;
23import org.onosproject.net.pi.model.PiPipelineInterpreter;
24import org.onosproject.net.pi.runtime.PiAction;
25import org.onosproject.net.pi.runtime.PiActionGroup;
26import org.onosproject.net.pi.runtime.PiActionGroupId;
27import org.onosproject.net.pi.runtime.PiActionGroupMember;
28import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
29import org.onosproject.net.pi.runtime.PiGroupKey;
30import org.onosproject.net.pi.runtime.PiTableAction;
31import org.onosproject.net.pi.runtime.PiTranslationService.PiTranslationException;
32
33import java.nio.ByteBuffer;
34
35import static java.lang.String.format;
36import static org.onosproject.net.pi.impl.PiFlowRuleTranslator.translateTreatment;
37import static org.onosproject.net.pi.impl.PiUtils.getInterpreterOrNull;
38import static org.onosproject.net.pi.runtime.PiTableAction.Type.ACTION;
39
40/**
41 * Implementation of group translation logic.
42 */
43final class PiGroupTranslator {
44
45 private PiGroupTranslator() {
46 // Hides constructor.
47 }
48
49 /**
50 * Returns a PI action group equivalent to the given group, for the given pipeconf and device.
51 *
52 * @param group group
53 * @param pipeconf pipeconf
54 * @param device device
55 * @return PI action group
56 * @throws PiTranslationException if the group cannot be translated
57 */
58 static PiActionGroup translate(Group group, PiPipeconf pipeconf, Device device) throws PiTranslationException {
59
60 final PiPipelineInterpreter interpreter = getInterpreterOrNull(device, pipeconf);
61
62 final PiActionGroup.Builder piActionGroupBuilder = PiActionGroup.builder()
63 .withId(PiActionGroupId.of(group.id().id()));
64
65 switch (group.type()) {
66 case SELECT:
67 piActionGroupBuilder.withType(PiActionGroup.Type.SELECT);
68 break;
69 default:
70 throw new PiTranslationException(format("Group type %s not supported", group.type()));
71 }
72
73 if (!(group.appCookie() instanceof PiGroupKey)) {
74 throw new PiTranslationException("Group app cookie is not PI (class should be PiGroupKey)");
75 }
76 final PiGroupKey groupKey = (PiGroupKey) group.appCookie();
77
78 piActionGroupBuilder.withActionProfileId(groupKey.actionProfileId());
79
80 // Translate group buckets to PI group members
81 short bucketIdx = 0;
82 for (GroupBucket bucket : group.buckets().buckets()) {
83 /*
84 FIXME: the way member IDs are computed can cause collisions!
85 Problem:
86 In P4Runtime action group members, i.e. action buckets, are associated to a numeric ID chosen
87 at member insertion time. This ID must be unique for the whole action profile (i.e. the group table in
88 OpenFlow). In ONOS, GroupBucket doesn't specify any ID.
89
90 Solutions:
91 - Change GroupBucket API to force application wanting to perform group operations to specify a member id.
92 - Maintain state to dynamically allocate/deallocate member IDs, e.g. in a dedicated service, or in a
93 P4Runtime Group Provider.
94
95 Hack:
96 Statically derive member ID by combining groupId and position of the bucket in the list.
97 */
98 ByteBuffer bb = ByteBuffer.allocate(4)
99 .putShort((short) (group.id().id() & 0xffff))
100 .putShort(bucketIdx);
101 bb.rewind();
102 int memberId = bb.getInt();
103 bucketIdx++;
104
105 final PiTableAction tableAction = translateTreatment(bucket.treatment(), interpreter, groupKey.tableId(),
106 pipeconf.pipelineModel());
107
108 if (tableAction.type() != ACTION) {
109 throw new PiTranslationException(format(
110 "PI table action of type %s is not supported in groups", tableAction.type()));
111 }
112
113 piActionGroupBuilder.addMember(PiActionGroupMember.builder()
114 .withId(PiActionGroupMemberId.of(memberId))
115 .withAction((PiAction) tableAction)
116 .withWeight(bucket.weight())
117 .build());
118 }
119
120 return piActionGroupBuilder.build();
121 }
122}