blob: d582f6e7e819e9a35b5174f042a18ebcf0971788 [file] [log] [blame]
Sho SHIMIZUee2aa652015-02-25 18:56:43 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Sho SHIMIZUee2aa652015-02-25 18:56:43 -08003 *
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 */
16package org.onosproject.net.intent.impl.compiler;
17
18import com.google.common.collect.HashMultimap;
19import com.google.common.collect.SetMultimap;
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
Brian O'Connor406e2642016-04-18 11:45:35 -070025import org.onlab.packet.Ip4Address;
26import org.onlab.packet.IpPrefix;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080027import org.onosproject.core.ApplicationId;
28import org.onosproject.core.CoreService;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080029import org.onosproject.net.ConnectPoint;
30import org.onosproject.net.DeviceId;
31import org.onosproject.net.Link;
32import org.onosproject.net.PortNumber;
33import org.onosproject.net.flow.DefaultFlowRule;
34import org.onosproject.net.flow.DefaultTrafficSelector;
35import org.onosproject.net.flow.DefaultTrafficTreatment;
36import org.onosproject.net.flow.FlowRule;
37import org.onosproject.net.flow.TrafficSelector;
38import org.onosproject.net.flow.TrafficTreatment;
Brian O'Connor406e2642016-04-18 11:45:35 -070039import org.onosproject.net.flow.instructions.L2ModificationInstruction;
40import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
41import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction;
42import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
43import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
44import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
45import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
46import org.onosproject.net.flow.instructions.L3ModificationInstruction;
47import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpEthInstruction;
48import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpIPInstruction;
49import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpOpInstruction;
50import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
51import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
52import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080053import org.onosproject.net.intent.FlowRuleIntent;
54import org.onosproject.net.intent.Intent;
55import org.onosproject.net.intent.IntentCompiler;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080056import org.onosproject.net.intent.LinkCollectionIntent;
Brian O'Connor406e2642016-04-18 11:45:35 -070057import org.onosproject.net.intent.impl.IntentCompilationException;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080058
59import java.util.ArrayList;
Sho SHIMIZU98ffca82015-05-11 08:39:24 -070060import java.util.Collections;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080061import java.util.List;
62import java.util.Set;
63import java.util.stream.Collectors;
64
65@Component(immediate = true)
66public class LinkCollectionIntentCompiler implements IntentCompiler<LinkCollectionIntent> {
67
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuskabdbdd242016-03-01 01:55:55 -080069 protected IntentConfigurableRegistrator registrator;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080070
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected CoreService coreService;
73
74 private ApplicationId appId;
75
76 @Activate
77 public void activate() {
78 appId = coreService.registerApplication("org.onosproject.net.intent");
Thomas Vachuskabdbdd242016-03-01 01:55:55 -080079 registrator.registerCompiler(LinkCollectionIntent.class, this, false);
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080080 }
81
82 @Deactivate
83 public void deactivate() {
Thomas Vachuskabdbdd242016-03-01 01:55:55 -080084 registrator.unregisterCompiler(LinkCollectionIntent.class, false);
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080085 }
86
87 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -080088 public List<Intent> compile(LinkCollectionIntent intent, List<Intent> installable) {
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080089 SetMultimap<DeviceId, PortNumber> inputPorts = HashMultimap.create();
90 SetMultimap<DeviceId, PortNumber> outputPorts = HashMultimap.create();
91
92 for (Link link : intent.links()) {
Jonathan Hart066244c2015-06-23 09:46:19 -070093 inputPorts.put(link.dst().deviceId(), link.dst().port());
94 outputPorts.put(link.src().deviceId(), link.src().port());
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080095 }
96
97 for (ConnectPoint ingressPoint : intent.ingressPoints()) {
98 inputPorts.put(ingressPoint.deviceId(), ingressPoint.port());
99 }
100
101 for (ConnectPoint egressPoint : intent.egressPoints()) {
102 outputPorts.put(egressPoint.deviceId(), egressPoint.port());
103 }
104
105 List<FlowRule> rules = new ArrayList<>();
106 for (DeviceId deviceId: outputPorts.keys()) {
107 rules.addAll(createRules(intent, deviceId, inputPorts.get(deviceId), outputPorts.get(deviceId)));
108 }
Sho SHIMIZU98ffca82015-05-11 08:39:24 -0700109 return Collections.singletonList(new FlowRuleIntent(appId, rules, intent.resources()));
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800110 }
111
112 private List<FlowRule> createRules(LinkCollectionIntent intent, DeviceId deviceId,
113 Set<PortNumber> inPorts, Set<PortNumber> outPorts) {
114 Set<PortNumber> ingressPorts = intent.ingressPoints().stream()
115 .filter(point -> point.deviceId().equals(deviceId))
116 .map(ConnectPoint::port)
117 .collect(Collectors.toSet());
118
119 TrafficTreatment.Builder defaultTreatmentBuilder = DefaultTrafficTreatment.builder();
120 outPorts.stream()
121 .forEach(defaultTreatmentBuilder::setOutput);
122 TrafficTreatment defaultTreatment = defaultTreatmentBuilder.build();
123
124 TrafficTreatment.Builder ingressTreatmentBuilder = DefaultTrafficTreatment.builder(intent.treatment());
125 outPorts.stream()
126 .forEach(ingressTreatmentBuilder::setOutput);
127 TrafficTreatment ingressTreatment = ingressTreatmentBuilder.build();
128
Brian O'Connor406e2642016-04-18 11:45:35 -0700129 TrafficSelector defaultTrafficSelector = applyTreatmentToSelector(intent.selector(), ingressTreatment);
130
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800131 List<FlowRule> rules = new ArrayList<>(inPorts.size());
132 for (PortNumber inPort: inPorts) {
Brian O'Connor406e2642016-04-18 11:45:35 -0700133 TrafficSelector.Builder selectorBuilder;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800134 TrafficTreatment treatment;
135 if (ingressPorts.contains(inPort)) {
Brian O'Connor406e2642016-04-18 11:45:35 -0700136 selectorBuilder = DefaultTrafficSelector.builder(intent.selector());
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800137 treatment = ingressTreatment;
138 } else {
Brian O'Connor406e2642016-04-18 11:45:35 -0700139 selectorBuilder = DefaultTrafficSelector.builder(defaultTrafficSelector);
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800140 treatment = defaultTreatment;
141 }
Brian O'Connor406e2642016-04-18 11:45:35 -0700142 TrafficSelector selector = selectorBuilder.matchInPort(inPort).build();
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800143
Brian O'Connor81134662015-06-25 17:23:33 -0400144 FlowRule rule = DefaultFlowRule.builder()
145 .forDevice(deviceId)
146 .withSelector(selector)
147 .withTreatment(treatment)
148 .withPriority(intent.priority())
149 .fromApp(appId)
150 .makePermanent()
151 .build();
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800152 rules.add(rule);
153 }
154
155 return rules;
156 }
Brian O'Connor406e2642016-04-18 11:45:35 -0700157
158 private TrafficSelector applyTreatmentToSelector(TrafficSelector selector, TrafficTreatment treatment) {
159 TrafficSelector.Builder defaultSelectorBuilder = DefaultTrafficSelector.builder(selector);
160 treatment.allInstructions().forEach(instruction -> {
161 switch (instruction.type()) {
162 case L0MODIFICATION:
163 case L1MODIFICATION:
164 throw new IntentCompilationException("L0 and L1 mods not supported");
165 case L2MODIFICATION:
166 L2ModificationInstruction l2mod = (L2ModificationInstruction) instruction;
167 switch (l2mod.subtype()) {
168 case ETH_SRC:
169 case ETH_DST:
170 ModEtherInstruction ethInstr = (ModEtherInstruction) l2mod;
171 switch (ethInstr.subtype()) {
172 case ETH_SRC:
173 defaultSelectorBuilder.matchEthSrc(ethInstr.mac());
174 break;
175 case ETH_DST:
176 defaultSelectorBuilder.matchEthDst(ethInstr.mac());
177 break;
178 default:
179 throw new IntentCompilationException("Bad eth subtype");
180 }
181 break;
182 case VLAN_ID:
183 ModVlanIdInstruction vlanIdInstr = (ModVlanIdInstruction) l2mod;
184 defaultSelectorBuilder.matchVlanId(vlanIdInstr.vlanId());
185 break;
186 case VLAN_PUSH:
187 //FIXME
188 break;
189 case VLAN_POP:
190 //TODO how do we handle dropped label? remove the selector?
191 throw new IntentCompilationException("Can't handle pop label");
192 case VLAN_PCP:
193 ModVlanPcpInstruction vlanPcpInstruction = (ModVlanPcpInstruction) l2mod;
194 defaultSelectorBuilder.matchVlanPcp(vlanPcpInstruction.vlanPcp());
195 break;
196 case MPLS_LABEL:
197 case MPLS_PUSH:
198 //FIXME
199 ModMplsLabelInstruction mplsInstr = (ModMplsLabelInstruction) l2mod;
200 defaultSelectorBuilder.matchMplsLabel(mplsInstr.label());
201 break;
202 case MPLS_POP:
203 //TODO how do we handle dropped label? remove the selector?
204 throw new IntentCompilationException("Can't handle pop label");
205 case DEC_MPLS_TTL:
206 // no-op
207 break;
208 case MPLS_BOS:
209 ModMplsBosInstruction mplsBosInstr = (ModMplsBosInstruction) l2mod;
210 defaultSelectorBuilder.matchMplsBos(mplsBosInstr.mplsBos());
211 break;
212 case TUNNEL_ID:
213 ModTunnelIdInstruction tunInstr = (ModTunnelIdInstruction) l2mod;
214 defaultSelectorBuilder.matchTunnelId(tunInstr.tunnelId());
215 break;
216 default:
217 throw new IntentCompilationException("Unknown L2 Modification instruction");
218 }
219 break;
220 case L3MODIFICATION:
221 L3ModificationInstruction l3mod = (L3ModificationInstruction) instruction;
222 // TODO check ethernet proto
223 switch (l3mod.subtype()) {
224 case IPV4_SRC:
225 case IPV4_DST:
226 case IPV6_SRC:
227 case IPV6_DST:
228 ModIPInstruction ipInstr = (ModIPInstruction) l3mod;
229 // TODO check if ip falls in original prefix
230 IpPrefix prefix = ipInstr.ip().toIpPrefix();
231 switch (ipInstr.subtype()) {
232 case IPV4_SRC:
233 defaultSelectorBuilder.matchIPSrc(prefix);
234 break;
235 case IPV4_DST:
236 defaultSelectorBuilder.matchIPSrc(prefix);
237 break;
238 case IPV6_SRC:
239 defaultSelectorBuilder.matchIPv6Src(prefix);
240 break;
241 case IPV6_DST:
242 defaultSelectorBuilder.matchIPv6Dst(prefix);
243 break;
244 default:
245 throw new IntentCompilationException("Bad type for IP instruction");
246 }
247 break;
248 case IPV6_FLABEL:
249 ModIPv6FlowLabelInstruction ipFlowInstr = (ModIPv6FlowLabelInstruction) l3mod;
250 defaultSelectorBuilder.matchIPv6FlowLabel(ipFlowInstr.flowLabel());
251 break;
252 case DEC_TTL:
253 // no-op
254 break;
255 case TTL_OUT:
256 // no-op
257 break;
258 case TTL_IN:
259 // no-op
260 break;
261 case ARP_SPA:
262 ModArpIPInstruction arpIpInstr = (ModArpIPInstruction) l3mod;
263 if (arpIpInstr.ip().isIp4()) {
264 defaultSelectorBuilder.matchArpSpa((Ip4Address) arpIpInstr.ip());
265 } else {
266 throw new IntentCompilationException("IPv6 not supported for ARP");
267 }
268 break;
269 case ARP_SHA:
270 ModArpEthInstruction arpEthInstr = (ModArpEthInstruction) l3mod;
271 defaultSelectorBuilder.matchArpSha(arpEthInstr.mac());
272 break;
273 case ARP_OP:
274 ModArpOpInstruction arpOpInstr = (ModArpOpInstruction) l3mod;
275 //FIXME is the long to int cast safe?
276 defaultSelectorBuilder.matchArpOp((int) arpOpInstr.op());
277 break;
278 default:
279 throw new IntentCompilationException("Unknown L3 Modification instruction");
280 }
281 break;
282 case L4MODIFICATION:
283 if (instruction instanceof ModTransportPortInstruction) {
284 // TODO check IP proto
285 ModTransportPortInstruction l4mod = (ModTransportPortInstruction) instruction;
286 switch (l4mod.subtype()) {
287 case TCP_SRC:
288 defaultSelectorBuilder.matchTcpSrc(l4mod.port());
289 break;
290 case TCP_DST:
291 defaultSelectorBuilder.matchTcpDst(l4mod.port());
292 break;
293 case UDP_SRC:
294 defaultSelectorBuilder.matchUdpSrc(l4mod.port());
295 break;
296 case UDP_DST:
297 defaultSelectorBuilder.matchUdpDst(l4mod.port());
298 break;
299 default:
300 throw new IntentCompilationException("Unknown L4 Modification instruction");
301 }
302 } else {
303 throw new IntentCompilationException("Unknown L4 Modification instruction");
304 }
305 break;
306 case NOACTION:
307 case OUTPUT:
308 case GROUP:
309 case QUEUE:
310 case TABLE:
311 case METER:
312 case METADATA:
313 case EXTENSION: // TODO is extension no-op or unsupported?
314 // Nothing to do
315 break;
316 default:
317 throw new IntentCompilationException("Unknown instruction type");
318 }
319 });
320 return defaultSelectorBuilder.build();
321 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800322}