blob: 39fba4f05521aee12124ed49c4baf0a8de4d07f2 [file] [log] [blame]
Charles Chan425854b2016-04-11 15:32:12 -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.driver.pipeline;
18
19import org.onlab.packet.MacAddress;
20import org.onlab.packet.VlanId;
21import org.onosproject.core.ApplicationId;
22import org.onosproject.core.DefaultGroupId;
23import org.onosproject.net.flow.DefaultTrafficTreatment;
24import org.onosproject.net.flow.TrafficSelector;
25import org.onosproject.net.flow.TrafficTreatment;
26import org.onosproject.net.flow.criteria.Criterion;
27import org.onosproject.net.flow.criteria.VlanIdCriterion;
28import org.onosproject.net.flow.instructions.Instruction;
29import org.onosproject.net.flow.instructions.Instructions;
30import org.onosproject.net.flow.instructions.L2ModificationInstruction;
31import org.onosproject.net.group.DefaultGroupBucket;
32import org.onosproject.net.group.DefaultGroupDescription;
33import org.onosproject.net.group.DefaultGroupKey;
34import org.onosproject.net.group.GroupBucket;
35import org.onosproject.net.group.GroupBuckets;
36import org.onosproject.net.group.GroupDescription;
37import org.onosproject.net.group.GroupKey;
38import org.slf4j.Logger;
39
40import java.util.Collections;
41
42import static org.slf4j.LoggerFactory.getLogger;
43
44/**
45 * Group handler for CpqD OFDPA pipeline.
46 */
47public class CpqdOfdpa2GroupHandler extends Ofdpa2GroupHandler {
48 private final Logger log = getLogger(getClass());
49
50 @Override
51 protected GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId,
52 ApplicationId appId, boolean mpls,
53 TrafficSelector meta) {
54 // for the l2interface group, get vlan and port info
55 // for the outer group, get the src/dst mac, and vlan info
56 TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
57 TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
58 VlanId vlanid = null;
59 long portNum = 0;
60 boolean setVlan = false, popVlan = false;
61 MacAddress srcMac = MacAddress.ZERO;
62 MacAddress dstMac = MacAddress.ZERO;
63 for (Instruction ins : treatment.allInstructions()) {
64 if (ins.type() == Instruction.Type.L2MODIFICATION) {
65 L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
66 switch (l2ins.subtype()) {
67 case ETH_DST:
68 dstMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
69 outerTtb.setEthDst(dstMac);
70 break;
71 case ETH_SRC:
72 srcMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
73 outerTtb.setEthSrc(srcMac);
74 break;
75 case VLAN_ID:
76 vlanid = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
77 outerTtb.setVlanId(vlanid);
78 setVlan = true;
79 break;
80 case VLAN_POP:
81 innerTtb.popVlan();
82 popVlan = true;
83 break;
84 case DEC_MPLS_TTL:
85 case MPLS_LABEL:
86 case MPLS_POP:
87 case MPLS_PUSH:
88 case VLAN_PCP:
89 case VLAN_PUSH:
90 default:
91 break;
92 }
93 } else if (ins.type() == Instruction.Type.OUTPUT) {
94 portNum = ((Instructions.OutputInstruction) ins).port().toLong();
95 innerTtb.add(ins);
96 } else {
97 log.warn("Driver does not handle this type of TrafficTreatment"
98 + " instruction in nextObjectives: {}", ins.type());
99 }
100 }
101
102 if (vlanid == null && meta != null) {
103 // use metadata if available
104 Criterion vidCriterion = meta.getCriterion(Criterion.Type.VLAN_VID);
105 if (vidCriterion != null) {
106 vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
107 }
108 // if vlan is not set, use the vlan in metadata for outerTtb
109 if (vlanid != null && !setVlan) {
110 outerTtb.setVlanId(vlanid);
111 }
112 }
113
114 if (vlanid == null) {
115 log.error("Driver cannot process an L2/L3 group chain without "
116 + "egress vlan information for dev: {} port:{}",
117 deviceId, portNum);
118 return null;
119 }
120
121 if (!setVlan && !popVlan) {
122 // untagged outgoing port
123 TrafficTreatment.Builder temp = DefaultTrafficTreatment.builder();
124 temp.popVlan();
125 innerTtb.build().allInstructions().forEach(i -> temp.add(i));
126 innerTtb = temp;
127 }
128
129 // assemble information for ofdpa l2interface group
130 int l2groupId = L2_INTERFACE_TYPE | (vlanid.toShort() << 16) | (int) portNum;
131 // a globally unique groupkey that is different for ports in the same device,
132 // but different for the same portnumber on different devices. Also different
133 // for the various group-types created out of the same next objective.
134 int l2gk = l2InterfaceGroupKey(deviceId, vlanid, portNum);
135 final GroupKey l2groupkey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(l2gk));
136
137 // assemble information for outer group
138 GroupDescription outerGrpDesc = null;
139 if (mpls) {
140 // outer group is MPLSInteface
141 int mplsInterfaceIndex = getNextAvailableIndex();
142 int mplsgroupId = MPLS_INTERFACE_TYPE | (SUBTYPE_MASK & mplsInterfaceIndex);
143 final GroupKey mplsgroupkey = new DefaultGroupKey(
144 Ofdpa2Pipeline.appKryo.serialize(mplsInterfaceIndex));
145 outerTtb.group(new DefaultGroupId(l2groupId));
146 // create the mpls-interface group description to wait for the
147 // l2 interface group to be processed
148 GroupBucket mplsinterfaceGroupBucket =
149 DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
150 outerGrpDesc = new DefaultGroupDescription(
151 deviceId,
152 GroupDescription.Type.INDIRECT,
153 new GroupBuckets(Collections.singletonList(
154 mplsinterfaceGroupBucket)),
155 mplsgroupkey,
156 mplsgroupId,
157 appId);
158 log.debug("Trying MPLS-Interface: device:{} gid:{} gkey:{} nextid:{}",
159 deviceId, Integer.toHexString(mplsgroupId),
160 mplsgroupkey, nextId);
161 } else {
162 // outer group is L3Unicast
163 int l3unicastIndex = getNextAvailableIndex();
164 int l3groupId = L3_UNICAST_TYPE | (TYPE_MASK & l3unicastIndex);
165 final GroupKey l3groupkey = new DefaultGroupKey(
166 Ofdpa2Pipeline.appKryo.serialize(l3unicastIndex));
167 outerTtb.group(new DefaultGroupId(l2groupId));
168 // create the l3unicast group description to wait for the
169 // l2 interface group to be processed
170 GroupBucket l3unicastGroupBucket =
171 DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
172 outerGrpDesc = new DefaultGroupDescription(
173 deviceId,
174 GroupDescription.Type.INDIRECT,
175 new GroupBuckets(Collections.singletonList(
176 l3unicastGroupBucket)),
177 l3groupkey,
178 l3groupId,
179 appId);
180 log.debug("Trying L3Unicast: device:{} gid:{} gkey:{} nextid:{}",
181 deviceId, Integer.toHexString(l3groupId),
182 l3groupkey, nextId);
183 }
184
185 // store l2groupkey with the groupChainElem for the outer-group that depends on it
186 GroupChainElem gce = new GroupChainElem(outerGrpDesc, 1, false);
187 updatePendingGroups(l2groupkey, gce);
188
189 // create group description for the inner l2interfacegroup
190 GroupBucket l2InterfaceGroupBucket =
191 DefaultGroupBucket.createIndirectGroupBucket(innerTtb.build());
192 GroupDescription l2groupDescription =
193 new DefaultGroupDescription(
194 deviceId,
195 GroupDescription.Type.INDIRECT,
196 new GroupBuckets(Collections.singletonList(
197 l2InterfaceGroupBucket)),
198 l2groupkey,
199 l2groupId,
200 appId);
201 log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}",
202 deviceId, Integer.toHexString(l2groupId),
203 l2groupkey, nextId);
204 return new GroupInfo(l2groupDescription, outerGrpDesc);
205 }
206}