Fixes for the Pica8 pipeline and the cpqd emulation of the OFDPA pipeline.
Change-Id: Ib1982cdb7bc580cf86c43ace229388ee1f1106a2
Showing
4 changed files
with
251 additions
and
318 deletions
... | @@ -29,7 +29,7 @@ public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline { | ... | @@ -29,7 +29,7 @@ public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline { |
29 | processIpTable(); | 29 | processIpTable(); |
30 | //processMcastTable(); | 30 | //processMcastTable(); |
31 | processBridgingTable(); | 31 | processBridgingTable(); |
32 | - //processAclTable(); | 32 | + processAclTable(); |
33 | //processGroupTable(); | 33 | //processGroupTable(); |
34 | } | 34 | } |
35 | 35 | ||
... | @@ -152,7 +152,35 @@ public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline { | ... | @@ -152,7 +152,35 @@ public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline { |
152 | log.info("Failed to initialize Bridging table"); | 152 | log.info("Failed to initialize Bridging table"); |
153 | } | 153 | } |
154 | })); | 154 | })); |
155 | + } | ||
155 | 156 | ||
157 | + private void processAclTable() { | ||
158 | + //table miss entry - catch all to executed action-set | ||
159 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
160 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
161 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
162 | + selector = DefaultTrafficSelector.builder(); | ||
163 | + treatment = DefaultTrafficTreatment.builder(); | ||
164 | + FlowRule rule = DefaultFlowRule.builder() | ||
165 | + .forDevice(deviceId) | ||
166 | + .withSelector(selector.build()) | ||
167 | + .withTreatment(treatment.build()) | ||
168 | + .withPriority(LOWEST_PRIORITY) | ||
169 | + .fromApp(driverId) | ||
170 | + .makePermanent() | ||
171 | + .forTable(ACL_TABLE).build(); | ||
172 | + ops = ops.add(rule); | ||
173 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
174 | + @Override | ||
175 | + public void onSuccess(FlowRuleOperations ops) { | ||
176 | + log.info("Initialized Acl table"); | ||
177 | + } | ||
178 | + | ||
179 | + @Override | ||
180 | + public void onError(FlowRuleOperations ops) { | ||
181 | + log.info("Failed to initialize Acl table"); | ||
182 | + } | ||
183 | + })); | ||
156 | } | 184 | } |
157 | 185 | ||
158 | } | 186 | } | ... | ... |
... | @@ -529,7 +529,6 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -529,7 +529,6 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
529 | .makePermanent() | 529 | .makePermanent() |
530 | .forTable(ACL_TABLE); | 530 | .forTable(ACL_TABLE); |
531 | 531 | ||
532 | - // XXX bug in OFDPA | ||
533 | return Collections.singletonList(ruleBuilder.build()); | 532 | return Collections.singletonList(ruleBuilder.build()); |
534 | } | 533 | } |
535 | 534 | ... | ... |
... | @@ -15,18 +15,16 @@ | ... | @@ -15,18 +15,16 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.driver.pipeline; | 16 | package org.onosproject.driver.pipeline; |
17 | 17 | ||
18 | -import com.google.common.cache.Cache; | ||
19 | -import com.google.common.cache.CacheBuilder; | ||
20 | -import com.google.common.cache.RemovalCause; | ||
21 | -import com.google.common.cache.RemovalNotification; | ||
22 | - | ||
23 | import org.onlab.osgi.ServiceDirectory; | 18 | import org.onlab.osgi.ServiceDirectory; |
24 | import org.onlab.packet.Ethernet; | 19 | import org.onlab.packet.Ethernet; |
25 | import org.onlab.packet.IPv4; | 20 | import org.onlab.packet.IPv4; |
21 | +import org.onlab.packet.MacAddress; | ||
22 | +import org.onlab.packet.VlanId; | ||
26 | import org.onlab.util.KryoNamespace; | 23 | import org.onlab.util.KryoNamespace; |
27 | import org.onosproject.core.ApplicationId; | 24 | import org.onosproject.core.ApplicationId; |
28 | import org.onosproject.core.CoreService; | 25 | import org.onosproject.core.CoreService; |
29 | import org.onosproject.net.DeviceId; | 26 | import org.onosproject.net.DeviceId; |
27 | +import org.onosproject.net.PortNumber; | ||
30 | import org.onosproject.net.behaviour.NextGroup; | 28 | import org.onosproject.net.behaviour.NextGroup; |
31 | import org.onosproject.net.behaviour.Pipeliner; | 29 | import org.onosproject.net.behaviour.Pipeliner; |
32 | import org.onosproject.net.behaviour.PipelinerContext; | 30 | import org.onosproject.net.behaviour.PipelinerContext; |
... | @@ -48,34 +46,23 @@ import org.onosproject.net.flow.criteria.IPCriterion; | ... | @@ -48,34 +46,23 @@ import org.onosproject.net.flow.criteria.IPCriterion; |
48 | import org.onosproject.net.flow.criteria.IPProtocolCriterion; | 46 | import org.onosproject.net.flow.criteria.IPProtocolCriterion; |
49 | import org.onosproject.net.flow.criteria.PortCriterion; | 47 | import org.onosproject.net.flow.criteria.PortCriterion; |
50 | import org.onosproject.net.flow.criteria.VlanIdCriterion; | 48 | import org.onosproject.net.flow.criteria.VlanIdCriterion; |
49 | +import org.onosproject.net.flow.instructions.Instruction; | ||
50 | +import org.onosproject.net.flow.instructions.L2ModificationInstruction; | ||
51 | import org.onosproject.net.flowobjective.FilteringObjective; | 51 | import org.onosproject.net.flowobjective.FilteringObjective; |
52 | import org.onosproject.net.flowobjective.FlowObjectiveStore; | 52 | import org.onosproject.net.flowobjective.FlowObjectiveStore; |
53 | import org.onosproject.net.flowobjective.ForwardingObjective; | 53 | import org.onosproject.net.flowobjective.ForwardingObjective; |
54 | import org.onosproject.net.flowobjective.NextObjective; | 54 | import org.onosproject.net.flowobjective.NextObjective; |
55 | import org.onosproject.net.flowobjective.Objective; | 55 | import org.onosproject.net.flowobjective.Objective; |
56 | import org.onosproject.net.flowobjective.ObjectiveError; | 56 | import org.onosproject.net.flowobjective.ObjectiveError; |
57 | -import org.onosproject.net.group.DefaultGroupBucket; | 57 | +import org.onosproject.store.serializers.KryoNamespaces; |
58 | -import org.onosproject.net.group.DefaultGroupDescription; | ||
59 | -import org.onosproject.net.group.DefaultGroupKey; | ||
60 | -import org.onosproject.net.group.Group; | ||
61 | -import org.onosproject.net.group.GroupBucket; | ||
62 | -import org.onosproject.net.group.GroupBuckets; | ||
63 | -import org.onosproject.net.group.GroupDescription; | ||
64 | -import org.onosproject.net.group.GroupEvent; | ||
65 | -import org.onosproject.net.group.GroupKey; | ||
66 | -import org.onosproject.net.group.GroupListener; | ||
67 | -import org.onosproject.net.group.GroupService; | ||
68 | import org.slf4j.Logger; | 58 | import org.slf4j.Logger; |
69 | 59 | ||
60 | +import java.util.ArrayList; | ||
70 | import java.util.Collection; | 61 | import java.util.Collection; |
71 | import java.util.Collections; | 62 | import java.util.Collections; |
72 | -import java.util.Set; | 63 | +import java.util.List; |
73 | -import java.util.concurrent.Executors; | 64 | +import java.util.concurrent.ConcurrentHashMap; |
74 | -import java.util.concurrent.ScheduledExecutorService; | ||
75 | -import java.util.concurrent.TimeUnit; | ||
76 | -import java.util.stream.Collectors; | ||
77 | 65 | ||
78 | -import static org.onlab.util.Tools.groupedThreads; | ||
79 | import static org.slf4j.LoggerFactory.getLogger; | 66 | import static org.slf4j.LoggerFactory.getLogger; |
80 | 67 | ||
81 | /** | 68 | /** |
... | @@ -83,12 +70,10 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -83,12 +70,10 @@ import static org.slf4j.LoggerFactory.getLogger; |
83 | */ | 70 | */ |
84 | public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner { | 71 | public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner { |
85 | 72 | ||
86 | - protected static final int VLAN_TABLE = 252; | 73 | + protected static final int IP_UNICAST_TABLE = 252; |
87 | - protected static final int ETHTYPE_TABLE = 252; | 74 | + protected static final int ACL_TABLE = 0; |
88 | - protected static final int IP_UNICAST_TABLE = 251; | ||
89 | - protected static final int ACL_TABLE = 251; | ||
90 | 75 | ||
91 | - private static final int CONTROLLER_PRIORITY = 255; | 76 | + //private static final int CONTROLLER_PRIORITY = 255; |
92 | private static final int DROP_PRIORITY = 0; | 77 | private static final int DROP_PRIORITY = 0; |
93 | private static final int HIGHEST_PRIORITY = 0xffff; | 78 | private static final int HIGHEST_PRIORITY = 0xffff; |
94 | 79 | ||
... | @@ -97,46 +82,29 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner | ... | @@ -97,46 +82,29 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner |
97 | private ServiceDirectory serviceDirectory; | 82 | private ServiceDirectory serviceDirectory; |
98 | private FlowRuleService flowRuleService; | 83 | private FlowRuleService flowRuleService; |
99 | private CoreService coreService; | 84 | private CoreService coreService; |
100 | - private GroupService groupService; | ||
101 | private FlowObjectiveStore flowObjectiveStore; | 85 | private FlowObjectiveStore flowObjectiveStore; |
102 | private DeviceId deviceId; | 86 | private DeviceId deviceId; |
103 | private ApplicationId appId; | 87 | private ApplicationId appId; |
88 | + private Collection<Filter> filters; | ||
89 | + private Collection<ForwardingObjective> pendingVersatiles; | ||
104 | 90 | ||
105 | private KryoNamespace appKryo = new KryoNamespace.Builder() | 91 | private KryoNamespace appKryo = new KryoNamespace.Builder() |
106 | - .register(GroupKey.class) | 92 | + .register(KryoNamespaces.API) |
107 | - .register(DefaultGroupKey.class) | ||
108 | .register(PicaGroup.class) | 93 | .register(PicaGroup.class) |
109 | .register(byte[].class) | 94 | .register(byte[].class) |
110 | .build(); | 95 | .build(); |
111 | 96 | ||
112 | - private Cache<GroupKey, NextObjective> pendingGroups; | ||
113 | - | ||
114 | - private ScheduledExecutorService groupChecker = | ||
115 | - Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", | ||
116 | - "ovs-pica-%d")); | ||
117 | - | ||
118 | @Override | 97 | @Override |
119 | public void init(DeviceId deviceId, PipelinerContext context) { | 98 | public void init(DeviceId deviceId, PipelinerContext context) { |
120 | this.serviceDirectory = context.directory(); | 99 | this.serviceDirectory = context.directory(); |
121 | this.deviceId = deviceId; | 100 | this.deviceId = deviceId; |
122 | 101 | ||
123 | - pendingGroups = CacheBuilder.newBuilder() | ||
124 | - .expireAfterWrite(20, TimeUnit.SECONDS) | ||
125 | - .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> { | ||
126 | - if (notification.getCause() == RemovalCause.EXPIRED) { | ||
127 | - fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED); | ||
128 | - } | ||
129 | - }).build(); | ||
130 | - | ||
131 | - groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS); | ||
132 | - | ||
133 | coreService = serviceDirectory.get(CoreService.class); | 102 | coreService = serviceDirectory.get(CoreService.class); |
134 | flowRuleService = serviceDirectory.get(FlowRuleService.class); | 103 | flowRuleService = serviceDirectory.get(FlowRuleService.class); |
135 | - groupService = serviceDirectory.get(GroupService.class); | ||
136 | flowObjectiveStore = context.store(); | 104 | flowObjectiveStore = context.store(); |
137 | - | 105 | + filters = Collections.newSetFromMap(new ConcurrentHashMap<Filter, Boolean>()); |
138 | - groupService.addListener(new InnerGroupListener()); | 106 | + pendingVersatiles = Collections.newSetFromMap( |
139 | - | 107 | + new ConcurrentHashMap<ForwardingObjective, Boolean>()); |
140 | appId = coreService.registerApplication( | 108 | appId = coreService.registerApplication( |
141 | "org.onosproject.driver.OVSPicaPipeline"); | 109 | "org.onosproject.driver.OVSPicaPipeline"); |
142 | 110 | ||
... | @@ -196,22 +164,46 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner | ... | @@ -196,22 +164,46 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner |
196 | switch (nextObjective.type()) { | 164 | switch (nextObjective.type()) { |
197 | case SIMPLE: | 165 | case SIMPLE: |
198 | Collection<TrafficTreatment> treatments = nextObjective.next(); | 166 | Collection<TrafficTreatment> treatments = nextObjective.next(); |
199 | - if (treatments.size() == 1) { | 167 | + if (treatments.size() != 1) { |
200 | - TrafficTreatment treatment = treatments.iterator().next(); | 168 | + log.error("Next Objectives of type Simple should only have a " |
201 | - GroupBucket bucket = | 169 | + + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id()); |
202 | - DefaultGroupBucket.createIndirectGroupBucket(treatment); | 170 | + fail(nextObjective, ObjectiveError.BADPARAMS); |
203 | - final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id())); | 171 | + return; |
204 | - GroupDescription groupDescription | 172 | + } |
205 | - = new DefaultGroupDescription(deviceId, | 173 | + TrafficTreatment treatment = treatments.iterator().next(); |
206 | - GroupDescription.Type.INDIRECT, | 174 | + TrafficTreatment.Builder filteredTreatment = DefaultTrafficTreatment.builder(); |
207 | - new GroupBuckets(Collections | 175 | + VlanId modVlanId; |
208 | - .singletonList(bucket)), | 176 | + for (Instruction ins : treatment.allInstructions()) { |
209 | - key, | 177 | + if (ins.type() == Instruction.Type.L2MODIFICATION) { |
210 | - null, // let group service determine group id | 178 | + L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; |
211 | - nextObjective.appId()); | 179 | + switch (l2ins.subtype()) { |
212 | - groupService.addGroup(groupDescription); | 180 | + case ETH_DST: |
213 | - pendingGroups.put(key, nextObjective); | 181 | + filteredTreatment.setEthDst( |
182 | + ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac()); | ||
183 | + break; | ||
184 | + case ETH_SRC: | ||
185 | + filteredTreatment.setEthSrc( | ||
186 | + ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac()); | ||
187 | + break; | ||
188 | + case VLAN_ID: | ||
189 | + modVlanId = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId(); | ||
190 | + filteredTreatment.setVlanId(modVlanId); | ||
191 | + break; | ||
192 | + default: | ||
193 | + break; | ||
194 | + } | ||
195 | + } else if (ins.type() == Instruction.Type.OUTPUT) { | ||
196 | + //long portNum = ((Instructions.OutputInstruction) ins).port().toLong(); | ||
197 | + filteredTreatment.add(ins); | ||
198 | + } else { | ||
199 | + // Ignore the vlan_pcp action since it's does matter much. | ||
200 | + log.warn("Driver does not handle this type of TrafficTreatment" | ||
201 | + + " instruction in nextObjectives: {}", ins.type()); | ||
202 | + } | ||
214 | } | 203 | } |
204 | + // store for future use | ||
205 | + flowObjectiveStore.putNextGroup(nextObjective.id(), | ||
206 | + new PicaGroup(filteredTreatment.build())); | ||
215 | break; | 207 | break; |
216 | case HASHED: | 208 | case HASHED: |
217 | case BROADCAST: | 209 | case BROADCAST: |
... | @@ -250,11 +242,17 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner | ... | @@ -250,11 +242,17 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner |
250 | fail(fwd, ObjectiveError.UNKNOWN); | 242 | fail(fwd, ObjectiveError.UNKNOWN); |
251 | return Collections.emptySet(); | 243 | return Collections.emptySet(); |
252 | } | 244 | } |
245 | + | ||
253 | if (ethType.ethType() == Ethernet.TYPE_ARP) { | 246 | if (ethType.ethType() == Ethernet.TYPE_ARP) { |
254 | - log.warn("Driver automatically handles ARP packets by punting to controller " | 247 | + if (filters.isEmpty()) { |
255 | - + " from ETHER table"); | 248 | + pendingVersatiles.add(fwd); |
256 | - pass(fwd); | 249 | + return Collections.emptySet(); |
257 | - return Collections.emptySet(); | 250 | + } |
251 | + Collection<FlowRule> flowrules = new ArrayList<FlowRule>(); | ||
252 | + for (Filter filter : filters) { | ||
253 | + flowrules.addAll(processVersatilesWithFilters(filter, fwd)); | ||
254 | + } | ||
255 | + return flowrules; | ||
258 | } else if (ethType.ethType() == Ethernet.TYPE_LLDP || | 256 | } else if (ethType.ethType() == Ethernet.TYPE_LLDP || |
259 | ethType.ethType() == Ethernet.TYPE_BSN) { | 257 | ethType.ethType() == Ethernet.TYPE_BSN) { |
260 | log.warn("Driver currently does not currently handle LLDP packets"); | 258 | log.warn("Driver currently does not currently handle LLDP packets"); |
... | @@ -280,7 +278,7 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner | ... | @@ -280,7 +278,7 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner |
280 | } | 278 | } |
281 | if (ipProto != null && ipProto.protocol() == IPv4.PROTOCOL_TCP) { | 279 | if (ipProto != null && ipProto.protocol() == IPv4.PROTOCOL_TCP) { |
282 | log.warn("Driver automatically punts all packets reaching the " | 280 | log.warn("Driver automatically punts all packets reaching the " |
283 | - + "LOCAL table to the controller"); | 281 | + + "ACL table to the controller"); |
284 | pass(fwd); | 282 | pass(fwd); |
285 | return Collections.emptySet(); | 283 | return Collections.emptySet(); |
286 | } | 284 | } |
... | @@ -291,6 +289,51 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner | ... | @@ -291,6 +289,51 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner |
291 | return Collections.emptySet(); | 289 | return Collections.emptySet(); |
292 | } | 290 | } |
293 | 291 | ||
292 | + private Collection<FlowRule> processVersatilesWithFilters( | ||
293 | + Filter filt, ForwardingObjective fwd) { | ||
294 | + Collection<FlowRule> flows = new ArrayList<FlowRule>(); | ||
295 | + | ||
296 | + // rule for ARP replies | ||
297 | + log.debug("adding ARP rule in ACL table"); | ||
298 | + TrafficSelector.Builder sel = DefaultTrafficSelector.builder(); | ||
299 | + TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder(); | ||
300 | + sel.matchInPort(filt.port()); | ||
301 | + sel.matchVlanId(filt.vlanId()); | ||
302 | + sel.matchEthDst(filt.mac()); | ||
303 | + sel.matchEthType(Ethernet.TYPE_ARP); | ||
304 | + treat.setOutput(PortNumber.CONTROLLER); | ||
305 | + FlowRule rule = DefaultFlowRule.builder() | ||
306 | + .forDevice(deviceId) | ||
307 | + .withSelector(sel.build()) | ||
308 | + .withTreatment(treat.build()) | ||
309 | + .withPriority(HIGHEST_PRIORITY) | ||
310 | + .fromApp(appId) | ||
311 | + .makePermanent() | ||
312 | + .forTable(ACL_TABLE).build(); | ||
313 | + flows.add(rule); | ||
314 | + | ||
315 | + // rule for ARP Broadcast | ||
316 | + sel = DefaultTrafficSelector.builder(); | ||
317 | + treat = DefaultTrafficTreatment.builder(); | ||
318 | + sel.matchInPort(filt.port()); | ||
319 | + sel.matchVlanId(filt.vlanId()); | ||
320 | + sel.matchEthDst(MacAddress.BROADCAST); | ||
321 | + sel.matchEthType(Ethernet.TYPE_ARP); | ||
322 | + treat.setOutput(PortNumber.CONTROLLER); | ||
323 | + rule = DefaultFlowRule.builder() | ||
324 | + .forDevice(deviceId) | ||
325 | + .withSelector(sel.build()) | ||
326 | + .withTreatment(treat.build()) | ||
327 | + .withPriority(HIGHEST_PRIORITY) | ||
328 | + .fromApp(appId) | ||
329 | + .makePermanent() | ||
330 | + .forTable(ACL_TABLE).build(); | ||
331 | + flows.add(rule); | ||
332 | + | ||
333 | + return flows; | ||
334 | + } | ||
335 | + | ||
336 | + | ||
294 | private Collection<FlowRule> processSpecific(ForwardingObjective fwd) { | 337 | private Collection<FlowRule> processSpecific(ForwardingObjective fwd) { |
295 | log.debug("Processing specific forwarding objective"); | 338 | log.debug("Processing specific forwarding objective"); |
296 | TrafficSelector selector = fwd.selector(); | 339 | TrafficSelector selector = fwd.selector(); |
... | @@ -301,46 +344,47 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner | ... | @@ -301,46 +344,47 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner |
301 | return Collections.emptySet(); | 344 | return Collections.emptySet(); |
302 | } | 345 | } |
303 | 346 | ||
304 | - TrafficSelector filteredSelector = | 347 | + List<FlowRule> ipflows = new ArrayList<FlowRule>(); |
305 | - DefaultTrafficSelector.builder() | 348 | + for (Filter f: filters) { |
306 | - .matchEthType(Ethernet.TYPE_IPV4) | 349 | + TrafficSelector filteredSelector = |
307 | - .matchIPDst( | 350 | + DefaultTrafficSelector.builder() |
351 | + .matchEthType(Ethernet.TYPE_IPV4) | ||
352 | + .matchIPDst( | ||
308 | ((IPCriterion) | 353 | ((IPCriterion) |
309 | selector.getCriterion(Criterion.Type.IPV4_DST)).ip()) | 354 | selector.getCriterion(Criterion.Type.IPV4_DST)).ip()) |
310 | - .build(); | 355 | + .matchEthDst(f.mac()) |
311 | - | 356 | + .matchVlanId(f.vlanId()) |
312 | - TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); | 357 | + .build(); |
313 | - | 358 | + TrafficTreatment tt = null; |
314 | - if (fwd.nextId() != null) { | 359 | + if (fwd.nextId() != null) { |
315 | - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); | 360 | + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); |
316 | - GroupKey key = appKryo.deserialize(next.data()); | 361 | + if (next == null) { |
317 | - Group group = groupService.getGroup(deviceId, key); | 362 | + log.error("next-id {} does not exist in store", fwd.nextId()); |
318 | - if (group == null) { | 363 | + return Collections.emptySet(); |
319 | - log.warn("The group left!"); | 364 | + } |
320 | - fail(fwd, ObjectiveError.GROUPMISSING); | 365 | + tt = appKryo.deserialize(next.data()); |
321 | - return Collections.emptySet(); | 366 | + if (tt == null) { |
367 | + log.error("Error in deserializing next-id {}", fwd.nextId()); | ||
368 | + return Collections.emptySet(); | ||
369 | + } | ||
322 | } | 370 | } |
323 | - tb.group(group.id()); | ||
324 | - } | ||
325 | - | ||
326 | - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | ||
327 | - .fromApp(fwd.appId()) | ||
328 | - .withPriority(fwd.priority()) | ||
329 | - .forDevice(deviceId) | ||
330 | - .withSelector(filteredSelector) | ||
331 | - .withTreatment(tb.build()); | ||
332 | 371 | ||
333 | - if (fwd.permanent()) { | 372 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() |
334 | - ruleBuilder.makePermanent(); | 373 | + .fromApp(fwd.appId()) |
335 | - } else { | 374 | + .withPriority(fwd.priority()) |
336 | - ruleBuilder.makeTemporary(fwd.timeout()); | 375 | + .forDevice(deviceId) |
376 | + .withSelector(filteredSelector) | ||
377 | + .withTreatment(tt); | ||
378 | + if (fwd.permanent()) { | ||
379 | + ruleBuilder.makePermanent(); | ||
380 | + } else { | ||
381 | + ruleBuilder.makeTemporary(fwd.timeout()); | ||
382 | + } | ||
383 | + ruleBuilder.forTable(IP_UNICAST_TABLE); | ||
384 | + ipflows.add(ruleBuilder.build()); | ||
337 | } | 385 | } |
338 | 386 | ||
339 | - ruleBuilder.forTable(IP_UNICAST_TABLE); | 387 | + return ipflows; |
340 | - | ||
341 | - | ||
342 | - return Collections.singletonList(ruleBuilder.build()); | ||
343 | - | ||
344 | } | 388 | } |
345 | 389 | ||
346 | private void processFilter(FilteringObjective filt, boolean install, | 390 | private void processFilter(FilteringObjective filt, boolean install, |
... | @@ -357,67 +401,58 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner | ... | @@ -357,67 +401,58 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner |
357 | fail(filt, ObjectiveError.UNKNOWN); | 401 | fail(filt, ObjectiveError.UNKNOWN); |
358 | return; | 402 | return; |
359 | } | 403 | } |
404 | + | ||
405 | + EthCriterion e = null; VlanIdCriterion v = null; | ||
406 | + Collection<IPCriterion> ips = new ArrayList<IPCriterion>(); | ||
360 | // convert filtering conditions for switch-intfs into flowrules | 407 | // convert filtering conditions for switch-intfs into flowrules |
361 | FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | 408 | FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); |
362 | for (Criterion c : filt.conditions()) { | 409 | for (Criterion c : filt.conditions()) { |
363 | if (c.type() == Criterion.Type.ETH_DST) { | 410 | if (c.type() == Criterion.Type.ETH_DST) { |
364 | - EthCriterion e = (EthCriterion) c; | 411 | + e = (EthCriterion) c; |
365 | - log.debug("adding rule for MAC: {}", e.mac()); | ||
366 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
367 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
368 | - selector.matchEthDst(e.mac()); | ||
369 | - treatment.transition(IP_UNICAST_TABLE); | ||
370 | - FlowRule rule = DefaultFlowRule.builder() | ||
371 | - .forDevice(deviceId) | ||
372 | - .withSelector(selector.build()) | ||
373 | - .withTreatment(treatment.build()) | ||
374 | - .withPriority(CONTROLLER_PRIORITY) | ||
375 | - .fromApp(applicationId) | ||
376 | - .makePermanent() | ||
377 | - .forTable(ETHTYPE_TABLE).build(); | ||
378 | - ops = install ? ops.add(rule) : ops.remove(rule); | ||
379 | } else if (c.type() == Criterion.Type.VLAN_VID) { | 412 | } else if (c.type() == Criterion.Type.VLAN_VID) { |
380 | - VlanIdCriterion v = (VlanIdCriterion) c; | 413 | + v = (VlanIdCriterion) c; |
381 | - log.debug("adding rule for VLAN: {}", v.vlanId()); | ||
382 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
383 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
384 | - selector.matchVlanId(v.vlanId()); | ||
385 | - selector.matchInPort(p.port()); | ||
386 | - treatment.transition(ETHTYPE_TABLE); | ||
387 | - treatment.deferred().popVlan(); | ||
388 | - FlowRule rule = DefaultFlowRule.builder() | ||
389 | - .forDevice(deviceId) | ||
390 | - .withSelector(selector.build()) | ||
391 | - .withTreatment(treatment.build()) | ||
392 | - .withPriority(CONTROLLER_PRIORITY) | ||
393 | - .fromApp(applicationId) | ||
394 | - .makePermanent() | ||
395 | - .forTable(VLAN_TABLE).build(); | ||
396 | - ops = install ? ops.add(rule) : ops.remove(rule); | ||
397 | } else if (c.type() == Criterion.Type.IPV4_DST) { | 414 | } else if (c.type() == Criterion.Type.IPV4_DST) { |
398 | - IPCriterion ip = (IPCriterion) c; | 415 | + ips.add((IPCriterion) c); |
399 | - log.debug("adding rule for IP: {}", ip.ip()); | ||
400 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
401 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
402 | - selector.matchEthType(Ethernet.TYPE_IPV4); | ||
403 | - selector.matchIPDst(ip.ip()); | ||
404 | - treatment.transition(ACL_TABLE); | ||
405 | - FlowRule rule = DefaultFlowRule.builder() | ||
406 | - .forDevice(deviceId) | ||
407 | - .withSelector(selector.build()) | ||
408 | - .withTreatment(treatment.build()) | ||
409 | - .withPriority(HIGHEST_PRIORITY) | ||
410 | - .fromApp(applicationId) | ||
411 | - .makePermanent() | ||
412 | - .forTable(IP_UNICAST_TABLE).build(); | ||
413 | - | ||
414 | - ops = install ? ops.add(rule) : ops.remove(rule); | ||
415 | } else { | 416 | } else { |
416 | - log.warn("Driver does not currently process filtering condition" | 417 | + log.error("Unsupported filter {}", c); |
417 | - + " of type: {}", c.type()); | ||
418 | fail(filt, ObjectiveError.UNSUPPORTED); | 418 | fail(filt, ObjectiveError.UNSUPPORTED); |
419 | + return; | ||
420 | + } | ||
421 | + } | ||
422 | + | ||
423 | + // cache for later use | ||
424 | + Filter filter = new Filter(p, e, v, ips); | ||
425 | + filters.add(filter); | ||
426 | + | ||
427 | + // apply any pending versatile forwarding objectives | ||
428 | + for (ForwardingObjective fwd : pendingVersatiles) { | ||
429 | + Collection<FlowRule> ret = processVersatilesWithFilters(filter, fwd); | ||
430 | + for (FlowRule fr : ret) { | ||
431 | + ops.add(fr); | ||
419 | } | 432 | } |
420 | } | 433 | } |
434 | + | ||
435 | + for (IPCriterion ipaddr : ips) { | ||
436 | + log.debug("adding IP filtering rules in ACL table: {}", ipaddr.ip()); | ||
437 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
438 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
439 | + selector.matchInPort(p.port()); | ||
440 | + selector.matchVlanId(v.vlanId()); | ||
441 | + selector.matchEthDst(e.mac()); | ||
442 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
443 | + selector.matchIPDst(ipaddr.ip()); // router IPs to the controller | ||
444 | + treatment.setOutput(PortNumber.CONTROLLER); | ||
445 | + FlowRule rule = DefaultFlowRule.builder() | ||
446 | + .forDevice(deviceId) | ||
447 | + .withSelector(selector.build()) | ||
448 | + .withTreatment(treatment.build()) | ||
449 | + .withPriority(HIGHEST_PRIORITY) | ||
450 | + .fromApp(applicationId) | ||
451 | + .makePermanent() | ||
452 | + .forTable(ACL_TABLE).build(); | ||
453 | + ops = ops.add(rule); | ||
454 | + } | ||
455 | + | ||
421 | // apply filtering flow rules | 456 | // apply filtering flow rules |
422 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | 457 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { |
423 | @Override | 458 | @Override |
... | @@ -447,25 +482,20 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner | ... | @@ -447,25 +482,20 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner |
447 | } | 482 | } |
448 | 483 | ||
449 | private void initializePipeline() { | 484 | private void initializePipeline() { |
450 | - processVlanTable(true); | 485 | + //processIpUnicastTable(true); |
451 | - processEtherTable(true); | 486 | + processACLTable(true); |
452 | - processIpUnicastTable(true); | ||
453 | - //processACLTable(true); | ||
454 | } | 487 | } |
455 | 488 | ||
456 | - private void processVlanTable(boolean install) { | 489 | + private void processACLTable(boolean install) { |
457 | TrafficSelector.Builder selector; | 490 | TrafficSelector.Builder selector; |
458 | TrafficTreatment.Builder treatment; | 491 | TrafficTreatment.Builder treatment; |
459 | FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | 492 | FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); |
460 | FlowRule rule; | 493 | FlowRule rule; |
461 | 494 | ||
462 | - | ||
463 | //Drop rule | 495 | //Drop rule |
464 | selector = DefaultTrafficSelector.builder(); | 496 | selector = DefaultTrafficSelector.builder(); |
465 | treatment = DefaultTrafficTreatment.builder(); | 497 | treatment = DefaultTrafficTreatment.builder(); |
466 | 498 | ||
467 | - treatment.drop(); | ||
468 | - | ||
469 | rule = DefaultFlowRule.builder() | 499 | rule = DefaultFlowRule.builder() |
470 | .forDevice(deviceId) | 500 | .forDevice(deviceId) |
471 | .withSelector(selector.build()) | 501 | .withSelector(selector.build()) |
... | @@ -473,186 +503,62 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner | ... | @@ -473,186 +503,62 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner |
473 | .withPriority(DROP_PRIORITY) | 503 | .withPriority(DROP_PRIORITY) |
474 | .fromApp(appId) | 504 | .fromApp(appId) |
475 | .makePermanent() | 505 | .makePermanent() |
476 | - .forTable(VLAN_TABLE).build(); | 506 | + .forTable(ACL_TABLE).build(); |
477 | 507 | ||
478 | ops = install ? ops.add(rule) : ops.remove(rule); | 508 | ops = install ? ops.add(rule) : ops.remove(rule); |
479 | 509 | ||
480 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | 510 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { |
481 | @Override | 511 | @Override |
482 | public void onSuccess(FlowRuleOperations ops) { | 512 | public void onSuccess(FlowRuleOperations ops) { |
483 | - log.info("Provisioned vlan table"); | 513 | + log.info("Provisioned ACL table"); |
484 | } | 514 | } |
485 | 515 | ||
486 | @Override | 516 | @Override |
487 | public void onError(FlowRuleOperations ops) { | 517 | public void onError(FlowRuleOperations ops) { |
488 | - log.info("Failed to provision vlan table"); | 518 | + log.info("Failed to provision ACL table"); |
489 | } | 519 | } |
490 | })); | 520 | })); |
491 | } | 521 | } |
492 | 522 | ||
493 | - private void processEtherTable(boolean install) { | 523 | + private class Filter { |
494 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 524 | + private PortCriterion port; |
495 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment | 525 | + private VlanIdCriterion vlan; |
496 | - .builder(); | 526 | + private EthCriterion eth; |
497 | - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
498 | - FlowRule rule; | ||
499 | - | ||
500 | - selector.matchEthType(Ethernet.TYPE_ARP); | ||
501 | - treatment.punt(); | ||
502 | - | ||
503 | - rule = DefaultFlowRule.builder() | ||
504 | - .forDevice(deviceId) | ||
505 | - .withSelector(selector.build()) | ||
506 | - .withTreatment(treatment.build()) | ||
507 | - .withPriority(CONTROLLER_PRIORITY) | ||
508 | - .fromApp(appId) | ||
509 | - .makePermanent() | ||
510 | - .forTable(ETHTYPE_TABLE).build(); | ||
511 | - | ||
512 | - ops = install ? ops.add(rule) : ops.remove(rule); | ||
513 | - | ||
514 | - selector = DefaultTrafficSelector.builder(); | ||
515 | - treatment = DefaultTrafficTreatment.builder(); | ||
516 | - | ||
517 | - selector.matchEthType(Ethernet.TYPE_IPV4); | ||
518 | - treatment.transition(IP_UNICAST_TABLE); | ||
519 | - | ||
520 | - rule = DefaultFlowRule.builder() | ||
521 | - .forDevice(deviceId) | ||
522 | - .withPriority(CONTROLLER_PRIORITY) | ||
523 | - .withSelector(selector.build()) | ||
524 | - .withTreatment(treatment.build()) | ||
525 | - .fromApp(appId) | ||
526 | - .makePermanent() | ||
527 | - .forTable(ETHTYPE_TABLE).build(); | ||
528 | - | ||
529 | - ops = install ? ops.add(rule) : ops.remove(rule); | ||
530 | 527 | ||
531 | - //Drop rule | 528 | + @SuppressWarnings("unused") |
532 | - selector = DefaultTrafficSelector.builder(); | 529 | + private Collection<IPCriterion> ips; |
533 | - treatment = DefaultTrafficTreatment.builder(); | 530 | + |
534 | - | 531 | + public Filter(PortCriterion p, EthCriterion e, VlanIdCriterion v, |
535 | - treatment.drop(); | 532 | + Collection<IPCriterion> ips) { |
536 | - | 533 | + this.eth = e; |
537 | - rule = DefaultFlowRule.builder() | 534 | + this.port = p; |
538 | - .forDevice(deviceId) | 535 | + this.vlan = v; |
539 | - .withSelector(selector.build()) | 536 | + this.ips = ips; |
540 | - .withTreatment(treatment.build()) | ||
541 | - .withPriority(DROP_PRIORITY) | ||
542 | - .fromApp(appId) | ||
543 | - .makePermanent() | ||
544 | - .forTable(ETHTYPE_TABLE).build(); | ||
545 | - | ||
546 | - | ||
547 | - ops = install ? ops.add(rule) : ops.remove(rule); | ||
548 | - | ||
549 | - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
550 | - @Override | ||
551 | - public void onSuccess(FlowRuleOperations ops) { | ||
552 | - log.info("Provisioned ether table"); | ||
553 | - } | ||
554 | - | ||
555 | - @Override | ||
556 | - public void onError(FlowRuleOperations ops) { | ||
557 | - log.info("Failed to provision ether table"); | ||
558 | - } | ||
559 | - })); | ||
560 | - | ||
561 | - } | ||
562 | - | ||
563 | - | ||
564 | - private void processIpUnicastTable(boolean install) { | ||
565 | - TrafficSelector.Builder selector; | ||
566 | - TrafficTreatment.Builder treatment; | ||
567 | - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
568 | - FlowRule rule; | ||
569 | - | ||
570 | - //Drop rule | ||
571 | - selector = DefaultTrafficSelector.builder(); | ||
572 | - treatment = DefaultTrafficTreatment.builder(); | ||
573 | - | ||
574 | - treatment.drop(); | ||
575 | - | ||
576 | - rule = DefaultFlowRule.builder() | ||
577 | - .forDevice(deviceId) | ||
578 | - .withSelector(selector.build()) | ||
579 | - .withTreatment(treatment.build()) | ||
580 | - .withPriority(DROP_PRIORITY) | ||
581 | - .fromApp(appId) | ||
582 | - .makePermanent() | ||
583 | - .forTable(IP_UNICAST_TABLE).build(); | ||
584 | - | ||
585 | - ops = install ? ops.add(rule) : ops.remove(rule); | ||
586 | - | ||
587 | - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
588 | - @Override | ||
589 | - public void onSuccess(FlowRuleOperations ops) { | ||
590 | - log.info("Provisioned FIB table"); | ||
591 | - } | ||
592 | - | ||
593 | - @Override | ||
594 | - public void onError(FlowRuleOperations ops) { | ||
595 | - log.info("Failed to provision FIB table"); | ||
596 | - } | ||
597 | - })); | ||
598 | - } | ||
599 | - | ||
600 | - | ||
601 | - private class InnerGroupListener implements GroupListener { | ||
602 | - @Override | ||
603 | - public void event(GroupEvent event) { | ||
604 | - if (event.type() == GroupEvent.Type.GROUP_ADDED) { | ||
605 | - GroupKey key = event.subject().appCookie(); | ||
606 | - | ||
607 | - NextObjective obj = pendingGroups.getIfPresent(key); | ||
608 | - if (obj != null) { | ||
609 | - flowObjectiveStore.putNextGroup(obj.id(), new PicaGroup(key)); | ||
610 | - pass(obj); | ||
611 | - pendingGroups.invalidate(key); | ||
612 | - } | ||
613 | - } | ||
614 | } | 537 | } |
615 | - } | ||
616 | 538 | ||
539 | + public PortNumber port() { | ||
540 | + return port.port(); | ||
541 | + } | ||
617 | 542 | ||
618 | - private class GroupChecker implements Runnable { | 543 | + public VlanId vlanId() { |
544 | + return vlan.vlanId(); | ||
545 | + } | ||
619 | 546 | ||
620 | - @Override | 547 | + public MacAddress mac() { |
621 | - public void run() { | 548 | + return eth.mac(); |
622 | - Set<GroupKey> keys = pendingGroups.asMap().keySet().stream() | ||
623 | - .filter(key -> groupService.getGroup(deviceId, key) != null) | ||
624 | - .collect(Collectors.toSet()); | ||
625 | - | ||
626 | - keys.stream().forEach(key -> { | ||
627 | - NextObjective obj = pendingGroups.getIfPresent(key); | ||
628 | - if (obj == null) { | ||
629 | - return; | ||
630 | - } | ||
631 | - pass(obj); | ||
632 | - pendingGroups.invalidate(key); | ||
633 | - log.info("Heard back from group service for group {}. " | ||
634 | - + "Applying pending forwarding objectives", obj.id()); | ||
635 | - flowObjectiveStore.putNextGroup(obj.id(), new PicaGroup(key)); | ||
636 | - }); | ||
637 | } | 549 | } |
638 | } | 550 | } |
639 | 551 | ||
640 | private class PicaGroup implements NextGroup { | 552 | private class PicaGroup implements NextGroup { |
553 | + TrafficTreatment nextActions; | ||
641 | 554 | ||
642 | - private final GroupKey key; | 555 | + public PicaGroup(TrafficTreatment next) { |
643 | - | 556 | + this.nextActions = next; |
644 | - public PicaGroup(GroupKey key) { | ||
645 | - this.key = key; | ||
646 | - } | ||
647 | - | ||
648 | - @SuppressWarnings("unused") | ||
649 | - public GroupKey key() { | ||
650 | - return key; | ||
651 | } | 557 | } |
652 | 558 | ||
653 | @Override | 559 | @Override |
654 | public byte[] data() { | 560 | public byte[] data() { |
655 | - return appKryo.serialize(key); | 561 | + return appKryo.serialize(nextActions); |
656 | } | 562 | } |
657 | 563 | ||
658 | } | 564 | } | ... | ... |
... | @@ -84,7 +84,7 @@ | ... | @@ -84,7 +84,7 @@ |
84 | impl="org.onosproject.driver.pipeline.CentecV350Pipeline"/> | 84 | impl="org.onosproject.driver.pipeline.CentecV350Pipeline"/> |
85 | </driver> | 85 | </driver> |
86 | <driver name="pica" extends="default" | 86 | <driver name="pica" extends="default" |
87 | - manufacturer="Pica8, Inc." hwVersion="ly2" swVersion="PicOS 2.6"> | 87 | + manufacturer="Pica8, Inc." hwVersion=".*" swVersion="PicOS 2.6"> |
88 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 88 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
89 | impl="org.onosproject.driver.pipeline.PicaPipeline"/> | 89 | impl="org.onosproject.driver.pipeline.PicaPipeline"/> |
90 | </driver> | 90 | </driver> | ... | ... |
-
Please register or login to post a comment