Committed by
Gerrit Code Review
Changes to vRouter to accomodate ofdpa and softrouter pipelines.
Adding arp-spa to flow from vRouter to distinguish between multiple untagged interfaces with the same macAddress. Change-Id: Ifd6e00f70c538c780c0f5728d9ba960a4c70b1db
Showing
5 changed files
with
215 additions
and
68 deletions
... | @@ -22,6 +22,7 @@ import org.apache.felix.scr.annotations.Deactivate; | ... | @@ -22,6 +22,7 @@ import org.apache.felix.scr.annotations.Deactivate; |
22 | import org.apache.felix.scr.annotations.Reference; | 22 | import org.apache.felix.scr.annotations.Reference; |
23 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 23 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
24 | import org.onlab.packet.EthType; | 24 | import org.onlab.packet.EthType; |
25 | +import org.onlab.packet.VlanId; | ||
25 | import org.onosproject.core.ApplicationId; | 26 | import org.onosproject.core.ApplicationId; |
26 | import org.onosproject.core.CoreService; | 27 | import org.onosproject.core.CoreService; |
27 | import org.onosproject.incubator.net.intf.Interface; | 28 | import org.onosproject.incubator.net.intf.Interface; |
... | @@ -40,8 +41,10 @@ import org.onosproject.net.flow.DefaultTrafficTreatment; | ... | @@ -40,8 +41,10 @@ import org.onosproject.net.flow.DefaultTrafficTreatment; |
40 | import org.onosproject.net.flow.TrafficSelector; | 41 | import org.onosproject.net.flow.TrafficSelector; |
41 | import org.onosproject.net.flow.TrafficTreatment; | 42 | import org.onosproject.net.flow.TrafficTreatment; |
42 | import org.onosproject.net.flowobjective.DefaultForwardingObjective; | 43 | import org.onosproject.net.flowobjective.DefaultForwardingObjective; |
44 | +import org.onosproject.net.flowobjective.DefaultNextObjective; | ||
43 | import org.onosproject.net.flowobjective.FlowObjectiveService; | 45 | import org.onosproject.net.flowobjective.FlowObjectiveService; |
44 | import org.onosproject.net.flowobjective.ForwardingObjective; | 46 | import org.onosproject.net.flowobjective.ForwardingObjective; |
47 | +import org.onosproject.net.flowobjective.NextObjective; | ||
45 | import org.onosproject.net.host.InterfaceIpAddress; | 48 | import org.onosproject.net.host.InterfaceIpAddress; |
46 | import org.onosproject.routing.RoutingService; | 49 | import org.onosproject.routing.RoutingService; |
47 | import org.onosproject.routing.config.RouterConfig; | 50 | import org.onosproject.routing.config.RouterConfig; |
... | @@ -110,7 +113,7 @@ public class ControlPlaneRedirectManager { | ... | @@ -110,7 +113,7 @@ public class ControlPlaneRedirectManager { |
110 | routingAppId, RoutingService.ROUTER_CONFIG_CLASS); | 113 | routingAppId, RoutingService.ROUTER_CONFIG_CLASS); |
111 | 114 | ||
112 | if (config == null) { | 115 | if (config == null) { |
113 | - log.info("Router config not available"); | 116 | + log.warn("Router config not available"); |
114 | return; | 117 | return; |
115 | } | 118 | } |
116 | 119 | ||
... | @@ -145,6 +148,23 @@ public class ControlPlaneRedirectManager { | ... | @@ -145,6 +148,23 @@ public class ControlPlaneRedirectManager { |
145 | PortNumber controlPlanePort = controlPlaneConnectPoint.port(); | 148 | PortNumber controlPlanePort = controlPlaneConnectPoint.port(); |
146 | 149 | ||
147 | for (InterfaceIpAddress ip : intf.ipAddresses()) { | 150 | for (InterfaceIpAddress ip : intf.ipAddresses()) { |
151 | + // create nextObjectives for forwarding to this interface and the | ||
152 | + // controlPlaneConnectPoint | ||
153 | + int cpNextId, intfNextId; | ||
154 | + if (intf.vlan() == VlanId.NONE) { | ||
155 | + cpNextId = createNextObjective(deviceId, controlPlanePort, | ||
156 | + VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN), | ||
157 | + true); | ||
158 | + intfNextId = createNextObjective(deviceId, intf.connectPoint().port(), | ||
159 | + VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN), | ||
160 | + true); | ||
161 | + } else { | ||
162 | + cpNextId = createNextObjective(deviceId, controlPlanePort, | ||
163 | + intf.vlan(), false); | ||
164 | + intfNextId = createNextObjective(deviceId, intf.connectPoint().port(), | ||
165 | + intf.vlan(), false); | ||
166 | + } | ||
167 | + | ||
148 | // IPv4 to router | 168 | // IPv4 to router |
149 | TrafficSelector toSelector = DefaultTrafficSelector.builder() | 169 | TrafficSelector toSelector = DefaultTrafficSelector.builder() |
150 | .matchInPort(intf.connectPoint().port()) | 170 | .matchInPort(intf.connectPoint().port()) |
... | @@ -154,12 +174,8 @@ public class ControlPlaneRedirectManager { | ... | @@ -154,12 +174,8 @@ public class ControlPlaneRedirectManager { |
154 | .matchIPDst(ip.ipAddress().toIpPrefix()) | 174 | .matchIPDst(ip.ipAddress().toIpPrefix()) |
155 | .build(); | 175 | .build(); |
156 | 176 | ||
157 | - TrafficTreatment toTreatment = DefaultTrafficTreatment.builder() | ||
158 | - .setOutput(controlPlanePort) | ||
159 | - .build(); | ||
160 | - | ||
161 | flowObjectiveService.forward(deviceId, | 177 | flowObjectiveService.forward(deviceId, |
162 | - buildForwardingObjective(toSelector, toTreatment, true)); | 178 | + buildForwardingObjective(toSelector, null, cpNextId, true)); |
163 | 179 | ||
164 | // IPv4 from router | 180 | // IPv4 from router |
165 | TrafficSelector fromSelector = DefaultTrafficSelector.builder() | 181 | TrafficSelector fromSelector = DefaultTrafficSelector.builder() |
... | @@ -170,12 +186,8 @@ public class ControlPlaneRedirectManager { | ... | @@ -170,12 +186,8 @@ public class ControlPlaneRedirectManager { |
170 | .matchIPSrc(ip.ipAddress().toIpPrefix()) | 186 | .matchIPSrc(ip.ipAddress().toIpPrefix()) |
171 | .build(); | 187 | .build(); |
172 | 188 | ||
173 | - TrafficTreatment intfTreatment = DefaultTrafficTreatment.builder() | ||
174 | - .setOutput(intf.connectPoint().port()) | ||
175 | - .build(); | ||
176 | - | ||
177 | flowObjectiveService.forward(deviceId, | 189 | flowObjectiveService.forward(deviceId, |
178 | - buildForwardingObjective(fromSelector, intfTreatment, true)); | 190 | + buildForwardingObjective(fromSelector, null, intfNextId, true)); |
179 | 191 | ||
180 | // ARP to router | 192 | // ARP to router |
181 | toSelector = DefaultTrafficSelector.builder() | 193 | toSelector = DefaultTrafficSelector.builder() |
... | @@ -184,13 +196,12 @@ public class ControlPlaneRedirectManager { | ... | @@ -184,13 +196,12 @@ public class ControlPlaneRedirectManager { |
184 | .matchVlanId(intf.vlan()) | 196 | .matchVlanId(intf.vlan()) |
185 | .build(); | 197 | .build(); |
186 | 198 | ||
187 | - toTreatment = DefaultTrafficTreatment.builder() | 199 | + TrafficTreatment puntTreatment = DefaultTrafficTreatment.builder() |
188 | - .setOutput(controlPlanePort) | ||
189 | .punt() | 200 | .punt() |
190 | .build(); | 201 | .build(); |
191 | 202 | ||
192 | flowObjectiveService.forward(deviceId, | 203 | flowObjectiveService.forward(deviceId, |
193 | - buildForwardingObjective(toSelector, toTreatment, true)); | 204 | + buildForwardingObjective(toSelector, puntTreatment, cpNextId, true)); |
194 | 205 | ||
195 | // ARP from router | 206 | // ARP from router |
196 | fromSelector = DefaultTrafficSelector.builder() | 207 | fromSelector = DefaultTrafficSelector.builder() |
... | @@ -198,15 +209,11 @@ public class ControlPlaneRedirectManager { | ... | @@ -198,15 +209,11 @@ public class ControlPlaneRedirectManager { |
198 | .matchEthSrc(intf.mac()) | 209 | .matchEthSrc(intf.mac()) |
199 | .matchVlanId(intf.vlan()) | 210 | .matchVlanId(intf.vlan()) |
200 | .matchEthType(EthType.EtherType.ARP.ethType().toShort()) | 211 | .matchEthType(EthType.EtherType.ARP.ethType().toShort()) |
201 | - .build(); | 212 | + .matchArpSpa(ip.ipAddress().getIp4Address()) |
202 | - | ||
203 | - intfTreatment = DefaultTrafficTreatment.builder() | ||
204 | - .setOutput(intf.connectPoint().port()) | ||
205 | - .punt() | ||
206 | .build(); | 213 | .build(); |
207 | 214 | ||
208 | flowObjectiveService.forward(deviceId, | 215 | flowObjectiveService.forward(deviceId, |
209 | - buildForwardingObjective(fromSelector, intfTreatment, true)); | 216 | + buildForwardingObjective(fromSelector, puntTreatment, intfNextId, true)); |
210 | } | 217 | } |
211 | } | 218 | } |
212 | 219 | ||
... | @@ -219,31 +226,83 @@ public class ControlPlaneRedirectManager { | ... | @@ -219,31 +226,83 @@ public class ControlPlaneRedirectManager { |
219 | .matchIPProtocol((byte) OSPF_IP_PROTO) | 226 | .matchIPProtocol((byte) OSPF_IP_PROTO) |
220 | .build(); | 227 | .build(); |
221 | 228 | ||
222 | - TrafficTreatment toTreatment = DefaultTrafficTreatment.builder() | 229 | + // create nextObjectives for forwarding to the controlPlaneConnectPoint |
223 | - .setOutput(controlPlaneConnectPoint.port()) | 230 | + DeviceId deviceId = controlPlaneConnectPoint.deviceId(); |
224 | - .build(); | 231 | + PortNumber controlPlanePort = controlPlaneConnectPoint.port(); |
225 | - | 232 | + int cpNextId; |
233 | + if (intf.vlan() == VlanId.NONE) { | ||
234 | + cpNextId = createNextObjective(deviceId, controlPlanePort, | ||
235 | + VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN), | ||
236 | + true); | ||
237 | + } else { | ||
238 | + cpNextId = createNextObjective(deviceId, controlPlanePort, | ||
239 | + intf.vlan(), false); | ||
240 | + } | ||
241 | + log.debug("ospf flows intf:{} nextid:{}", intf, cpNextId); | ||
226 | flowObjectiveService.forward(controlPlaneConnectPoint.deviceId(), | 242 | flowObjectiveService.forward(controlPlaneConnectPoint.deviceId(), |
227 | - buildForwardingObjective(toSelector, toTreatment, ospfEnabled)); | 243 | + buildForwardingObjective(toSelector, null, cpNextId, ospfEnabled)); |
228 | } | 244 | } |
229 | 245 | ||
230 | /** | 246 | /** |
231 | - * Builds a forwarding objective from the given selector and treatment. | 247 | + * Creates a next objective for forwarding to a port. Handles metadata for |
248 | + * some pipelines that require vlan information for egress port. | ||
249 | + * | ||
250 | + * @param deviceId the device on which the next objective is being created | ||
251 | + * @param portNumber the egress port | ||
252 | + * @param vlanId vlan information for egress port | ||
253 | + * @param popVlan if vlan tag should be popped or not | ||
254 | + * @return nextId of the next objective created | ||
255 | + */ | ||
256 | + private int createNextObjective(DeviceId deviceId, PortNumber portNumber, | ||
257 | + VlanId vlanId, boolean popVlan) { | ||
258 | + int nextId = flowObjectiveService.allocateNextId(); | ||
259 | + NextObjective.Builder nextObjBuilder = DefaultNextObjective | ||
260 | + .builder().withId(nextId) | ||
261 | + .withType(NextObjective.Type.SIMPLE) | ||
262 | + .fromApp(appId); | ||
263 | + | ||
264 | + TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder(); | ||
265 | + if (popVlan) { | ||
266 | + ttBuilder.popVlan(); | ||
267 | + } | ||
268 | + ttBuilder.setOutput(portNumber); | ||
269 | + | ||
270 | + // setup metadata to pass to nextObjective - indicate the vlan on egress | ||
271 | + // if needed by the switch pipeline. | ||
272 | + TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder(); | ||
273 | + metabuilder.matchVlanId(vlanId); | ||
274 | + | ||
275 | + nextObjBuilder.withMeta(metabuilder.build()); | ||
276 | + nextObjBuilder.addTreatment(ttBuilder.build()); | ||
277 | + log.debug("Submited next objective {} in device {} for port/vlan {}/{}", | ||
278 | + nextId, deviceId, portNumber, vlanId); | ||
279 | + flowObjectiveService.next(deviceId, nextObjBuilder.add()); | ||
280 | + return nextId; | ||
281 | + } | ||
282 | + | ||
283 | + /** | ||
284 | + * Builds a forwarding objective from the given selector, treatment and nextId. | ||
232 | * | 285 | * |
233 | * @param selector selector | 286 | * @param selector selector |
234 | - * @param treatment treatment | 287 | + * @param treatment treatment to apply to packet, can be null |
288 | + * @param nextId next objective to point to for forwarding packet | ||
235 | * @param add true to create an add objective, false to create a remove | 289 | * @param add true to create an add objective, false to create a remove |
236 | * objective | 290 | * objective |
237 | * @return forwarding objective | 291 | * @return forwarding objective |
238 | */ | 292 | */ |
239 | private ForwardingObjective buildForwardingObjective(TrafficSelector selector, | 293 | private ForwardingObjective buildForwardingObjective(TrafficSelector selector, |
240 | TrafficTreatment treatment, | 294 | TrafficTreatment treatment, |
295 | + int nextId, | ||
241 | boolean add) { | 296 | boolean add) { |
242 | - | 297 | + DefaultForwardingObjective.Builder fobBuilder = DefaultForwardingObjective.builder(); |
243 | - ForwardingObjective.Builder fobBuilder = DefaultForwardingObjective.builder() | 298 | + fobBuilder.withSelector(selector); |
244 | - .withSelector(selector) | 299 | + if (treatment != null) { |
245 | - .withTreatment(treatment) | 300 | + fobBuilder.withTreatment(treatment); |
246 | - .fromApp(appId) | 301 | + } |
302 | + if (nextId != -1) { | ||
303 | + fobBuilder.nextStep(nextId); | ||
304 | + } | ||
305 | + fobBuilder.fromApp(appId) | ||
247 | .withPriority(PRIORITY) | 306 | .withPriority(PRIORITY) |
248 | .withFlag(ForwardingObjective.Flag.VERSATILE); | 307 | .withFlag(ForwardingObjective.Flag.VERSATILE); |
249 | 308 | ... | ... |
... | @@ -34,6 +34,7 @@ import org.onosproject.core.ApplicationId; | ... | @@ -34,6 +34,7 @@ import org.onosproject.core.ApplicationId; |
34 | import org.onosproject.core.CoreService; | 34 | import org.onosproject.core.CoreService; |
35 | import org.onosproject.incubator.net.intf.Interface; | 35 | import org.onosproject.incubator.net.intf.Interface; |
36 | import org.onosproject.incubator.net.intf.InterfaceService; | 36 | import org.onosproject.incubator.net.intf.InterfaceService; |
37 | +import org.onosproject.net.ConnectPoint; | ||
37 | import org.onosproject.net.DeviceId; | 38 | import org.onosproject.net.DeviceId; |
38 | import org.onosproject.net.config.NetworkConfigEvent; | 39 | import org.onosproject.net.config.NetworkConfigEvent; |
39 | import org.onosproject.net.config.NetworkConfigListener; | 40 | import org.onosproject.net.config.NetworkConfigListener; |
... | @@ -80,6 +81,8 @@ public class SingleSwitchFibInstaller { | ... | @@ -80,6 +81,8 @@ public class SingleSwitchFibInstaller { |
80 | private static final int PRIORITY_OFFSET = 100; | 81 | private static final int PRIORITY_OFFSET = 100; |
81 | private static final int PRIORITY_MULTIPLIER = 5; | 82 | private static final int PRIORITY_MULTIPLIER = 5; |
82 | 83 | ||
84 | + public static final short ASSIGNED_VLAN = 4094; | ||
85 | + | ||
83 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 86 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
84 | protected CoreService coreService; | 87 | protected CoreService coreService; |
85 | 88 | ||
... | @@ -103,7 +106,8 @@ public class SingleSwitchFibInstaller { | ... | @@ -103,7 +106,8 @@ public class SingleSwitchFibInstaller { |
103 | // Device id of data-plane switch - should be learned from config | 106 | // Device id of data-plane switch - should be learned from config |
104 | private DeviceId deviceId; | 107 | private DeviceId deviceId; |
105 | 108 | ||
106 | - private ApplicationId appId; | 109 | + private ConnectPoint controlPlaneConnectPoint; |
110 | + | ||
107 | private ApplicationId routerAppId; | 111 | private ApplicationId routerAppId; |
108 | 112 | ||
109 | // Reference count for how many times a next hop is used by a route | 113 | // Reference count for how many times a next hop is used by a route |
... | @@ -121,11 +125,8 @@ public class SingleSwitchFibInstaller { | ... | @@ -121,11 +125,8 @@ public class SingleSwitchFibInstaller { |
121 | 125 | ||
122 | @Activate | 126 | @Activate |
123 | protected void activate() { | 127 | protected void activate() { |
124 | - // TODO why are there two of the same app ID? | ||
125 | routerAppId = coreService.registerApplication(RoutingService.ROUTER_APP_ID); | 128 | routerAppId = coreService.registerApplication(RoutingService.ROUTER_APP_ID); |
126 | 129 | ||
127 | - appId = coreService.getAppId(RoutingService.ROUTER_APP_ID); | ||
128 | - | ||
129 | deviceListener = new InternalDeviceListener(); | 130 | deviceListener = new InternalDeviceListener(); |
130 | deviceService.addListener(deviceListener); | 131 | deviceService.addListener(deviceListener); |
131 | 132 | ||
... | @@ -156,6 +157,8 @@ public class SingleSwitchFibInstaller { | ... | @@ -156,6 +157,8 @@ public class SingleSwitchFibInstaller { |
156 | log.info("Router config not available"); | 157 | log.info("Router config not available"); |
157 | return; | 158 | return; |
158 | } | 159 | } |
160 | + controlPlaneConnectPoint = routerConfig.getControlPlaneConnectPoint(); | ||
161 | + log.info("Control Plane Connect Point: {}", controlPlaneConnectPoint); | ||
159 | 162 | ||
160 | deviceId = routerConfig.getControlPlaneConnectPoint().deviceId(); | 163 | deviceId = routerConfig.getControlPlaneConnectPoint().deviceId(); |
161 | 164 | ||
... | @@ -231,7 +234,7 @@ public class SingleSwitchFibInstaller { | ... | @@ -231,7 +234,7 @@ public class SingleSwitchFibInstaller { |
231 | int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET; | 234 | int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET; |
232 | 235 | ||
233 | ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder() | 236 | ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder() |
234 | - .fromApp(appId) | 237 | + .fromApp(routerAppId) |
235 | .makePermanent() | 238 | .makePermanent() |
236 | .withSelector(selector) | 239 | .withSelector(selector) |
237 | .withPriority(priority) | 240 | .withPriority(priority) |
... | @@ -266,23 +269,30 @@ public class SingleSwitchFibInstaller { | ... | @@ -266,23 +269,30 @@ public class SingleSwitchFibInstaller { |
266 | .setEthSrc(egressIntf.mac()) | 269 | .setEthSrc(egressIntf.mac()) |
267 | .setEthDst(nextHop.mac()); | 270 | .setEthDst(nextHop.mac()); |
268 | 271 | ||
272 | + TrafficSelector.Builder metabuilder = null; | ||
269 | if (!egressIntf.vlan().equals(VlanId.NONE)) { | 273 | if (!egressIntf.vlan().equals(VlanId.NONE)) { |
270 | treatment.pushVlan() | 274 | treatment.pushVlan() |
271 | .setVlanId(egressIntf.vlan()) | 275 | .setVlanId(egressIntf.vlan()) |
272 | .setVlanPcp((byte) 0); | 276 | .setVlanPcp((byte) 0); |
277 | + } else { | ||
278 | + // untagged outgoing port may require internal vlan in some pipelines | ||
279 | + metabuilder = DefaultTrafficSelector.builder(); | ||
280 | + metabuilder.matchVlanId(VlanId.vlanId(ASSIGNED_VLAN)); | ||
273 | } | 281 | } |
274 | 282 | ||
275 | treatment.setOutput(egressIntf.connectPoint().port()); | 283 | treatment.setOutput(egressIntf.connectPoint().port()); |
276 | 284 | ||
277 | int nextId = flowObjectiveService.allocateNextId(); | 285 | int nextId = flowObjectiveService.allocateNextId(); |
278 | - | 286 | + NextObjective.Builder nextBuilder = DefaultNextObjective.builder() |
279 | - NextObjective nextObjective = DefaultNextObjective.builder() | ||
280 | .withId(nextId) | 287 | .withId(nextId) |
281 | .addTreatment(treatment.build()) | 288 | .addTreatment(treatment.build()) |
282 | .withType(NextObjective.Type.SIMPLE) | 289 | .withType(NextObjective.Type.SIMPLE) |
283 | - .fromApp(appId) | 290 | + .fromApp(routerAppId); |
284 | - .add(); // TODO add callbacks | 291 | + if (metabuilder != null) { |
292 | + nextBuilder.withMeta(metabuilder.build()); | ||
293 | + } | ||
285 | 294 | ||
295 | + NextObjective nextObjective = nextBuilder.add(); // TODO add callbacks | ||
286 | flowObjectiveService.next(deviceId, nextObjective); | 296 | flowObjectiveService.next(deviceId, nextObjective); |
287 | 297 | ||
288 | nextHops.put(nextHop.ip(), nextId); | 298 | nextHops.put(nextHop.ip(), nextId); |
... | @@ -329,13 +339,29 @@ public class SingleSwitchFibInstaller { | ... | @@ -329,13 +339,29 @@ public class SingleSwitchFibInstaller { |
329 | } | 339 | } |
330 | 340 | ||
331 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); | 341 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); |
342 | + // first add filter for the interface | ||
332 | fob.withKey(Criteria.matchInPort(intf.connectPoint().port())) | 343 | fob.withKey(Criteria.matchInPort(intf.connectPoint().port())) |
333 | .addCondition(Criteria.matchEthDst(intf.mac())) | 344 | .addCondition(Criteria.matchEthDst(intf.mac())) |
334 | .addCondition(Criteria.matchVlanId(intf.vlan())); | 345 | .addCondition(Criteria.matchVlanId(intf.vlan())); |
335 | - | ||
336 | fob.withPriority(PRIORITY_OFFSET); | 346 | fob.withPriority(PRIORITY_OFFSET); |
347 | + if (intf.vlan() == VlanId.NONE) { | ||
348 | + TrafficTreatment tt = DefaultTrafficTreatment.builder() | ||
349 | + .pushVlan().setVlanId(VlanId.vlanId(ASSIGNED_VLAN)).build(); | ||
350 | + fob.withMeta(tt); | ||
351 | + } | ||
352 | + | ||
353 | + fob.permit().fromApp(routerAppId); | ||
354 | + sendFilteringObjective(install, fob, intf); | ||
355 | + if (controlPlaneConnectPoint != null) { | ||
356 | + // then add the same mac/vlan filters for control-plane connect point | ||
357 | + fob.withKey(Criteria.matchInPort(controlPlaneConnectPoint.port())); | ||
358 | + sendFilteringObjective(install, fob, intf); | ||
359 | + } | ||
360 | + } | ||
361 | + } | ||
337 | 362 | ||
338 | - fob.permit().fromApp(appId); | 363 | + private void sendFilteringObjective(boolean install, FilteringObjective.Builder fob, |
364 | + Interface intf) { | ||
339 | flowObjectiveService.filter( | 365 | flowObjectiveService.filter( |
340 | deviceId, | 366 | deviceId, |
341 | fob.add(new ObjectiveContext() { | 367 | fob.add(new ObjectiveContext() { |
... | @@ -354,7 +380,6 @@ public class SingleSwitchFibInstaller { | ... | @@ -354,7 +380,6 @@ public class SingleSwitchFibInstaller { |
354 | } | 380 | } |
355 | })); | 381 | })); |
356 | } | 382 | } |
357 | - } | ||
358 | 383 | ||
359 | private class InternalFibListener implements FibListener { | 384 | private class InternalFibListener implements FibListener { |
360 | 385 | ... | ... |
... | @@ -387,11 +387,12 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -387,11 +387,12 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
387 | Set<PendingNext> pending = pendingForwards.remove(event.subject()); | 387 | Set<PendingNext> pending = pendingForwards.remove(event.subject()); |
388 | 388 | ||
389 | if (pending == null) { | 389 | if (pending == null) { |
390 | - log.debug("Nothing pending for this obj event"); | 390 | + log.warn("Nothing pending for this obj event {}", event); |
391 | return; | 391 | return; |
392 | } | 392 | } |
393 | 393 | ||
394 | - log.debug("Processing pending forwarding objectives {}", pending.size()); | 394 | + log.debug("Processing {} pending forwarding objectives for nextId {}", |
395 | + pending.size(), event.subject()); | ||
395 | pending.forEach(p -> getDevicePipeliner(p.deviceId()) | 396 | pending.forEach(p -> getDevicePipeliner(p.deviceId()) |
396 | .forward(p.forwardingObjective())); | 397 | .forward(p.forwardingObjective())); |
397 | } | 398 | } | ... | ... |
... | @@ -584,35 +584,60 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -584,35 +584,60 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
584 | + "nextId or Treatment", fwd.selector(), fwd.appId()); | 584 | + "nextId or Treatment", fwd.selector(), fwd.appId()); |
585 | return Collections.emptySet(); | 585 | return Collections.emptySet(); |
586 | } | 586 | } |
587 | + | ||
587 | // XXX driver does not currently do type checking as per Tables 65-67 in | 588 | // XXX driver does not currently do type checking as per Tables 65-67 in |
588 | // OFDPA 2.0 spec. The only allowed treatment is a punt to the controller. | 589 | // OFDPA 2.0 spec. The only allowed treatment is a punt to the controller. |
589 | - if (fwd.treatment() != null && | 590 | + TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder(); |
590 | - fwd.treatment().allInstructions().size() == 1 && | 591 | + if (fwd.treatment() != null) { |
591 | - fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) { | 592 | + for (Instruction ins : fwd.treatment().allInstructions()) { |
592 | - OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0); | 593 | + if (ins instanceof OutputInstruction) { |
594 | + OutputInstruction o = (OutputInstruction) ins; | ||
593 | if (o.port() == PortNumber.CONTROLLER) { | 595 | if (o.port() == PortNumber.CONTROLLER) { |
594 | - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | 596 | + ttBuilder.add(o); |
595 | - .fromApp(fwd.appId()) | ||
596 | - .withPriority(fwd.priority()) | ||
597 | - .forDevice(deviceId) | ||
598 | - .withSelector(fwd.selector()) | ||
599 | - .withTreatment(fwd.treatment()) | ||
600 | - .makePermanent() | ||
601 | - .forTable(ACL_TABLE); | ||
602 | - return Collections.singletonList(ruleBuilder.build()); | ||
603 | } else { | 597 | } else { |
604 | log.warn("Only allowed treatments in versatile forwarding " | 598 | log.warn("Only allowed treatments in versatile forwarding " |
605 | + "objectives are punts to the controller"); | 599 | + "objectives are punts to the controller"); |
606 | - return Collections.emptySet(); | 600 | + } |
601 | + } else { | ||
602 | + log.warn("Cannot process instruction in versatile fwd {}", ins); | ||
607 | } | 603 | } |
608 | } | 604 | } |
609 | - | ||
610 | - if (fwd.nextId() != null) { | ||
611 | - // XXX overide case | ||
612 | - log.warn("versatile objective --> next Id not yet implemeted"); | ||
613 | } | 605 | } |
606 | + if (fwd.nextId() != null) { | ||
607 | + // overide case | ||
608 | + NextGroup next = getGroupForNextObjective(fwd.nextId()); | ||
609 | + List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data()); | ||
610 | + // we only need the top level group's key to point the flow to it | ||
611 | + Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst()); | ||
612 | + if (group == null) { | ||
613 | + log.warn("Group with key:{} for next-id:{} not found in dev:{}", | ||
614 | + gkeys.get(0).peekFirst(), fwd.nextId(), deviceId); | ||
615 | + fail(fwd, ObjectiveError.GROUPMISSING); | ||
614 | return Collections.emptySet(); | 616 | return Collections.emptySet(); |
615 | } | 617 | } |
618 | + ttBuilder.deferred().group(group.id()); | ||
619 | + } | ||
620 | + // ensure that match does not include vlan = NONE as OF-DPA does not | ||
621 | + // match untagged packets this way in the ACL table. | ||
622 | + TrafficSelector.Builder selBuilder = DefaultTrafficSelector.builder(); | ||
623 | + for (Criterion criterion : fwd.selector().criteria()) { | ||
624 | + if (criterion instanceof VlanIdCriterion && | ||
625 | + ((VlanIdCriterion) criterion).vlanId() == VlanId.NONE) { | ||
626 | + continue; | ||
627 | + } | ||
628 | + selBuilder.add(criterion); | ||
629 | + } | ||
630 | + | ||
631 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | ||
632 | + .fromApp(fwd.appId()) | ||
633 | + .withPriority(fwd.priority()) | ||
634 | + .forDevice(deviceId) | ||
635 | + .withSelector(selBuilder.build()) | ||
636 | + .withTreatment(ttBuilder.build()) | ||
637 | + .makePermanent() | ||
638 | + .forTable(ACL_TABLE); | ||
639 | + return Collections.singletonList(ruleBuilder.build()); | ||
640 | + } | ||
616 | 641 | ||
617 | /** | 642 | /** |
618 | * In the OF-DPA 2.0 pipeline, specific forwarding refers to the IP table | 643 | * In the OF-DPA 2.0 pipeline, specific forwarding refers to the IP table | ... | ... |
... | @@ -42,6 +42,8 @@ import org.onosproject.net.flow.criteria.EthTypeCriterion; | ... | @@ -42,6 +42,8 @@ import org.onosproject.net.flow.criteria.EthTypeCriterion; |
42 | import org.onosproject.net.flow.criteria.IPCriterion; | 42 | import org.onosproject.net.flow.criteria.IPCriterion; |
43 | import org.onosproject.net.flow.criteria.PortCriterion; | 43 | import org.onosproject.net.flow.criteria.PortCriterion; |
44 | import org.onosproject.net.flow.criteria.VlanIdCriterion; | 44 | import org.onosproject.net.flow.criteria.VlanIdCriterion; |
45 | +import org.onosproject.net.flow.instructions.Instruction; | ||
46 | +import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; | ||
45 | import org.onosproject.net.flowobjective.FilteringObjective; | 47 | import org.onosproject.net.flowobjective.FilteringObjective; |
46 | import org.onosproject.net.flowobjective.FlowObjectiveStore; | 48 | import org.onosproject.net.flowobjective.FlowObjectiveStore; |
47 | import org.onosproject.net.flowobjective.ForwardingObjective; | 49 | import org.onosproject.net.flowobjective.ForwardingObjective; |
... | @@ -50,6 +52,7 @@ import org.onosproject.net.flowobjective.Objective; | ... | @@ -50,6 +52,7 @@ import org.onosproject.net.flowobjective.Objective; |
50 | import org.onosproject.net.flowobjective.ObjectiveError; | 52 | import org.onosproject.net.flowobjective.ObjectiveError; |
51 | import org.onosproject.store.serializers.KryoNamespaces; | 53 | import org.onosproject.store.serializers.KryoNamespaces; |
52 | import org.slf4j.Logger; | 54 | import org.slf4j.Logger; |
55 | +import static org.onlab.util.Tools.delay; | ||
53 | 56 | ||
54 | import java.util.ArrayList; | 57 | import java.util.ArrayList; |
55 | import java.util.Collection; | 58 | import java.util.Collection; |
... | @@ -314,19 +317,50 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe | ... | @@ -314,19 +317,50 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe |
314 | } | 317 | } |
315 | 318 | ||
316 | /** | 319 | /** |
317 | - * SoftRouter has a single versatile table - the filter table. All versatile | 320 | + * SoftRouter has a single versatile table - the filter table. |
318 | - * flow rules must include the filtering rules. | 321 | + * This table can be used to filter entries that reach the next table (FIB table). |
322 | + * It can also be used to punt packets to the controller and/or bypass | ||
323 | + * the FIB table to forward out of a port. | ||
319 | * | 324 | * |
320 | * @param fwd The forwarding objective of type versatile | 325 | * @param fwd The forwarding objective of type versatile |
321 | * @return A collection of flow rules meant to be delivered to the flowrule | 326 | * @return A collection of flow rules meant to be delivered to the flowrule |
322 | * subsystem. May return empty collection in case of failures. | 327 | * subsystem. May return empty collection in case of failures. |
323 | */ | 328 | */ |
324 | private Collection<FlowRule> processVersatile(ForwardingObjective fwd) { | 329 | private Collection<FlowRule> processVersatile(ForwardingObjective fwd) { |
330 | + log.debug("Received versatile fwd: to next:{}", fwd.nextId()); | ||
325 | Collection<FlowRule> flowrules = new ArrayList<>(); | 331 | Collection<FlowRule> flowrules = new ArrayList<>(); |
332 | + if (fwd.nextId() == null && fwd.treatment() == null) { | ||
333 | + log.error("Forwarding objective {} from {} must contain " | ||
334 | + + "nextId or Treatment", fwd.selector(), fwd.appId()); | ||
335 | + return Collections.emptySet(); | ||
336 | + } | ||
337 | + TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder(); | ||
338 | + if (fwd.treatment() != null) { | ||
339 | + fwd.treatment().immediate().forEach(ins -> ttBuilder.add(ins)); | ||
340 | + } | ||
341 | + //convert nextId to flow actions | ||
342 | + if (fwd.nextId() != null) { | ||
343 | + // only acceptable value is output to port | ||
344 | + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); | ||
345 | + if (next == null) { | ||
346 | + log.error("next-id {} does not exist in store", fwd.nextId()); | ||
347 | + return Collections.emptySet(); | ||
348 | + } | ||
349 | + TrafficTreatment nt = appKryo.deserialize(next.data()); | ||
350 | + if (nt == null) { | ||
351 | + log.error("Error in deserializing next-id {}", fwd.nextId()); | ||
352 | + return Collections.emptySet(); | ||
353 | + } | ||
354 | + for (Instruction ins : nt.allInstructions()) { | ||
355 | + if (ins instanceof OutputInstruction) { | ||
356 | + ttBuilder.add(ins); | ||
357 | + } | ||
358 | + } | ||
359 | + } | ||
326 | 360 | ||
327 | FlowRule rule = DefaultFlowRule.builder() | 361 | FlowRule rule = DefaultFlowRule.builder() |
328 | .withSelector(fwd.selector()) | 362 | .withSelector(fwd.selector()) |
329 | - .withTreatment(fwd.treatment()) | 363 | + .withTreatment(ttBuilder.build()) |
330 | .makePermanent() | 364 | .makePermanent() |
331 | .forDevice(deviceId) | 365 | .forDevice(deviceId) |
332 | .fromApp(fwd.appId()) | 366 | .fromApp(fwd.appId()) |
... | @@ -350,7 +384,7 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe | ... | @@ -350,7 +384,7 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe |
350 | * | 384 | * |
351 | */ | 385 | */ |
352 | private Collection<FlowRule> processSpecific(ForwardingObjective fwd) { | 386 | private Collection<FlowRule> processSpecific(ForwardingObjective fwd) { |
353 | - log.debug("Processing specific forwarding objective"); | 387 | + log.debug("Processing specific forwarding objective to next:{}", fwd.nextId()); |
354 | TrafficSelector selector = fwd.selector(); | 388 | TrafficSelector selector = fwd.selector(); |
355 | EthTypeCriterion ethType = | 389 | EthTypeCriterion ethType = |
356 | (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); | 390 | (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); |
... | @@ -411,6 +445,9 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe | ... | @@ -411,6 +445,9 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe |
411 | */ | 445 | */ |
412 | private void processSimpleNextObjective(NextObjective nextObj) { | 446 | private void processSimpleNextObjective(NextObjective nextObj) { |
413 | // Simple next objective has a single treatment (not a collection) | 447 | // Simple next objective has a single treatment (not a collection) |
448 | + log.debug("Received nextObj {}", nextObj.id()); | ||
449 | + // delay processing to emulate group creation | ||
450 | + delay(50); | ||
414 | TrafficTreatment treatment = nextObj.next().iterator().next(); | 451 | TrafficTreatment treatment = nextObj.next().iterator().next(); |
415 | flowObjectiveStore.putNextGroup(nextObj.id(), | 452 | flowObjectiveStore.putNextGroup(nextObj.id(), |
416 | new DummyGroup(treatment)); | 453 | new DummyGroup(treatment)); | ... | ... |
-
Please register or login to post a comment