Simple software switch pipeline.
Change-Id: Iaaee946967cb339a875564d962d3467899df0d31
Showing
6 changed files
with
555 additions
and
9 deletions
... | @@ -52,6 +52,12 @@ | ... | @@ -52,6 +52,12 @@ |
52 | <artifactId>onos-of-api</artifactId> | 52 | <artifactId>onos-of-api</artifactId> |
53 | </dependency> | 53 | </dependency> |
54 | 54 | ||
55 | + <dependency> | ||
56 | + <groupId>org.onosproject</groupId> | ||
57 | + <artifactId>onos-core-serializers</artifactId> | ||
58 | + <version>1.2.0-SNAPSHOT</version> | ||
59 | + </dependency> | ||
60 | + | ||
55 | <dependency> | 61 | <dependency> |
56 | <groupId>org.easymock</groupId> | 62 | <groupId>org.easymock</groupId> |
57 | <artifactId>easymock</artifactId> | 63 | <artifactId>easymock</artifactId> |
... | @@ -63,6 +69,8 @@ | ... | @@ -63,6 +69,8 @@ |
63 | <artifactId>org.apache.felix.scr.annotations</artifactId> | 69 | <artifactId>org.apache.felix.scr.annotations</artifactId> |
64 | </dependency> | 70 | </dependency> |
65 | 71 | ||
72 | + | ||
73 | + | ||
66 | </dependencies> | 74 | </dependencies> |
67 | 75 | ||
68 | <build> | 76 | <build> | ... | ... |
... | @@ -29,12 +29,11 @@ import org.projectfloodlight.openflow.types.TableId; | ... | @@ -29,12 +29,11 @@ import org.projectfloodlight.openflow.types.TableId; |
29 | import java.util.Collections; | 29 | import java.util.Collections; |
30 | import java.util.concurrent.atomic.AtomicBoolean; | 30 | import java.util.concurrent.atomic.AtomicBoolean; |
31 | 31 | ||
32 | -//import java.util.ArrayList; | ||
33 | 32 | ||
34 | /** | 33 | /** |
35 | - * Corsa switch driver for BGP Router deployment. | 34 | + * Corsa switch handshaker. |
36 | */ | 35 | */ |
37 | -public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch { | 36 | +public class CorsaSwitchHandShaker extends AbstractOpenFlowSwitch { |
38 | 37 | ||
39 | private AtomicBoolean handShakeComplete = new AtomicBoolean(false); | 38 | private AtomicBoolean handShakeComplete = new AtomicBoolean(false); |
40 | 39 | ... | ... |
... | @@ -13,6 +13,10 @@ import org.onosproject.net.flow.TrafficSelector; | ... | @@ -13,6 +13,10 @@ import org.onosproject.net.flow.TrafficSelector; |
13 | import org.onosproject.net.flow.TrafficTreatment; | 13 | import org.onosproject.net.flow.TrafficTreatment; |
14 | import org.slf4j.Logger; | 14 | import org.slf4j.Logger; |
15 | 15 | ||
16 | +/** | ||
17 | + * Driver for Corsa TTP. | ||
18 | + * | ||
19 | + */ | ||
16 | public class CorsaPipeline extends OVSCorsaPipeline { | 20 | public class CorsaPipeline extends OVSCorsaPipeline { |
17 | 21 | ||
18 | private final Logger log = getLogger(getClass()); | 22 | private final Logger log = getLogger(getClass()); |
... | @@ -37,7 +41,6 @@ public class CorsaPipeline extends OVSCorsaPipeline { | ... | @@ -37,7 +41,6 @@ public class CorsaPipeline extends OVSCorsaPipeline { |
37 | .makePermanent() | 41 | .makePermanent() |
38 | .forTable(VLAN_MPLS_TABLE).build(); | 42 | .forTable(VLAN_MPLS_TABLE).build(); |
39 | 43 | ||
40 | - | ||
41 | ops = install ? ops.add(rule) : ops.remove(rule); | 44 | ops = install ? ops.add(rule) : ops.remove(rule); |
42 | 45 | ||
43 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | 46 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ... | ... |
... | @@ -102,7 +102,6 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -102,7 +102,6 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
102 | protected static final int ACL_TABLE = 60; | 102 | protected static final int ACL_TABLE = 60; |
103 | protected static final int MAC_LEARNING_TABLE = 254; | 103 | protected static final int MAC_LEARNING_TABLE = 254; |
104 | 104 | ||
105 | - @SuppressWarnings("unused") | ||
106 | private static final int HIGHEST_PRIORITY = 0xffff; | 105 | private static final int HIGHEST_PRIORITY = 0xffff; |
107 | private static final int DEFAULT_PRIORITY = 0x8000; | 106 | private static final int DEFAULT_PRIORITY = 0x8000; |
108 | private static final int LOWEST_PRIORITY = 0x0; | 107 | private static final int LOWEST_PRIORITY = 0x0; | ... | ... |
1 | +package org.onosproject.driver.pipeline; | ||
2 | + | ||
3 | +import static org.slf4j.LoggerFactory.getLogger; | ||
4 | + | ||
5 | +import java.util.ArrayList; | ||
6 | +import java.util.Collection; | ||
7 | +import java.util.Collections; | ||
8 | +import java.util.concurrent.ConcurrentHashMap; | ||
9 | + | ||
10 | +import org.onlab.osgi.ServiceDirectory; | ||
11 | +import org.onlab.packet.Ethernet; | ||
12 | +import org.onlab.packet.MacAddress; | ||
13 | +import org.onlab.packet.VlanId; | ||
14 | +import org.onlab.util.KryoNamespace; | ||
15 | +import org.onosproject.core.ApplicationId; | ||
16 | +import org.onosproject.core.CoreService; | ||
17 | +import org.onosproject.net.DeviceId; | ||
18 | +import org.onosproject.net.PortNumber; | ||
19 | +import org.onosproject.net.behaviour.NextGroup; | ||
20 | +import org.onosproject.net.behaviour.Pipeliner; | ||
21 | +import org.onosproject.net.behaviour.PipelinerContext; | ||
22 | +import org.onosproject.net.driver.AbstractHandlerBehaviour; | ||
23 | +import org.onosproject.net.flow.DefaultFlowRule; | ||
24 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
25 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
26 | +import org.onosproject.net.flow.FlowRule; | ||
27 | +import org.onosproject.net.flow.FlowRuleOperations; | ||
28 | +import org.onosproject.net.flow.FlowRuleOperationsContext; | ||
29 | +import org.onosproject.net.flow.FlowRuleService; | ||
30 | +import org.onosproject.net.flow.TrafficSelector; | ||
31 | +import org.onosproject.net.flow.TrafficTreatment; | ||
32 | +import org.onosproject.net.flow.criteria.Criteria; | ||
33 | +import org.onosproject.net.flow.criteria.Criterion; | ||
34 | +import org.onosproject.net.flow.criteria.EthCriterion; | ||
35 | +import org.onosproject.net.flow.criteria.EthTypeCriterion; | ||
36 | +import org.onosproject.net.flow.criteria.IPCriterion; | ||
37 | +import org.onosproject.net.flow.criteria.PortCriterion; | ||
38 | +import org.onosproject.net.flow.criteria.VlanIdCriterion; | ||
39 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
40 | +import org.onosproject.net.flowobjective.FlowObjectiveStore; | ||
41 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
42 | +import org.onosproject.net.flowobjective.NextObjective; | ||
43 | +import org.onosproject.net.flowobjective.Objective; | ||
44 | +import org.onosproject.net.flowobjective.ObjectiveError; | ||
45 | +import org.slf4j.Logger; | ||
46 | +import org.onosproject.store.serializers.KryoNamespaces; | ||
47 | + | ||
48 | +/** | ||
49 | + * Simple 2-Table Pipeline for Software/NPU based routers. This pipeline | ||
50 | + * does not forward IP traffic to next-hop groups. Instead it forwards traffic | ||
51 | + * using OF FlowMod actions. | ||
52 | + */ | ||
53 | +public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipeliner { | ||
54 | + | ||
55 | + protected static final int FILTER_TABLE = 0; | ||
56 | + protected static final int FIB_TABLE = 1; | ||
57 | + | ||
58 | + private static final int DROP_PRIORITY = 0; | ||
59 | + private static final int DEFAULT_PRIORITY = 0x8000; | ||
60 | + private static final int HIGHEST_PRIORITY = 0xffff; | ||
61 | + | ||
62 | + private ServiceDirectory serviceDirectory; | ||
63 | + protected FlowRuleService flowRuleService; | ||
64 | + private CoreService coreService; | ||
65 | + private FlowObjectiveStore flowObjectiveStore; | ||
66 | + protected DeviceId deviceId; | ||
67 | + protected ApplicationId appId; | ||
68 | + private ApplicationId driverId; | ||
69 | + private Collection<Filter> filters; | ||
70 | + private Collection<ForwardingObjective> pendingVersatiles; | ||
71 | + | ||
72 | + private KryoNamespace appKryo = new KryoNamespace.Builder() | ||
73 | + .register(DummyGroup.class) | ||
74 | + .register(KryoNamespaces.API) | ||
75 | + .register(byte[].class) | ||
76 | + .build(); | ||
77 | + | ||
78 | + private final Logger log = getLogger(getClass()); | ||
79 | + | ||
80 | + @Override | ||
81 | + public void init(DeviceId deviceId, PipelinerContext context) { | ||
82 | + this.serviceDirectory = context.directory(); | ||
83 | + this.deviceId = deviceId; | ||
84 | + coreService = serviceDirectory.get(CoreService.class); | ||
85 | + flowRuleService = serviceDirectory.get(FlowRuleService.class); | ||
86 | + flowObjectiveStore = context.store(); | ||
87 | + driverId = coreService.registerApplication( | ||
88 | + "org.onosproject.driver.OVSCorsaPipeline"); | ||
89 | + filters = Collections.newSetFromMap(new ConcurrentHashMap<Filter, Boolean>()); | ||
90 | + pendingVersatiles = Collections.newSetFromMap( | ||
91 | + new ConcurrentHashMap<ForwardingObjective, Boolean>()); | ||
92 | + initializePipeline(); | ||
93 | + } | ||
94 | + | ||
95 | + @Override | ||
96 | + public void filter(FilteringObjective filteringObjective) { | ||
97 | + if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { | ||
98 | + processFilter(filteringObjective, | ||
99 | + filteringObjective.op() == Objective.Operation.ADD, | ||
100 | + filteringObjective.appId()); | ||
101 | + } else { | ||
102 | + fail(filteringObjective, ObjectiveError.UNSUPPORTED); | ||
103 | + } | ||
104 | + } | ||
105 | + | ||
106 | + @Override | ||
107 | + public void forward(ForwardingObjective fwd) { | ||
108 | + Collection<FlowRule> rules; | ||
109 | + FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder(); | ||
110 | + | ||
111 | + rules = processForward(fwd); | ||
112 | + switch (fwd.op()) { | ||
113 | + case ADD: | ||
114 | + rules.stream() | ||
115 | + .filter(rule -> rule != null) | ||
116 | + .forEach(flowOpsBuilder::add); | ||
117 | + break; | ||
118 | + case REMOVE: | ||
119 | + rules.stream() | ||
120 | + .filter(rule -> rule != null) | ||
121 | + .forEach(flowOpsBuilder::remove); | ||
122 | + break; | ||
123 | + default: | ||
124 | + fail(fwd, ObjectiveError.UNKNOWN); | ||
125 | + log.warn("Unknown forwarding type {}", fwd.op()); | ||
126 | + } | ||
127 | + | ||
128 | + | ||
129 | + flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() { | ||
130 | + @Override | ||
131 | + public void onSuccess(FlowRuleOperations ops) { | ||
132 | + pass(fwd); | ||
133 | + } | ||
134 | + | ||
135 | + @Override | ||
136 | + public void onError(FlowRuleOperations ops) { | ||
137 | + fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); | ||
138 | + } | ||
139 | + })); | ||
140 | + | ||
141 | + } | ||
142 | + | ||
143 | + @Override | ||
144 | + public void next(NextObjective nextObjective) { | ||
145 | + switch (nextObjective.type()) { | ||
146 | + case SIMPLE: | ||
147 | + Collection<TrafficTreatment> treatments = nextObjective.next(); | ||
148 | + if (treatments.size() != 1) { | ||
149 | + log.error("Next Objectives of type Simple should only have a " | ||
150 | + + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id()); | ||
151 | + fail(nextObjective, ObjectiveError.BADPARAMS); | ||
152 | + return; | ||
153 | + } | ||
154 | + processSimpleNextObjective(nextObjective); | ||
155 | + break; | ||
156 | + case HASHED: | ||
157 | + case BROADCAST: | ||
158 | + case FAILOVER: | ||
159 | + fail(nextObjective, ObjectiveError.UNSUPPORTED); | ||
160 | + log.warn("Unsupported next objective type {}", nextObjective.type()); | ||
161 | + break; | ||
162 | + default: | ||
163 | + fail(nextObjective, ObjectiveError.UNKNOWN); | ||
164 | + log.warn("Unknown next objective type {}", nextObjective.type()); | ||
165 | + } | ||
166 | + } | ||
167 | + | ||
168 | + private void pass(Objective obj) { | ||
169 | + if (obj.context().isPresent()) { | ||
170 | + obj.context().get().onSuccess(obj); | ||
171 | + } | ||
172 | + } | ||
173 | + | ||
174 | + private void fail(Objective obj, ObjectiveError error) { | ||
175 | + if (obj.context().isPresent()) { | ||
176 | + obj.context().get().onError(obj, error); | ||
177 | + } | ||
178 | + } | ||
179 | + | ||
180 | + | ||
181 | + private void initializePipeline() { | ||
182 | + //Drop rules for both tables | ||
183 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
184 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
185 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
186 | + | ||
187 | + treatment.drop(); | ||
188 | + | ||
189 | + FlowRule rule = DefaultFlowRule.builder() | ||
190 | + .forDevice(deviceId) | ||
191 | + .withSelector(selector.build()) | ||
192 | + .withTreatment(treatment.build()) | ||
193 | + .withPriority(DROP_PRIORITY) | ||
194 | + .fromApp(driverId) | ||
195 | + .makePermanent() | ||
196 | + .forTable(FILTER_TABLE) | ||
197 | + .build(); | ||
198 | + ops = ops.add(rule); | ||
199 | + | ||
200 | + rule = DefaultFlowRule.builder().forDevice(deviceId) | ||
201 | + .withSelector(selector.build()) | ||
202 | + .withTreatment(treatment.build()) | ||
203 | + .withPriority(DROP_PRIORITY) | ||
204 | + .fromApp(driverId) | ||
205 | + .makePermanent() | ||
206 | + .forTable(FIB_TABLE) | ||
207 | + .build(); | ||
208 | + ops = ops.add(rule); | ||
209 | + | ||
210 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
211 | + @Override | ||
212 | + public void onSuccess(FlowRuleOperations ops) { | ||
213 | + log.info("Provisioned drop rules in both tables"); | ||
214 | + } | ||
215 | + | ||
216 | + @Override | ||
217 | + public void onError(FlowRuleOperations ops) { | ||
218 | + log.info("Failed to provision drop rules"); | ||
219 | + } | ||
220 | + })); | ||
221 | + } | ||
222 | + | ||
223 | + private void processFilter(FilteringObjective filt, boolean install, | ||
224 | + ApplicationId applicationId) { | ||
225 | + // This driver only processes filtering criteria defined with switch | ||
226 | + // ports as the key | ||
227 | + PortCriterion p; EthCriterion e = null; VlanIdCriterion v = null; | ||
228 | + Collection<IPCriterion> ips = new ArrayList<IPCriterion>(); | ||
229 | + if (!filt.key().equals(Criteria.dummy()) && | ||
230 | + filt.key().type() == Criterion.Type.IN_PORT) { | ||
231 | + p = (PortCriterion) filt.key(); | ||
232 | + } else { | ||
233 | + log.warn("No key defined in filtering objective from app: {}. Not" | ||
234 | + + "processing filtering objective", applicationId); | ||
235 | + fail(filt, ObjectiveError.UNKNOWN); | ||
236 | + return; | ||
237 | + } | ||
238 | + | ||
239 | + // convert filtering conditions for switch-intfs into flowrules | ||
240 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
241 | + for (Criterion c : filt.conditions()) { | ||
242 | + if (c.type() == Criterion.Type.ETH_DST) { | ||
243 | + e = (EthCriterion) c; | ||
244 | + } else if (c.type() == Criterion.Type.VLAN_VID) { | ||
245 | + v = (VlanIdCriterion) c; | ||
246 | + } else if (c.type() == Criterion.Type.IPV4_DST) { | ||
247 | + ips.add((IPCriterion) c); | ||
248 | + } else { | ||
249 | + log.error("Unsupported filter {}", c); | ||
250 | + fail(filt, ObjectiveError.UNSUPPORTED); | ||
251 | + return; | ||
252 | + } | ||
253 | + } | ||
254 | + | ||
255 | + log.debug("adding Port/VLAN/MAC filtering rules in filter table: {}/{}/{}", | ||
256 | + p.port(), v.vlanId(), e.mac()); | ||
257 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
258 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
259 | + selector.matchInPort(p.port()); | ||
260 | + selector.matchVlanId(v.vlanId()); | ||
261 | + selector.matchEthDst(e.mac()); | ||
262 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
263 | + treatment.transition(FIB_TABLE); | ||
264 | + FlowRule rule = DefaultFlowRule.builder() | ||
265 | + .forDevice(deviceId) | ||
266 | + .withSelector(selector.build()) | ||
267 | + .withTreatment(treatment.build()) | ||
268 | + .withPriority(DEFAULT_PRIORITY) | ||
269 | + .fromApp(applicationId) | ||
270 | + .makePermanent() | ||
271 | + .forTable(FILTER_TABLE).build(); | ||
272 | + ops = ops.add(rule); | ||
273 | + | ||
274 | + for (IPCriterion ipaddr : ips) { | ||
275 | + log.debug("adding IP filtering rules in FIB table: {}", ipaddr.ip()); | ||
276 | + selector = DefaultTrafficSelector.builder(); | ||
277 | + treatment = DefaultTrafficTreatment.builder(); | ||
278 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
279 | + selector.matchIPDst(ipaddr.ip()); | ||
280 | + treatment.setOutput(PortNumber.CONTROLLER); | ||
281 | + rule = DefaultFlowRule.builder() | ||
282 | + .forDevice(deviceId) | ||
283 | + .withSelector(selector.build()) | ||
284 | + .withTreatment(treatment.build()) | ||
285 | + .withPriority(HIGHEST_PRIORITY) | ||
286 | + .fromApp(applicationId) | ||
287 | + .makePermanent() | ||
288 | + .forTable(FIB_TABLE).build(); | ||
289 | + ops = ops.add(rule); | ||
290 | + } | ||
291 | + | ||
292 | + // cache for later use | ||
293 | + Filter filter = new Filter(p, e, v, ips); | ||
294 | + filters.add(filter); | ||
295 | + // apply any pending versatile forwarding objectives | ||
296 | + for (ForwardingObjective fwd : pendingVersatiles) { | ||
297 | + Collection<FlowRule> ret = processVersatilesWithFilters(filter, fwd); | ||
298 | + for (FlowRule fr : ret) { | ||
299 | + ops.add(fr); | ||
300 | + } | ||
301 | + } | ||
302 | + | ||
303 | + ops = install ? ops.add(rule) : ops.remove(rule); | ||
304 | + // apply filtering flow rules | ||
305 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
306 | + @Override | ||
307 | + public void onSuccess(FlowRuleOperations ops) { | ||
308 | + log.info("Applied filtering rules"); | ||
309 | + pass(filt); | ||
310 | + } | ||
311 | + | ||
312 | + @Override | ||
313 | + public void onError(FlowRuleOperations ops) { | ||
314 | + log.info("Failed to apply filtering rules"); | ||
315 | + fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); | ||
316 | + } | ||
317 | + })); | ||
318 | + } | ||
319 | + | ||
320 | + private Collection<FlowRule> processForward(ForwardingObjective fwd) { | ||
321 | + switch (fwd.flag()) { | ||
322 | + case SPECIFIC: | ||
323 | + return processSpecific(fwd); | ||
324 | + case VERSATILE: | ||
325 | + return processVersatile(fwd); | ||
326 | + default: | ||
327 | + fail(fwd, ObjectiveError.UNKNOWN); | ||
328 | + log.warn("Unknown forwarding flag {}", fwd.flag()); | ||
329 | + } | ||
330 | + return Collections.emptySet(); | ||
331 | + } | ||
332 | + | ||
333 | + /** | ||
334 | + * SoftRouter has a single versatile table - the filter table. All versatile | ||
335 | + * flow rules must include the filtering rules. | ||
336 | + * | ||
337 | + * @param fwd The forwarding objective of type versatile | ||
338 | + * @return A collection of flow rules meant to be delivered to the flowrule | ||
339 | + * subsystem. May return empty collection in case of failures. | ||
340 | + */ | ||
341 | + private Collection<FlowRule> processVersatile(ForwardingObjective fwd) { | ||
342 | + if (filters.isEmpty()) { | ||
343 | + pendingVersatiles.add(fwd); | ||
344 | + return Collections.emptySet(); | ||
345 | + } | ||
346 | + Collection<FlowRule> flowrules = new ArrayList<FlowRule>(); | ||
347 | + for (Filter filter : filters) { | ||
348 | + flowrules.addAll(processVersatilesWithFilters(filter, fwd)); | ||
349 | + } | ||
350 | + return flowrules; | ||
351 | + } | ||
352 | + | ||
353 | + private Collection<FlowRule> processVersatilesWithFilters( | ||
354 | + Filter filt, ForwardingObjective fwd) { | ||
355 | + log.info("Processing versatile forwarding objective"); | ||
356 | + Collection<FlowRule> flows = new ArrayList<FlowRule>(); | ||
357 | + TrafficSelector match = fwd.selector(); | ||
358 | + EthTypeCriterion ethType = | ||
359 | + (EthTypeCriterion) match.getCriterion(Criterion.Type.ETH_TYPE); | ||
360 | + if (ethType == null) { | ||
361 | + log.error("Versatile forwarding objective must include ethType"); | ||
362 | + fail(fwd, ObjectiveError.UNKNOWN); | ||
363 | + return Collections.emptySet(); | ||
364 | + } | ||
365 | + | ||
366 | + if (ethType.ethType() == Ethernet.TYPE_ARP) { | ||
367 | + // need to install ARP request & reply flow rules for each interface filter | ||
368 | + | ||
369 | + // rule for ARP replies | ||
370 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
371 | + selector.matchInPort(filt.port()); | ||
372 | + selector.matchVlanId(filt.vlanId()); | ||
373 | + selector.matchEthDst(filt.mac()); | ||
374 | + selector.matchEthType(Ethernet.TYPE_ARP); | ||
375 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | ||
376 | + .fromApp(fwd.appId()) | ||
377 | + .withPriority(fwd.priority()) | ||
378 | + .forDevice(deviceId) | ||
379 | + .withSelector(selector.build()) | ||
380 | + .withTreatment(fwd.treatment()) | ||
381 | + .makePermanent() | ||
382 | + .forTable(FILTER_TABLE); | ||
383 | + flows.add(ruleBuilder.build()); | ||
384 | + | ||
385 | + //rule for ARP requests | ||
386 | + selector = DefaultTrafficSelector.builder(); | ||
387 | + selector.matchInPort(filt.port()); | ||
388 | + selector.matchVlanId(filt.vlanId()); | ||
389 | + selector.matchEthDst(MacAddress.BROADCAST); | ||
390 | + selector.matchEthType(Ethernet.TYPE_ARP); | ||
391 | + ruleBuilder = DefaultFlowRule.builder() | ||
392 | + .fromApp(fwd.appId()) | ||
393 | + .withPriority(fwd.priority()) | ||
394 | + .forDevice(deviceId) | ||
395 | + .withSelector(selector.build()) | ||
396 | + .withTreatment(fwd.treatment()) | ||
397 | + .makePermanent() | ||
398 | + .forTable(FILTER_TABLE); | ||
399 | + flows.add(ruleBuilder.build()); | ||
400 | + | ||
401 | + return flows; | ||
402 | + } | ||
403 | + // not handling other versatile flows | ||
404 | + return Collections.emptySet(); | ||
405 | + } | ||
406 | + | ||
407 | + /** | ||
408 | + * SoftRouter has a single specific table - the FIB Table. It emulates | ||
409 | + * LPM matching of dstIP by using higher priority flows for longer prefixes. | ||
410 | + * Flows are forwarded using flow-actions | ||
411 | + * | ||
412 | + * @param fwd The forwarding objective of type simple | ||
413 | + * @return A collection of flow rules meant to be delivered to the flowrule | ||
414 | + * subsystem. Typically the returned collection has a single flowrule. | ||
415 | + * May return empty collection in case of failures. | ||
416 | + * | ||
417 | + */ | ||
418 | + private Collection<FlowRule> processSpecific(ForwardingObjective fwd) { | ||
419 | + log.debug("Processing specific forwarding objective"); | ||
420 | + TrafficSelector selector = fwd.selector(); | ||
421 | + EthTypeCriterion ethType = | ||
422 | + (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); | ||
423 | + // XXX currently supporting only the L3 unicast table | ||
424 | + if (ethType == null || ethType.ethType() != Ethernet.TYPE_IPV4) { | ||
425 | + fail(fwd, ObjectiveError.UNSUPPORTED); | ||
426 | + return Collections.emptySet(); | ||
427 | + } | ||
428 | + | ||
429 | + TrafficSelector filteredSelector = | ||
430 | + DefaultTrafficSelector.builder() | ||
431 | + .matchEthType(Ethernet.TYPE_IPV4) | ||
432 | + .matchIPDst(((IPCriterion) | ||
433 | + selector.getCriterion(Criterion.Type.IPV4_DST)).ip()) | ||
434 | + .build(); | ||
435 | + | ||
436 | + TrafficTreatment tt = null; | ||
437 | + if (fwd.nextId() != null) { | ||
438 | + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); | ||
439 | + if (next == null) { | ||
440 | + log.error("next-id {} does not exist in store", fwd.nextId()); | ||
441 | + return Collections.emptySet(); | ||
442 | + } | ||
443 | + tt = appKryo.deserialize(next.data()); | ||
444 | + if (tt == null) { | ||
445 | + log.error("Error in deserializing next-id {}", fwd.nextId()); | ||
446 | + return Collections.emptySet(); | ||
447 | + } | ||
448 | + } | ||
449 | + | ||
450 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | ||
451 | + .fromApp(fwd.appId()) | ||
452 | + .withPriority(fwd.priority()) | ||
453 | + .forDevice(deviceId) | ||
454 | + .withSelector(filteredSelector) | ||
455 | + .withTreatment(tt); | ||
456 | + | ||
457 | + if (fwd.permanent()) { | ||
458 | + ruleBuilder.makePermanent(); | ||
459 | + } else { | ||
460 | + ruleBuilder.makeTemporary(fwd.timeout()); | ||
461 | + } | ||
462 | + | ||
463 | + ruleBuilder.forTable(FIB_TABLE); | ||
464 | + return Collections.singletonList(ruleBuilder.build()); | ||
465 | + } | ||
466 | + | ||
467 | + /** | ||
468 | + * Next Objectives are stored as dummy groups for retrieval later | ||
469 | + * when Forwarding Objectives reference the next objective id. At that point | ||
470 | + * the dummy group is fetched from the distributed store and the enclosed | ||
471 | + * treatment is applied as a flow rule action. | ||
472 | + * | ||
473 | + * @param nextObjective the next objective of type simple | ||
474 | + */ | ||
475 | + private void processSimpleNextObjective(NextObjective nextObj) { | ||
476 | + // Simple next objective has a single treatment (not a collection) | ||
477 | + flowObjectiveStore.putNextGroup(nextObj.id(), | ||
478 | + new DummyGroup(nextObj.next().iterator().next())); | ||
479 | + } | ||
480 | + | ||
481 | + private class Filter { | ||
482 | + private PortCriterion port; | ||
483 | + private VlanIdCriterion vlan; | ||
484 | + private EthCriterion eth; | ||
485 | + | ||
486 | + @SuppressWarnings("unused") | ||
487 | + private Collection<IPCriterion> ips; | ||
488 | + | ||
489 | + public Filter(PortCriterion p, EthCriterion e, VlanIdCriterion v, | ||
490 | + Collection<IPCriterion> ips) { | ||
491 | + this.eth = e; | ||
492 | + this.port = p; | ||
493 | + this.vlan = v; | ||
494 | + this.ips = ips; | ||
495 | + } | ||
496 | + | ||
497 | + public PortNumber port() { | ||
498 | + return port.port(); | ||
499 | + } | ||
500 | + | ||
501 | + public VlanId vlanId() { | ||
502 | + return vlan.vlanId(); | ||
503 | + } | ||
504 | + | ||
505 | + public MacAddress mac() { | ||
506 | + return eth.mac(); | ||
507 | + } | ||
508 | + } | ||
509 | + | ||
510 | + private class DummyGroup implements NextGroup { | ||
511 | + TrafficTreatment nextActions; | ||
512 | + | ||
513 | + public DummyGroup(TrafficTreatment next) { | ||
514 | + this.nextActions = next; | ||
515 | + } | ||
516 | + | ||
517 | + @Override | ||
518 | + public byte[] data() { | ||
519 | + return appKryo.serialize(nextActions); | ||
520 | + } | ||
521 | + | ||
522 | + } | ||
523 | + | ||
524 | +} |
... | @@ -27,17 +27,20 @@ | ... | @@ -27,17 +27,20 @@ |
27 | impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> | 27 | impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> |
28 | </driver> | 28 | </driver> |
29 | <driver name="spring-open-cpqd" extends="default" | 29 | <driver name="spring-open-cpqd" extends="default" |
30 | - manufacturer="Stanford University, Ericsson Research and CPqD Research" hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*"> | 30 | + manufacturer="Stanford University, Ericsson Research and CPqD Research" |
31 | + hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*"> | ||
31 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 32 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
32 | impl="org.onosproject.driver.pipeline.SpringOpenTTP"/> | 33 | impl="org.onosproject.driver.pipeline.SpringOpenTTP"/> |
33 | </driver> | 34 | </driver> |
34 | <driver name="spring-open" extends="default" | 35 | <driver name="spring-open" extends="default" |
35 | - manufacturer="Dell " hwVersion="OpenFlow switch HW ver. 1.0" swVersion="OpenFlow switch SW ver. 1.0 and 1.3"> | 36 | + manufacturer="Dell " hwVersion="OpenFlow switch HW ver. 1.0" |
37 | + swVersion="OpenFlow switch SW ver. 1.0 and 1.3"> | ||
36 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 38 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
37 | impl="org.onosproject.driver.pipeline.SpringOpenTTPDell"/> | 39 | impl="org.onosproject.driver.pipeline.SpringOpenTTPDell"/> |
38 | </driver> | 40 | </driver> |
39 | <driver name="linc-oe" extends="default" | 41 | <driver name="linc-oe" extends="default" |
40 | - manufacturer="FlowForwarding.org" hwVersion="Unknown" swVersion="LINC-OE OpenFlow Software Switch 1.1"> | 42 | + manufacturer="FlowForwarding.org" hwVersion="Unknown" |
43 | + swVersion="LINC-OE OpenFlow Software Switch 1.1"> | ||
41 | <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" | 44 | <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" |
42 | impl="org.onosproject.driver.handshaker.OFOpticalSwitchImplLINC13"/> | 45 | impl="org.onosproject.driver.handshaker.OFOpticalSwitchImplLINC13"/> |
43 | </driver> | 46 | </driver> |
... | @@ -45,12 +48,22 @@ | ... | @@ -45,12 +48,22 @@ |
45 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 48 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
46 | impl="org.onosproject.driver.pipeline.CorsaPipeline"/> | 49 | impl="org.onosproject.driver.pipeline.CorsaPipeline"/> |
47 | <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" | 50 | <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" |
48 | - impl="org.onosproject.driver.handshaker.OFCorsaSwitchDriver"/> | 51 | + impl="org.onosproject.driver.handshaker.CorsaSwitchHandShaker"/> |
49 | </driver> | 52 | </driver> |
50 | <driver name="ofdpa" extends="default" | 53 | <driver name="ofdpa" extends="default" |
51 | manufacturer="Broadcom Corp." hwVersion="OF-DPA 1.0" swVersion="OF-DPA 1.0"> | 54 | manufacturer="Broadcom Corp." hwVersion="OF-DPA 1.0" swVersion="OF-DPA 1.0"> |
52 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 55 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
53 | impl="org.onosproject.driver.pipeline.OFDPA1Pipeline"/> | 56 | impl="org.onosproject.driver.pipeline.OFDPA1Pipeline"/> |
54 | </driver> | 57 | </driver> |
58 | + <!-- The SoftRouter driver is meant to be used by any software/NPU based | ||
59 | + ~ switch that wishes to implement a simple 2-table router. ONOS needs to | ||
60 | + ~ be configured with the dpid of such a device to attach this driver | ||
61 | + ~ to the device. | ||
62 | + --> | ||
63 | + <driver name="softrouter" extends="default" | ||
64 | + manufacturer="Various" hwVersion="various" swVersion="0.0.0"> | ||
65 | + <behaviour api="org.onosproject.net.behaviour.Pipeliner" | ||
66 | + impl="org.onosproject.driver.pipeline.SoftRouterPipeline"/> | ||
67 | + </driver> | ||
55 | </drivers> | 68 | </drivers> |
56 | 69 | ... | ... |
-
Please register or login to post a comment