blob: bf1be3976f826d2f1687882e7e7fefbd0166a160 [file] [log] [blame]
Michele Santuari9a8d16d2016-03-24 10:37:58 -07001/*
Brian O'Connor0a4e6742016-09-15 23:03:10 -07002 * Copyright 2016-present Open Networking Laboratory
Michele Santuari9a8d16d2016-03-24 10:37:58 -07003 *
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.drivers.corsa;
18
Michele Santuarid2c8b152016-03-30 17:57:56 -070019import com.google.common.collect.ImmutableSet;
Michele Santuari9a8d16d2016-03-24 10:37:58 -070020import org.onlab.packet.Ethernet;
21import org.onlab.packet.IPv4;
22import org.onlab.packet.VlanId;
23import org.onosproject.net.flow.DefaultFlowRule;
24import org.onosproject.net.flow.DefaultTrafficSelector;
25import org.onosproject.net.flow.DefaultTrafficTreatment;
26import org.onosproject.net.flow.FlowRule;
27import org.onosproject.net.flow.TrafficSelector;
28import org.onosproject.net.flow.TrafficTreatment;
29import org.onosproject.net.flow.criteria.Criterion;
30import org.onosproject.net.flow.criteria.IPCriterion;
31import org.onosproject.net.flow.criteria.IPProtocolCriterion;
Pier Ventredb673552016-07-20 15:37:19 +020032import org.onosproject.net.flow.instructions.Instruction;
Michele Santuarid2c8b152016-03-30 17:57:56 -070033import org.onosproject.net.flow.instructions.Instructions;
34import org.onosproject.net.flow.instructions.L2ModificationInstruction;
Michele Santuari9a8d16d2016-03-24 10:37:58 -070035import org.onosproject.net.flowobjective.ForwardingObjective;
36import org.onosproject.net.flowobjective.ObjectiveError;
37import org.slf4j.Logger;
38
39import java.util.Collection;
40import java.util.Collections;
41
42import static org.onosproject.net.flow.FlowRule.Builder;
Michele Santuarid2c8b152016-03-30 17:57:56 -070043import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
44import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_SRC;
45import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_ID;
46import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_POP;
Michele Santuari9a8d16d2016-03-24 10:37:58 -070047import static org.slf4j.LoggerFactory.getLogger;
48
49public class CorsaPipelineV39 extends CorsaPipelineV3 {
50
51 private final Logger log = getLogger(getClass());
52
53 private static final Short NATIVE_VLAN = 4095;
54
55 @Override
56 public void initializePipeline() {
57
58 processMeterTable(true); //Meter Table
59 processPortBasedProtoTable(true);
60 processVlanCheckTable(true); //Table 1
61 processVlanMacXlateTable(true); //Table 2
62 processVlanCircuitTable(true); //Table 3
63 processL3IFMacDATable(true); //Table 5
64 processEtherTable(true); //Table 6
65 //TODO: to be implemented for intents
Michele Santuarid2c8b152016-03-30 17:57:56 -070066 processFibTable(true); //Table 7
Michele Santuari9a8d16d2016-03-24 10:37:58 -070067 //processLocalTable(true); //Table 9
68 }
69
70 @Override
71 protected void processVlanCheckTable(boolean install) {
Michele Santuarid2c8b152016-03-30 17:57:56 -070072 //current device pipeline reports errors, but it is a bug
Michele Santuari9a8d16d2016-03-24 10:37:58 -070073 processTableMissGoTo(true, VLAN_CHECK_TABLE, VLAN_MAC_XLATE_TABLE, "Provisioned vlan tagged");
74 //Tag untagged packets
75 processUntaggedPackets(install);
76
77 }
78
79 private void processUntaggedPackets(boolean install) {
80
81 deviceService.getPorts(deviceId).forEach(port -> {
82 if (!port.number().isLogical()) {
83
84 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
85 .pushVlan().setVlanId(VlanId.vlanId(NATIVE_VLAN))
86 .transition(VLAN_MAC_XLATE_TABLE);
87
88 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
89 .matchVlanId(VlanId.NONE)
90 .matchInPort(port.number());
91
92 Builder rule = DefaultFlowRule.builder()
93 .forDevice(deviceId)
94 .withTreatment(treatment.build())
95 .withSelector(selector.build())
96 .withPriority(CONTROLLER_PRIORITY)
97 .fromApp(appId)
98 .makePermanent()
99 .forTable(VLAN_CHECK_TABLE);
100
101 processFlowRule(install, rule.build(), "Provisioned vlan untagged packet table");
102 }
103 });
104 }
105
106 @Override
107 protected void processVlanCircuitTable(boolean install) {
108 //Default action
109 processTableMissDrop(install, VLAN_CIRCUIT_TABLE, "Provisioned vlan circuit table drop");
110 //FIXME: it should be done only per port based when intent is installed
111 //Manage untagged packets
112 processRouterPacket(install);
113 }
114
115 private void processRouterPacket(boolean install) {
116
117 deviceService.getPorts(deviceId).forEach(port -> {
118 if (!port.number().isLogical()) {
119 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
120 .matchVlanId(VlanId.vlanId(NATIVE_VLAN))
121 .matchInPort(port.number());
122
123 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
124 .setVlanPcp((byte) 0)
125 .setQueue(0)
126 .meter(defaultMeterId)
127 .transition(L3_IF_MAC_DA_TABLE);
128
129 FlowRule rule = DefaultFlowRule.builder()
130 .forDevice(deviceId)
131 .withSelector(selector.build())
132 .withTreatment(treatment.build())
133 .withPriority(CONTROLLER_PRIORITY)
134 .fromApp(appId)
135 .makePermanent()
136 .forTable(VLAN_CIRCUIT_TABLE).build();
137 processFlowRule(install, rule, "Provisioned vlan circuit table");
138 }
139 });
140 }
141
142 @Override
143 protected void processL3IFMacDATable(boolean install) {
144 int table = L3_IF_MAC_DA_TABLE;
145
146 //Default action
147 processTableMissDrop(install, table, "Provisioned l3 table drop");
148
149 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
150
151 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
152 .transition(ETHER_TABLE);
153
154 FlowRule rule = DefaultFlowRule.builder()
155 .forDevice(deviceId)
156 .withSelector(selector.build())
157 .withTreatment(treatment.build())
158 .withPriority(1)
159 .fromApp(appId)
160 .makePermanent()
161 .forTable(table).build();
162 processFlowRule(install, rule, "Provisioned l3 table");
163 }
164
165 protected void processEtherTable(boolean install) {
166
167 //Default action
168 processTableMissDrop(install, ETHER_TABLE, "Provisioned ether type table drop");
169
170 //IP to FIB_TABLE
171 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
172 .matchEthType(Ethernet.TYPE_IPV4);
173
174 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder().transition(FIB_TABLE);
175
176 FlowRule rule = DefaultFlowRule.builder()
177 .forDevice(deviceId)
178 .withSelector(selector.build())
179 .withTreatment(treatment.build())
180 .withPriority(CONTROLLER_PRIORITY)
181 .fromApp(appId)
182 .makePermanent()
183 .forTable(ETHER_TABLE).build();
184 processFlowRule(install, rule, "Provisioned ether type table ip");
185 }
186
187 @Override
188 protected Collection<FlowRule> processArpTraffic(ForwardingObjective fwd, Builder rule) {
189 rule.forTable(PORT_BASED_PROTO_TABLE);
190 rule.withPriority(255);
191 return Collections.singletonList(rule.build());
192 }
193
194 @Override
195 protected Collection<FlowRule> processLinkDiscovery(ForwardingObjective fwd, Builder rule) {
196 rule.forTable(PORT_BASED_PROTO_TABLE);
197 rule.withPriority(255);
198 return Collections.singletonList(rule.build());
199 }
200
201 @Override
202 protected Collection<FlowRule> processIpTraffic(ForwardingObjective fwd, Builder rule) {
203 IPCriterion ipSrc = (IPCriterion) fwd.selector()
204 .getCriterion(Criterion.Type.IPV4_SRC);
205 if (ipSrc != null) {
206 log.warn("Driver does not currently handle matching Src IP");
207 fail(fwd, ObjectiveError.UNSUPPORTED);
Michele Santuarid2c8b152016-03-30 17:57:56 -0700208 return ImmutableSet.of();
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700209 }
210 IPCriterion ipDst = (IPCriterion) fwd.selector()
211 .getCriterion(Criterion.Type.IPV4_DST);
212 if (ipDst != null) {
213 log.error("Driver handles Dst IP matching as specific forwarding "
214 + "objective, not versatile");
215 fail(fwd, ObjectiveError.UNSUPPORTED);
Michele Santuarid2c8b152016-03-30 17:57:56 -0700216 return ImmutableSet.of();
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700217 }
218 IPProtocolCriterion ipProto = (IPProtocolCriterion) fwd.selector()
219 .getCriterion(Criterion.Type.IP_PROTO);
220 if (ipProto != null && ipProto.protocol() == IPv4.PROTOCOL_TCP) {
221 log.warn("Driver automatically punts all packets reaching the "
222 + "LOCAL table to the controller");
223 pass(fwd);
Michele Santuarid2c8b152016-03-30 17:57:56 -0700224 return ImmutableSet.of();
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700225 }
Michele Santuarid2c8b152016-03-30 17:57:56 -0700226 return ImmutableSet.of();
227 }
228
229 @Override
Pier Ventredb673552016-07-20 15:37:19 +0200230 protected CorsaTrafficTreatment processNextTreatment(TrafficTreatment treatment) {
Michele Santuarid2c8b152016-03-30 17:57:56 -0700231 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
Michele Santuarid2c8b152016-03-30 17:57:56 -0700232 treatment.immediate().stream()
233 .filter(i -> {
234 switch (i.type()) {
235 case L2MODIFICATION:
236 L2ModificationInstruction l2i = (L2ModificationInstruction) i;
237 if (l2i.subtype() == VLAN_ID ||
238 l2i.subtype() == VLAN_POP ||
Michele Santuarid2c8b152016-03-30 17:57:56 -0700239 l2i.subtype() == ETH_DST ||
240 l2i.subtype() == ETH_SRC) {
241 return true;
242 }
243 case OUTPUT:
244 return true;
245 default:
246 return false;
247 }
248 }).forEach(i -> tb.add(i));
Pier Ventredb673552016-07-20 15:37:19 +0200249
250 TrafficTreatment t = tb.build();
251
252 boolean isPresentModVlanId = false;
253 boolean isPresentModEthSrc = false;
254 boolean isPresentModEthDst = false;
255 boolean isPresentOutpuPort = false;
256
257 for (Instruction instruction : t.immediate()) {
258 switch (instruction.type()) {
259 case L2MODIFICATION:
260 L2ModificationInstruction l2i = (L2ModificationInstruction) instruction;
261 if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction) {
262 isPresentModVlanId = true;
263 }
264
265 if (l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
266 L2ModificationInstruction.L2SubType subType = l2i.subtype();
267 if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC)) {
268 isPresentModEthSrc = true;
269 } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST)) {
270 isPresentModEthDst = true;
271 }
272 }
273 case OUTPUT:
274 isPresentOutpuPort = true;
275 default:
276 }
277 }
278 CorsaTrafficTreatmentType type = CorsaTrafficTreatmentType.ACTIONS;
279 /**
280 * These are the allowed groups for CorsaPipelinev39
281 */
282 if (isPresentModVlanId && isPresentModEthSrc && isPresentModEthDst && isPresentOutpuPort) {
283 type = CorsaTrafficTreatmentType.GROUP;
284
285 } else if ((!isPresentModVlanId && isPresentModEthSrc && isPresentModEthDst && isPresentOutpuPort) ||
286 (!isPresentModVlanId && !isPresentModEthSrc && isPresentModEthDst && isPresentOutpuPort) ||
287 (!isPresentModVlanId && !isPresentModEthSrc && !isPresentModEthDst && isPresentOutpuPort)) {
288 type = CorsaTrafficTreatmentType.GROUP;
289 TrafficTreatment.Builder tb2 = DefaultTrafficTreatment.builder(t);
290 tb2.add(Instructions.popVlan());
291 t = tb2.build();
292 }
293 CorsaTrafficTreatment corsaTreatment = new CorsaTrafficTreatment(type, t);
294 return corsaTreatment;
Michele Santuari9a8d16d2016-03-24 10:37:58 -0700295 }
296}