blob: 0adc5754719cd561ef191a94468ef89c34d5ccb1 [file] [log] [blame]
alshabib0ccde6d2015-05-30 18:22:36 -07001/*
2 * Copyright 2015 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 */
16package org.onosproject.driver.pipeline;
17
18import org.onlab.osgi.ServiceDirectory;
Jonathan Hartdfc3b862015-07-01 14:49:56 -070019import org.onlab.packet.EthType;
20import org.onosproject.core.ApplicationId;
21import org.onosproject.core.CoreService;
alshabib2cc73cb2015-06-30 20:26:56 -070022import org.onosproject.net.DefaultAnnotations;
23import org.onosproject.net.Device;
alshabib0ccde6d2015-05-30 18:22:36 -070024import org.onosproject.net.DeviceId;
alshabib2cc73cb2015-06-30 20:26:56 -070025import org.onosproject.net.MastershipRole;
alshabib0ccde6d2015-05-30 18:22:36 -070026import org.onosproject.net.PortNumber;
27import org.onosproject.net.behaviour.Pipeliner;
28import org.onosproject.net.behaviour.PipelinerContext;
alshabib2cc73cb2015-06-30 20:26:56 -070029import org.onosproject.net.device.DefaultDeviceDescription;
30import org.onosproject.net.device.DeviceDescription;
31import org.onosproject.net.device.DeviceProvider;
32import org.onosproject.net.device.DeviceProviderRegistry;
33import org.onosproject.net.device.DeviceProviderService;
34import org.onosproject.net.device.DeviceService;
alshabib0ccde6d2015-05-30 18:22:36 -070035import org.onosproject.net.driver.AbstractHandlerBehaviour;
36import org.onosproject.net.flow.DefaultFlowRule;
Jonathan Hartdfc3b862015-07-01 14:49:56 -070037import org.onosproject.net.flow.DefaultTrafficSelector;
alshabib0ccde6d2015-05-30 18:22:36 -070038import org.onosproject.net.flow.DefaultTrafficTreatment;
39import org.onosproject.net.flow.FlowRule;
40import org.onosproject.net.flow.FlowRuleOperations;
41import org.onosproject.net.flow.FlowRuleOperationsContext;
42import org.onosproject.net.flow.FlowRuleService;
43import org.onosproject.net.flow.TrafficSelector;
44import org.onosproject.net.flow.TrafficTreatment;
45import org.onosproject.net.flow.instructions.Instructions;
46import org.onosproject.net.flowobjective.FilteringObjective;
47import org.onosproject.net.flowobjective.ForwardingObjective;
48import org.onosproject.net.flowobjective.NextObjective;
49import org.onosproject.net.flowobjective.ObjectiveError;
Jonathan Hartdfc3b862015-07-01 14:49:56 -070050import org.onosproject.net.packet.PacketPriority;
alshabib2cc73cb2015-06-30 20:26:56 -070051import org.onosproject.net.provider.AbstractProvider;
52import org.onosproject.net.provider.ProviderId;
alshabib0ccde6d2015-05-30 18:22:36 -070053import org.slf4j.Logger;
54
alshabib2cc73cb2015-06-30 20:26:56 -070055import static com.google.common.base.Preconditions.checkNotNull;
alshabib0ccde6d2015-05-30 18:22:36 -070056import static org.slf4j.LoggerFactory.getLogger;
57
58/**
59 * Simple single table pipeline abstraction.
60 */
61public class OLTPipeline extends AbstractHandlerBehaviour implements Pipeliner {
62
63 private final Logger log = getLogger(getClass());
64
alshabib2cc73cb2015-06-30 20:26:56 -070065 static final ProviderId PID = new ProviderId("olt", "org.onosproject.olt", true);
66
67 static final String DEVICE = "isAccess";
68 static final String OLT = "true";
69
alshabib0ccde6d2015-05-30 18:22:36 -070070 private ServiceDirectory serviceDirectory;
71 private FlowRuleService flowRuleService;
72 private DeviceId deviceId;
Jonathan Hartdfc3b862015-07-01 14:49:56 -070073 private CoreService coreService;
74
75 private ApplicationId appId;
alshabib0ccde6d2015-05-30 18:22:36 -070076
alshabib2cc73cb2015-06-30 20:26:56 -070077 private DeviceProvider provider = new AnnotationProvider();
78
alshabibb32cefe2015-06-08 18:15:05 -070079
alshabib0ccde6d2015-05-30 18:22:36 -070080 @Override
81 public void init(DeviceId deviceId, PipelinerContext context) {
82 this.serviceDirectory = context.directory();
83 this.deviceId = deviceId;
alshabib2cc73cb2015-06-30 20:26:56 -070084 DeviceProviderRegistry registry =
85 serviceDirectory.get(DeviceProviderRegistry.class);
alshabib0ccde6d2015-05-30 18:22:36 -070086 flowRuleService = serviceDirectory.get(FlowRuleService.class);
Jonathan Hartdfc3b862015-07-01 14:49:56 -070087 coreService = serviceDirectory.get(CoreService.class);
alshabibb32cefe2015-06-08 18:15:05 -070088
alshabib2cc73cb2015-06-30 20:26:56 -070089 try {
90 DeviceProviderService providerService = registry.register(provider);
91 providerService.deviceConnected(deviceId,
92 description(deviceId, DEVICE, OLT));
93 } finally {
94 registry.unregister(provider);
95 }
96
Jonathan Hartdfc3b862015-07-01 14:49:56 -070097 appId = coreService.registerApplication(
98 "org.onosproject.driver.OLTPipeline");
99
100 TrafficSelector selector = DefaultTrafficSelector.builder()
101 .matchEthType(EthType.EtherType.EAPOL.ethType().toShort())
102 .build();
103
alshabibaf734ff2015-07-01 16:35:26 -0700104 TrafficSelector arpSelector = DefaultTrafficSelector.builder()
105 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
106 .build();
107
Jonathan Hartdfc3b862015-07-01 14:49:56 -0700108 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
109 .punt()
110 .build();
111
112 FlowRule flowRule = new DefaultFlowRule(deviceId, selector, treatment,
113 PacketPriority.CONTROL.priorityValue(),
114 appId, 0, true, null);
115
alshabibaf734ff2015-07-01 16:35:26 -0700116 FlowRule arpRule = new DefaultFlowRule(deviceId, arpSelector, treatment,
117 PacketPriority.CONTROL.priorityValue(),
118 appId, 0, true, null);
119
120 flowRuleService.applyFlowRules(flowRule, arpRule);
alshabibb32cefe2015-06-08 18:15:05 -0700121 }
122
alshabib0ccde6d2015-05-30 18:22:36 -0700123 @Override
124 public void filter(FilteringObjective filter) {
125 throw new UnsupportedOperationException("Single table does not filter.");
126 }
127
128 @Override
129 public void forward(ForwardingObjective fwd) {
alshabib0ccde6d2015-05-30 18:22:36 -0700130 FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
131
132 if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
133 throw new UnsupportedOperationException(
134 "Only VERSATILE is supported.");
135 }
136
137 boolean isPunt = fwd.treatment().immediate().stream().anyMatch(i -> {
138 if (i instanceof Instructions.OutputInstruction) {
139 Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
140 return out.port().equals(PortNumber.CONTROLLER);
141 }
142 return false;
143 });
144
145 if (isPunt) {
146 return;
147 }
148
149 TrafficSelector selector = fwd.selector();
150 TrafficTreatment treatment = fwd.treatment();
151 if ((fwd.treatment().deferred().size() == 0) &&
152 (fwd.treatment().immediate().size() == 0) &&
153 (fwd.treatment().tableTransition() == null) &&
154 (!fwd.treatment().clearedDeferred())) {
155 TrafficTreatment.Builder flowTreatment = DefaultTrafficTreatment.builder();
156 flowTreatment.add(Instructions.createDrop());
157 treatment = flowTreatment.build();
158 }
159
160 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
161 .forDevice(deviceId)
162 .withSelector(selector)
163 .withTreatment(fwd.treatment())
164 .fromApp(fwd.appId())
165 .withPriority(fwd.priority());
166
167 if (fwd.permanent()) {
168 ruleBuilder.makePermanent();
169 } else {
170 ruleBuilder.makeTemporary(fwd.timeout());
171 }
172
173
174 switch (fwd.op()) {
175
176 case ADD:
177 flowBuilder.add(ruleBuilder.build());
178 break;
179 case REMOVE:
180 flowBuilder.remove(ruleBuilder.build());
181 break;
182 default:
183 log.warn("Unknown operation {}", fwd.op());
184 }
185
186 flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
187 @Override
188 public void onSuccess(FlowRuleOperations ops) {
189 if (fwd.context().isPresent()) {
190 fwd.context().get().onSuccess(fwd);
191 }
192 }
193
194 @Override
195 public void onError(FlowRuleOperations ops) {
196 if (fwd.context().isPresent()) {
197 fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
198 }
199 }
200 }));
201
202 }
203
204 @Override
205 public void next(NextObjective nextObjective) {
206 throw new UnsupportedOperationException("Single table does not next hop.");
207 }
208
alshabib2cc73cb2015-06-30 20:26:56 -0700209 /**
210 * Build a device description.
211 * @param deviceId a deviceId
212 * @param key the key of the annotation
213 * @param value the value for the annotation
214 * @return a device description
215 */
216 private DeviceDescription description(DeviceId deviceId, String key, String value) {
217 DeviceService deviceService = serviceDirectory.get(DeviceService.class);
218 Device device = deviceService.getDevice(deviceId);
219
220 checkNotNull(device, "Device not found in device service.");
221
222 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
223 if (value != null) {
224 builder.set(key, value);
225 } else {
226 builder.remove(key);
227 }
228 return new DefaultDeviceDescription(device.id().uri(), device.type(),
229 device.manufacturer(), device.hwVersion(),
230 device.swVersion(), device.serialNumber(),
231 device.chassisId(), builder.build());
232 }
233
234 /**
235 * Simple ancillary provider used to annotate device.
236 */
237 private static final class AnnotationProvider
238 extends AbstractProvider implements DeviceProvider {
239 private AnnotationProvider() {
240 super(PID);
241 }
242
243 @Override
244 public void triggerProbe(DeviceId deviceId) {
245 }
246
247 @Override
248 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
249 }
250
251 @Override
252 public boolean isReachable(DeviceId deviceId) {
253 return false;
254 }
255 }
256
alshabib0ccde6d2015-05-30 18:22:36 -0700257}