Committed by
Gerrit Code Review
CORD-48 First checkin for enabling OF-DPA driver to support the SR app.
Filtering Objective support added. Driver renamed from OFDPA1 to OFDPA2. Code refactored within driver to reflect test-code which will be used by static flow-pusher app in the future. Change-Id: I7132d8b8eaf28df7c11646c5a35035f258c65af4
Showing
10 changed files
with
885 additions
and
385 deletions
... | @@ -112,7 +112,7 @@ public class ArpHandler { | ... | @@ -112,7 +112,7 @@ public class ArpHandler { |
112 | 112 | ||
113 | 113 | ||
114 | private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) { | 114 | private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) { |
115 | - List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId); | 115 | + List<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); |
116 | if (gatewayIpAddresses != null) { | 116 | if (gatewayIpAddresses != null) { |
117 | Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest | 117 | Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest |
118 | .getTargetProtocolAddress()); | 118 | .getTargetProtocolAddress()); | ... | ... |
... | @@ -499,14 +499,13 @@ public class DefaultRoutingHandler { | ... | @@ -499,14 +499,13 @@ public class DefaultRoutingHandler { |
499 | } | 499 | } |
500 | 500 | ||
501 | /** | 501 | /** |
502 | - * Populates table miss entries for all tables, and pipeline rules for VLAN | 502 | + * Populates filtering rules for permitting Router DstMac and VLAN. |
503 | - * and TCAM tables. XXX rename/rethink | ||
504 | * | 503 | * |
505 | * @param deviceId Switch ID to set the rules | 504 | * @param deviceId Switch ID to set the rules |
506 | */ | 505 | */ |
507 | - public void populateTtpRules(DeviceId deviceId) { | 506 | + public void populatePortAddressingRules(DeviceId deviceId) { |
508 | - rulePopulator.populateTableVlan(deviceId); | 507 | + rulePopulator.populateRouterMacVlanFilters(deviceId); |
509 | - rulePopulator.populateTableTMac(deviceId); | 508 | + rulePopulator.populateRouterIpPunts(deviceId); |
510 | } | 509 | } |
511 | 510 | ||
512 | /** | 511 | /** | ... | ... |
... | @@ -126,7 +126,7 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -126,7 +126,7 @@ public class DeviceConfiguration implements DeviceProperties { |
126 | } | 126 | } |
127 | 127 | ||
128 | /** | 128 | /** |
129 | - * Returns the segment id of a segment router. | 129 | + * Returns the Node segment id of a segment router. |
130 | * | 130 | * |
131 | * @param deviceId device identifier | 131 | * @param deviceId device identifier |
132 | * @return segment id | 132 | * @return segment id |
... | @@ -147,7 +147,7 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -147,7 +147,7 @@ public class DeviceConfiguration implements DeviceProperties { |
147 | } | 147 | } |
148 | 148 | ||
149 | /** | 149 | /** |
150 | - * Returns the segment id of a segment router given its mac address. | 150 | + * Returns the Node segment id of a segment router given its Router mac address. |
151 | * | 151 | * |
152 | * @param routerMac router mac address | 152 | * @param routerMac router mac address |
153 | * @return segment id | 153 | * @return segment id |
... | @@ -164,7 +164,7 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -164,7 +164,7 @@ public class DeviceConfiguration implements DeviceProperties { |
164 | } | 164 | } |
165 | 165 | ||
166 | /** | 166 | /** |
167 | - * Returns the segment id of a segment router given its router ip address. | 167 | + * Returns the Node segment id of a segment router given its Router ip address. |
168 | * | 168 | * |
169 | * @param routerAddress router ip address | 169 | * @param routerAddress router ip address |
170 | * @return segment id | 170 | * @return segment id |
... | @@ -223,7 +223,7 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -223,7 +223,7 @@ public class DeviceConfiguration implements DeviceProperties { |
223 | 223 | ||
224 | /** | 224 | /** |
225 | * Indicates if the segment router is a edge router or | 225 | * Indicates if the segment router is a edge router or |
226 | - * a transit/back bone router. | 226 | + * a core/backbone router. |
227 | * | 227 | * |
228 | * @param deviceId device identifier | 228 | * @param deviceId device identifier |
229 | * @return boolean | 229 | * @return boolean |
... | @@ -244,9 +244,9 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -244,9 +244,9 @@ public class DeviceConfiguration implements DeviceProperties { |
244 | } | 244 | } |
245 | 245 | ||
246 | /** | 246 | /** |
247 | - * Returns the segment ids of all configured segment routers. | 247 | + * Returns the node segment ids of all configured segment routers. |
248 | * | 248 | * |
249 | - * @return list of segment ids | 249 | + * @return list of node segment ids |
250 | */ | 250 | */ |
251 | @Override | 251 | @Override |
252 | public List<Integer> getAllDeviceSegmentIds() { | 252 | public List<Integer> getAllDeviceSegmentIds() { |
... | @@ -290,12 +290,14 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -290,12 +290,14 @@ public class DeviceConfiguration implements DeviceProperties { |
290 | } | 290 | } |
291 | 291 | ||
292 | /** | 292 | /** |
293 | - * Returns the configured subnet gateway ip addresses for a segment router. | 293 | + * Returns the configured port ip addresses for a segment router. |
294 | + * These addresses serve as gateway IP addresses for the subnets configured | ||
295 | + * on those ports. | ||
294 | * | 296 | * |
295 | * @param deviceId device identifier | 297 | * @param deviceId device identifier |
296 | - * @return list of ip addresses | 298 | + * @return list of ip addresses configured on the ports |
297 | */ | 299 | */ |
298 | - public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) { | 300 | + public List<Ip4Address> getPortIPs(DeviceId deviceId) { |
299 | if (deviceConfigMap.get(deviceId) != null) { | 301 | if (deviceConfigMap.get(deviceId) != null) { |
300 | log.trace("getSubnetGatewayIps for device{} is {}", | 302 | log.trace("getSubnetGatewayIps for device{} is {}", |
301 | deviceId, | 303 | deviceId, |
... | @@ -307,6 +309,20 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -307,6 +309,20 @@ public class DeviceConfiguration implements DeviceProperties { |
307 | } | 309 | } |
308 | 310 | ||
309 | /** | 311 | /** |
312 | + * Returns the configured IP addresses per port | ||
313 | + * for a segment router. | ||
314 | + * | ||
315 | + * @param deviceId device identifier | ||
316 | + * @return map of port to gateway IP addresses | ||
317 | + */ | ||
318 | + public Map<PortNumber, Ip4Address> getPortIPMap(DeviceId deviceId) { | ||
319 | + if (deviceConfigMap.get(deviceId) != null) { | ||
320 | + return deviceConfigMap.get(deviceId).gatewayIps; | ||
321 | + } | ||
322 | + return null; | ||
323 | + } | ||
324 | + | ||
325 | + /** | ||
310 | * Returns the configured subnet prefixes for a segment router. | 326 | * Returns the configured subnet prefixes for a segment router. |
311 | * | 327 | * |
312 | * @param deviceId device identifier | 328 | * @param deviceId device identifier | ... | ... |
... | @@ -70,7 +70,7 @@ public class IcmpHandler { | ... | @@ -70,7 +70,7 @@ public class IcmpHandler { |
70 | DeviceId deviceId = connectPoint.deviceId(); | 70 | DeviceId deviceId = connectPoint.deviceId(); |
71 | Ip4Address destinationAddress = | 71 | Ip4Address destinationAddress = |
72 | Ip4Address.valueOf(ipv4.getDestinationAddress()); | 72 | Ip4Address.valueOf(ipv4.getDestinationAddress()); |
73 | - List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId); | 73 | + List<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); |
74 | Ip4Address routerIp = config.getRouterIp(deviceId); | 74 | Ip4Address routerIp = config.getRouterIp(deviceId); |
75 | IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH); | 75 | IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH); |
76 | Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address(); | 76 | Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address(); | ... | ... |
... | @@ -38,6 +38,7 @@ import org.onosproject.net.flowobjective.ForwardingObjective; | ... | @@ -38,6 +38,7 @@ import org.onosproject.net.flowobjective.ForwardingObjective; |
38 | import org.onosproject.net.flowobjective.Objective; | 38 | import org.onosproject.net.flowobjective.Objective; |
39 | import org.onosproject.net.flowobjective.ObjectiveError; | 39 | import org.onosproject.net.flowobjective.ObjectiveError; |
40 | import org.onosproject.net.flowobjective.ForwardingObjective.Builder; | 40 | import org.onosproject.net.flowobjective.ForwardingObjective.Builder; |
41 | +import org.onosproject.net.flowobjective.ForwardingObjective.Flag; | ||
41 | import org.onosproject.net.flowobjective.ObjectiveContext; | 42 | import org.onosproject.net.flowobjective.ObjectiveContext; |
42 | import org.slf4j.Logger; | 43 | import org.slf4j.Logger; |
43 | import org.slf4j.LoggerFactory; | 44 | import org.slf4j.LoggerFactory; |
... | @@ -57,6 +58,9 @@ public class RoutingRulePopulator { | ... | @@ -57,6 +58,9 @@ public class RoutingRulePopulator { |
57 | private AtomicLong rulePopulationCounter; | 58 | private AtomicLong rulePopulationCounter; |
58 | private SegmentRoutingManager srManager; | 59 | private SegmentRoutingManager srManager; |
59 | private DeviceConfiguration config; | 60 | private DeviceConfiguration config; |
61 | + | ||
62 | + private static final int HIGHEST_PRIORITY = 0xffff; | ||
63 | + | ||
60 | /** | 64 | /** |
61 | * Creates a RoutingRulePopulator object. | 65 | * Creates a RoutingRulePopulator object. |
62 | * | 66 | * |
... | @@ -98,7 +102,7 @@ public class RoutingRulePopulator { | ... | @@ -98,7 +102,7 @@ public class RoutingRulePopulator { |
98 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); | 102 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); |
99 | TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); | 103 | TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); |
100 | 104 | ||
101 | - sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, 32)); | 105 | + sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH)); |
102 | sbuilder.matchEthType(Ethernet.TYPE_IPV4); | 106 | sbuilder.matchEthType(Ethernet.TYPE_IPV4); |
103 | 107 | ||
104 | tbuilder.deferred() | 108 | tbuilder.deferred() |
... | @@ -350,16 +354,22 @@ public class RoutingRulePopulator { | ... | @@ -350,16 +354,22 @@ public class RoutingRulePopulator { |
350 | } | 354 | } |
351 | 355 | ||
352 | /** | 356 | /** |
353 | - * Populates VLAN flows rules. All packets are forwarded to TMAC table. | 357 | + * Creates a filtering objective to permit all untagged packets with a |
358 | + * dstMac corresponding to the router's MAC address. | ||
354 | * | 359 | * |
355 | - * @param deviceId switch ID to set the rules | 360 | + * @param deviceId the switch dpid for the router |
356 | */ | 361 | */ |
357 | - public void populateTableVlan(DeviceId deviceId) { | 362 | + public void populateRouterMacVlanFilters(DeviceId deviceId) { |
358 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); | 363 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); |
359 | fob.withKey(Criteria.matchInPort(PortNumber.ALL)) | 364 | fob.withKey(Criteria.matchInPort(PortNumber.ALL)) |
360 | - .addCondition(Criteria.matchVlanId(VlanId.NONE)); | 365 | + .addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId))) |
366 | + .addCondition(Criteria.matchVlanId(VlanId.NONE)) | ||
367 | + .addCondition(Criteria.matchIPDst( | ||
368 | + IpPrefix.valueOf(config.getRouterIp(deviceId), | ||
369 | + IpPrefix.MAX_INET_MASK_LENGTH))); | ||
370 | + | ||
361 | fob.permit().fromApp(srManager.appId); | 371 | fob.permit().fromApp(srManager.appId); |
362 | - log.debug("populateTableVlan: Installing filtering objective for untagged packets"); | 372 | + log.debug("Installing filtering objective for untagged packets"); |
363 | srManager.flowObjectiveService. | 373 | srManager.flowObjectiveService. |
364 | filter(deviceId, | 374 | filter(deviceId, |
365 | fob.add(new SRObjectiveContext(deviceId, | 375 | fob.add(new SRObjectiveContext(deviceId, |
... | @@ -367,23 +377,35 @@ public class RoutingRulePopulator { | ... | @@ -367,23 +377,35 @@ public class RoutingRulePopulator { |
367 | } | 377 | } |
368 | 378 | ||
369 | /** | 379 | /** |
370 | - * Populates TMAC table rules. IP packets are forwarded to IP table. MPLS | 380 | + * Creates a forwarding objective to punt all IP packets, destined to the |
371 | - * packets are forwarded to MPLS table. | 381 | + * router's port IP addresses, to the controller. Note that it the input |
382 | + * port should not be matched on, as these packets can come from any input. | ||
372 | * | 383 | * |
373 | - * @param deviceId switch ID to set the rules | 384 | + * @param deviceId the switch dpid for the router |
374 | */ | 385 | */ |
375 | - public void populateTableTMac(DeviceId deviceId) { | 386 | + public void populateRouterIpPunts(DeviceId deviceId) { |
376 | - | 387 | + ForwardingObjective.Builder puntIp = DefaultForwardingObjective.builder(); |
377 | - FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); | 388 | + |
378 | - fob.withKey(Criteria.matchInPort(PortNumber.ALL)) | 389 | + List<Ip4Address> gws = config.getPortIPs(deviceId); |
379 | - .addCondition(Criteria.matchEthDst(config | 390 | + for (Ip4Address ipaddr : gws) { |
380 | - .getDeviceMac(deviceId))); | 391 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
381 | - fob.permit().fromApp(srManager.appId); | 392 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); |
382 | - log.debug("populateTableTMac: Installing filtering objective for router mac"); | 393 | + selector.matchEthType(Ethernet.TYPE_IPV4); |
383 | - srManager.flowObjectiveService. | 394 | + selector.matchIPDst(IpPrefix.valueOf(ipaddr, |
384 | - filter(deviceId, | 395 | + IpPrefix.MAX_INET_MASK_LENGTH)); |
385 | - fob.add(new SRObjectiveContext(deviceId, | 396 | + treatment.setOutput(PortNumber.CONTROLLER); |
386 | - SRObjectiveContext.ObjectiveType.FILTER))); | 397 | + puntIp.withSelector(selector.build()); |
398 | + puntIp.withTreatment(treatment.build()); | ||
399 | + puntIp.withFlag(Flag.VERSATILE) | ||
400 | + .withPriority(HIGHEST_PRIORITY) | ||
401 | + .makePermanent() | ||
402 | + .fromApp(srManager.appId); | ||
403 | + log.debug("Installing forwarding objective to punt port IP addresses"); | ||
404 | + srManager.flowObjectiveService. | ||
405 | + forward(deviceId, | ||
406 | + puntIp.add(new SRObjectiveContext(deviceId, | ||
407 | + SRObjectiveContext.ObjectiveType.FORWARDING))); | ||
408 | + } | ||
387 | } | 409 | } |
388 | 410 | ||
389 | private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) { | 411 | private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) { | ... | ... |
... | @@ -497,7 +497,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -497,7 +497,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
497 | flowObjectiveService, | 497 | flowObjectiveService, |
498 | nsNextObjStore); | 498 | nsNextObjStore); |
499 | groupHandlerMap.put(device.id(), dgh); | 499 | groupHandlerMap.put(device.id(), dgh); |
500 | - defaultRoutingHandler.populateTtpRules(device.id()); | 500 | + defaultRoutingHandler.populatePortAddressingRules(device.id()); |
501 | } | 501 | } |
502 | 502 | ||
503 | private void processPortRemoved(Device device, Port port) { | 503 | private void processPortRemoved(Device device, Port port) { |
... | @@ -542,7 +542,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -542,7 +542,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
542 | flowObjectiveService, | 542 | flowObjectiveService, |
543 | nsNextObjStore); | 543 | nsNextObjStore); |
544 | groupHandlerMap.put(device.id(), groupHandler); | 544 | groupHandlerMap.put(device.id(), groupHandler); |
545 | - defaultRoutingHandler.populateTtpRules(device.id()); | 545 | + defaultRoutingHandler.populatePortAddressingRules(device.id()); |
546 | } | 546 | } |
547 | 547 | ||
548 | defaultRoutingHandler.startPopulationProcess(); | 548 | defaultRoutingHandler.startPopulationProcess(); | ... | ... |
... | @@ -29,22 +29,23 @@ import org.slf4j.Logger; | ... | @@ -29,22 +29,23 @@ import org.slf4j.Logger; |
29 | 29 | ||
30 | 30 | ||
31 | /** | 31 | /** |
32 | - * Driver for software switch emulation of the OFDPA 1.0 pipeline. | 32 | + * Driver for software switch emulation of the OFDPA 2.0 pipeline. |
33 | * The software switch is the CPqD OF 1.3 switch. | 33 | * The software switch is the CPqD OF 1.3 switch. |
34 | */ | 34 | */ |
35 | -public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline { | 35 | +public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { |
36 | 36 | ||
37 | private final Logger log = getLogger(getClass()); | 37 | private final Logger log = getLogger(getClass()); |
38 | 38 | ||
39 | @Override | 39 | @Override |
40 | protected void initializePipeline() { | 40 | protected void initializePipeline() { |
41 | processPortTable(); | 41 | processPortTable(); |
42 | - //processVlanTable(); | ||
43 | processTmacTable(); | 42 | processTmacTable(); |
44 | processIpTable(); | 43 | processIpTable(); |
45 | - //processMcastTable(); | ||
46 | processBridgingTable(); | 44 | processBridgingTable(); |
47 | processAclTable(); | 45 | processAclTable(); |
46 | + // XXX implement table miss entries and default groups | ||
47 | + //processVlanTable(); | ||
48 | + //processMPLSTable(); | ||
48 | //processGroupTable(); | 49 | //processGroupTable(); |
49 | } | 50 | } |
50 | 51 | ||
... | @@ -169,6 +170,7 @@ public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline { | ... | @@ -169,6 +170,7 @@ public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline { |
169 | })); | 170 | })); |
170 | } | 171 | } |
171 | 172 | ||
173 | + @Override | ||
172 | protected void processAclTable() { | 174 | protected void processAclTable() { |
173 | //table miss entry - catch all to executed action-set | 175 | //table miss entry - catch all to executed action-set |
174 | FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | 176 | FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ... | ... |
... | @@ -18,6 +18,7 @@ package org.onosproject.driver.pipeline; | ... | @@ -18,6 +18,7 @@ package org.onosproject.driver.pipeline; |
18 | import static org.onlab.util.Tools.groupedThreads; | 18 | import static org.onlab.util.Tools.groupedThreads; |
19 | import static org.slf4j.LoggerFactory.getLogger; | 19 | import static org.slf4j.LoggerFactory.getLogger; |
20 | 20 | ||
21 | +import java.nio.ByteBuffer; | ||
21 | import java.util.ArrayList; | 22 | import java.util.ArrayList; |
22 | import java.util.Collection; | 23 | import java.util.Collection; |
23 | import java.util.Collections; | 24 | import java.util.Collections; |
... | @@ -30,18 +31,26 @@ import java.util.concurrent.TimeUnit; | ... | @@ -30,18 +31,26 @@ import java.util.concurrent.TimeUnit; |
30 | import java.util.stream.Collectors; | 31 | import java.util.stream.Collectors; |
31 | 32 | ||
32 | import org.onlab.osgi.ServiceDirectory; | 33 | import org.onlab.osgi.ServiceDirectory; |
34 | +import org.onlab.packet.Data; | ||
33 | import org.onlab.packet.Ethernet; | 35 | import org.onlab.packet.Ethernet; |
36 | +import org.onlab.packet.IPv4; | ||
37 | +import org.onlab.packet.IpPrefix; | ||
38 | +import org.onlab.packet.MPLS; | ||
39 | +import org.onlab.packet.MacAddress; | ||
34 | import org.onlab.packet.MplsLabel; | 40 | import org.onlab.packet.MplsLabel; |
41 | +import org.onlab.packet.UDP; | ||
35 | import org.onlab.packet.VlanId; | 42 | import org.onlab.packet.VlanId; |
36 | import org.onlab.util.KryoNamespace; | 43 | import org.onlab.util.KryoNamespace; |
37 | import org.onosproject.core.ApplicationId; | 44 | import org.onosproject.core.ApplicationId; |
38 | import org.onosproject.core.CoreService; | 45 | import org.onosproject.core.CoreService; |
39 | import org.onosproject.core.DefaultGroupId; | 46 | import org.onosproject.core.DefaultGroupId; |
40 | import org.onosproject.net.DeviceId; | 47 | import org.onosproject.net.DeviceId; |
48 | +import org.onosproject.net.Port; | ||
41 | import org.onosproject.net.PortNumber; | 49 | import org.onosproject.net.PortNumber; |
42 | import org.onosproject.net.behaviour.NextGroup; | 50 | import org.onosproject.net.behaviour.NextGroup; |
43 | import org.onosproject.net.behaviour.Pipeliner; | 51 | import org.onosproject.net.behaviour.Pipeliner; |
44 | import org.onosproject.net.behaviour.PipelinerContext; | 52 | import org.onosproject.net.behaviour.PipelinerContext; |
53 | +import org.onosproject.net.device.DeviceService; | ||
45 | import org.onosproject.net.driver.AbstractHandlerBehaviour; | 54 | import org.onosproject.net.driver.AbstractHandlerBehaviour; |
46 | import org.onosproject.net.flow.DefaultFlowRule; | 55 | import org.onosproject.net.flow.DefaultFlowRule; |
47 | import org.onosproject.net.flow.DefaultTrafficSelector; | 56 | import org.onosproject.net.flow.DefaultTrafficSelector; |
... | @@ -81,6 +90,11 @@ import org.onosproject.net.group.GroupEvent; | ... | @@ -81,6 +90,11 @@ import org.onosproject.net.group.GroupEvent; |
81 | import org.onosproject.net.group.GroupKey; | 90 | import org.onosproject.net.group.GroupKey; |
82 | import org.onosproject.net.group.GroupListener; | 91 | import org.onosproject.net.group.GroupListener; |
83 | import org.onosproject.net.group.GroupService; | 92 | import org.onosproject.net.group.GroupService; |
93 | +import org.onosproject.net.packet.DefaultOutboundPacket; | ||
94 | +import org.onosproject.net.packet.OutboundPacket; | ||
95 | +import org.onosproject.net.packet.PacketContext; | ||
96 | +import org.onosproject.net.packet.PacketProcessor; | ||
97 | +import org.onosproject.net.packet.PacketService; | ||
84 | import org.onosproject.store.serializers.KryoNamespaces; | 98 | import org.onosproject.store.serializers.KryoNamespaces; |
85 | import org.slf4j.Logger; | 99 | import org.slf4j.Logger; |
86 | 100 | ||
... | @@ -90,19 +104,22 @@ import com.google.common.cache.RemovalCause; | ... | @@ -90,19 +104,22 @@ import com.google.common.cache.RemovalCause; |
90 | import com.google.common.cache.RemovalNotification; | 104 | import com.google.common.cache.RemovalNotification; |
91 | 105 | ||
92 | /** | 106 | /** |
93 | - * Driver for Broadcom's OF-DPA v1.0 TTP. | 107 | + * Driver for Broadcom's OF-DPA v2.0 TTP. |
94 | * | 108 | * |
95 | */ | 109 | */ |
96 | -public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeliner { | 110 | +public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeliner { |
97 | 111 | ||
98 | protected static final int PORT_TABLE = 0; | 112 | protected static final int PORT_TABLE = 0; |
99 | protected static final int VLAN_TABLE = 10; | 113 | protected static final int VLAN_TABLE = 10; |
100 | protected static final int TMAC_TABLE = 20; | 114 | protected static final int TMAC_TABLE = 20; |
101 | protected static final int UNICAST_ROUTING_TABLE = 30; | 115 | protected static final int UNICAST_ROUTING_TABLE = 30; |
102 | protected static final int MULTICAST_ROUTING_TABLE = 40; | 116 | protected static final int MULTICAST_ROUTING_TABLE = 40; |
117 | + protected static final int MPLS_TABLE_0 = 23; | ||
118 | + protected static final int MPLS_TABLE_1 = 24; | ||
103 | protected static final int BRIDGING_TABLE = 50; | 119 | protected static final int BRIDGING_TABLE = 50; |
104 | protected static final int ACL_TABLE = 60; | 120 | protected static final int ACL_TABLE = 60; |
105 | protected static final int MAC_LEARNING_TABLE = 254; | 121 | protected static final int MAC_LEARNING_TABLE = 254; |
122 | + protected static final long OFPP_MAX = 0xffffff00L; | ||
106 | 123 | ||
107 | private static final int HIGHEST_PRIORITY = 0xffff; | 124 | private static final int HIGHEST_PRIORITY = 0xffff; |
108 | private static final int DEFAULT_PRIORITY = 0x8000; | 125 | private static final int DEFAULT_PRIORITY = 0x8000; |
... | @@ -128,6 +145,14 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -128,6 +145,14 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
128 | */ | 145 | */ |
129 | private static final int L2INTERFACEMASK = 0x0; | 146 | private static final int L2INTERFACEMASK = 0x0; |
130 | private static final int L3UNICASTMASK = 0x20000000; | 147 | private static final int L3UNICASTMASK = 0x20000000; |
148 | + //private static final int MPLSINTERFACEMASK = 0x90000000; | ||
149 | + private static final int L3ECMPMASK = 0x70000000; | ||
150 | + | ||
151 | + /* | ||
152 | + * This driver assigns all incoming untagged packets the same VLAN ID | ||
153 | + */ | ||
154 | + private static final short UNTAGGED_ASSIGNED_VLAN = 0xffa; // 4090 | ||
155 | + | ||
131 | 156 | ||
132 | private final Logger log = getLogger(getClass()); | 157 | private final Logger log = getLogger(getClass()); |
133 | private ServiceDirectory serviceDirectory; | 158 | private ServiceDirectory serviceDirectory; |
... | @@ -137,7 +162,9 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -137,7 +162,9 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
137 | private FlowObjectiveStore flowObjectiveStore; | 162 | private FlowObjectiveStore flowObjectiveStore; |
138 | protected DeviceId deviceId; | 163 | protected DeviceId deviceId; |
139 | protected ApplicationId driverId; | 164 | protected ApplicationId driverId; |
140 | - | 165 | + protected PacketService packetService; |
166 | + protected DeviceService deviceService; | ||
167 | + private InternalPacketProcessor processor = new InternalPacketProcessor(); | ||
141 | private KryoNamespace appKryo = new KryoNamespace.Builder() | 168 | private KryoNamespace appKryo = new KryoNamespace.Builder() |
142 | .register(KryoNamespaces.API) | 169 | .register(KryoNamespaces.API) |
143 | .register(GroupKey.class) | 170 | .register(GroupKey.class) |
... | @@ -151,7 +178,9 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -151,7 +178,9 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
151 | 178 | ||
152 | private ScheduledExecutorService groupChecker = | 179 | private ScheduledExecutorService groupChecker = |
153 | Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", | 180 | Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", |
154 | - "ofdpa1-%d")); | 181 | + "ofdpa2-%d")); |
182 | + private Set<IPCriterion> sentIpFilters = Collections.newSetFromMap( | ||
183 | + new ConcurrentHashMap<IPCriterion, Boolean>()); | ||
155 | 184 | ||
156 | @Override | 185 | @Override |
157 | public void init(DeviceId deviceId, PipelinerContext context) { | 186 | public void init(DeviceId deviceId, PipelinerContext context) { |
... | @@ -174,16 +203,29 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -174,16 +203,29 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
174 | flowRuleService = serviceDirectory.get(FlowRuleService.class); | 203 | flowRuleService = serviceDirectory.get(FlowRuleService.class); |
175 | groupService = serviceDirectory.get(GroupService.class); | 204 | groupService = serviceDirectory.get(GroupService.class); |
176 | flowObjectiveStore = context.store(); | 205 | flowObjectiveStore = context.store(); |
177 | - | 206 | + packetService = serviceDirectory.get(PacketService.class); |
207 | + deviceService = serviceDirectory.get(DeviceService.class); | ||
208 | + packetService.addProcessor(processor, PacketProcessor.director(2)); | ||
178 | groupService.addListener(new InnerGroupListener()); | 209 | groupService.addListener(new InnerGroupListener()); |
179 | 210 | ||
180 | driverId = coreService.registerApplication( | 211 | driverId = coreService.registerApplication( |
181 | - "org.onosproject.driver.OFDPA1Pipeline"); | 212 | + "org.onosproject.driver.OFDPA2Pipeline"); |
182 | 213 | ||
214 | + // OF-DPA does not require initializing the pipeline as it puts default | ||
215 | + // rules automatically in the hardware. However emulation of OFDPA in | ||
216 | + // software switches does require table-miss-entries. | ||
183 | initializePipeline(); | 217 | initializePipeline(); |
184 | 218 | ||
185 | } | 219 | } |
186 | 220 | ||
221 | + protected void initializePipeline() { | ||
222 | + | ||
223 | + } | ||
224 | + | ||
225 | + ////////////////////////////////////// | ||
226 | + // Flow Objectives | ||
227 | + ////////////////////////////////////// | ||
228 | + | ||
187 | @Override | 229 | @Override |
188 | public void filter(FilteringObjective filteringObjective) { | 230 | public void filter(FilteringObjective filteringObjective) { |
189 | if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { | 231 | if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { |
... | @@ -191,6 +233,11 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -191,6 +233,11 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
191 | filteringObjective.op() == Objective.Operation.ADD, | 233 | filteringObjective.op() == Objective.Operation.ADD, |
192 | filteringObjective.appId()); | 234 | filteringObjective.appId()); |
193 | } else { | 235 | } else { |
236 | + // Note that packets that don't match the PERMIT filter are | ||
237 | + // automatically denied. The DENY filter is used to deny packets | ||
238 | + // that are otherwise permitted by the PERMIT filter. | ||
239 | + // Use ACL table flow rules here for DENY filtering objectives | ||
240 | + log.debug("filter objective other than PERMIT currently not supported"); | ||
194 | fail(filteringObjective, ObjectiveError.UNSUPPORTED); | 241 | fail(filteringObjective, ObjectiveError.UNSUPPORTED); |
195 | } | 242 | } |
196 | } | 243 | } |
... | @@ -257,25 +304,31 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -257,25 +304,31 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
257 | } | 304 | } |
258 | } | 305 | } |
259 | 306 | ||
307 | + ////////////////////////////////////// | ||
308 | + // Flow handling | ||
309 | + ////////////////////////////////////// | ||
310 | + | ||
260 | /** | 311 | /** |
261 | - * As per OFDPA 1.0 TTP, filtering of VLAN ids, MAC addresses (for routing) | 312 | + * As per OFDPA 2.0 TTP, filtering of VLAN ids, MAC addresses (for routing) |
262 | * and IP addresses configured on switch ports happen in different tables. | 313 | * and IP addresses configured on switch ports happen in different tables. |
263 | * Note that IP filtering rules need to be added to the ACL table, as there | 314 | * Note that IP filtering rules need to be added to the ACL table, as there |
264 | * is no mechanism to send to controller via IP table. | 315 | * is no mechanism to send to controller via IP table. |
265 | * | 316 | * |
266 | - * @param filt | 317 | + * @param filt the filtering objective |
267 | - * @param install | 318 | + * @param install indicates whether to add or remove the objective |
268 | - * @param applicationId | 319 | + * @param applicationId the application that sent this objective |
269 | */ | 320 | */ |
270 | private void processFilter(FilteringObjective filt, | 321 | private void processFilter(FilteringObjective filt, |
271 | boolean install, ApplicationId applicationId) { | 322 | boolean install, ApplicationId applicationId) { |
272 | // This driver only processes filtering criteria defined with switch | 323 | // This driver only processes filtering criteria defined with switch |
273 | // ports as the key | 324 | // ports as the key |
274 | - PortCriterion p = null; EthCriterion e = null; VlanIdCriterion v = null; | 325 | + PortCriterion portCriterion = null; |
326 | + EthCriterion ethCriterion = null; | ||
327 | + VlanIdCriterion vidCriterion = null; | ||
275 | Collection<IPCriterion> ips = new ArrayList<IPCriterion>(); | 328 | Collection<IPCriterion> ips = new ArrayList<IPCriterion>(); |
276 | if (!filt.key().equals(Criteria.dummy()) && | 329 | if (!filt.key().equals(Criteria.dummy()) && |
277 | filt.key().type() == Criterion.Type.IN_PORT) { | 330 | filt.key().type() == Criterion.Type.IN_PORT) { |
278 | - p = (PortCriterion) filt.key(); | 331 | + portCriterion = (PortCriterion) filt.key(); |
279 | } else { | 332 | } else { |
280 | log.warn("No key defined in filtering objective from app: {}. Not" | 333 | log.warn("No key defined in filtering objective from app: {}. Not" |
281 | + "processing filtering objective", applicationId); | 334 | + "processing filtering objective", applicationId); |
... | @@ -284,199 +337,208 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -284,199 +337,208 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
284 | } | 337 | } |
285 | // convert filtering conditions for switch-intfs into flowrules | 338 | // convert filtering conditions for switch-intfs into flowrules |
286 | FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | 339 | FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); |
287 | - for (Criterion c : filt.conditions()) { | 340 | + for (Criterion criterion : filt.conditions()) { |
288 | - if (c.type() == Criterion.Type.ETH_DST) { | 341 | + if (criterion.type() == Criterion.Type.ETH_DST) { |
289 | - e = (EthCriterion) c; | 342 | + ethCriterion = (EthCriterion) criterion; |
290 | - } else if (c.type() == Criterion.Type.VLAN_VID) { | 343 | + } else if (criterion.type() == Criterion.Type.VLAN_VID) { |
291 | - v = (VlanIdCriterion) c; | 344 | + vidCriterion = (VlanIdCriterion) criterion; |
292 | - } else if (c.type() == Criterion.Type.IPV4_DST) { | 345 | + } else if (criterion.type() == Criterion.Type.IPV4_DST) { |
293 | - ips.add((IPCriterion) c); | 346 | + ips.add((IPCriterion) criterion); |
294 | } else { | 347 | } else { |
295 | - log.error("Unsupported filter {}", c); | 348 | + log.error("Unsupported filter {}", criterion); |
296 | fail(filt, ObjectiveError.UNSUPPORTED); | 349 | fail(filt, ObjectiveError.UNSUPPORTED); |
297 | return; | 350 | return; |
298 | } | 351 | } |
299 | } | 352 | } |
300 | 353 | ||
301 | - log.debug("adding VLAN filtering rule in VLAN table: {}", e.mac()); | 354 | + if (ethCriterion == null) { |
302 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 355 | + log.debug("filtering objective missing dstMac, cannot program TMAC table"); |
303 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | 356 | + } else { |
304 | - selector.matchInPort(p.port()); | 357 | + for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion, |
305 | - selector.matchVlanId(v.vlanId()); | 358 | + vidCriterion, applicationId)) { |
306 | - treatment.transition(TMAC_TABLE); | 359 | + log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}", |
307 | - FlowRule rule = DefaultFlowRule.builder() | 360 | + tmacRule, deviceId); |
308 | - .forDevice(deviceId) | 361 | + ops = install ? ops.add(tmacRule) : ops.remove(tmacRule); |
309 | - .withSelector(selector.build()) | 362 | + } |
310 | - .withTreatment(treatment.build()) | 363 | + } |
311 | - .withPriority(DEFAULT_PRIORITY) | ||
312 | - .fromApp(applicationId) | ||
313 | - .makePermanent() | ||
314 | - .forTable(VLAN_TABLE).build(); | ||
315 | - ops = ops.add(rule); | ||
316 | 364 | ||
317 | - log.debug("adding MAC filtering rules in TMAC table: {}", e.mac()); | 365 | + if (ethCriterion == null || vidCriterion == null) { |
318 | - selector = DefaultTrafficSelector.builder(); | 366 | + log.debug("filtering objective missing dstMac or vlan, cannot program" |
319 | - treatment = DefaultTrafficTreatment.builder(); | 367 | + + "Vlan Table"); |
320 | - selector.matchInPort(p.port()); | 368 | + } else { |
321 | - selector.matchVlanId(v.vlanId()); | 369 | + for (FlowRule vlanRule : processVlanIdFilter(portCriterion, vidCriterion, |
322 | - selector.matchEthType(Ethernet.TYPE_IPV4); | 370 | + applicationId)) { |
323 | - selector.matchEthDst(e.mac()); | 371 | + log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}", |
324 | - treatment.transition(UNICAST_ROUTING_TABLE); | 372 | + vlanRule, deviceId); |
325 | - rule = DefaultFlowRule.builder() | 373 | + ops = install ? ops.add(vlanRule) : ops.remove(vlanRule); |
326 | - .forDevice(deviceId) | 374 | + } |
327 | - .withSelector(selector.build()) | 375 | + } |
328 | - .withTreatment(treatment.build()) | ||
329 | - .withPriority(DEFAULT_PRIORITY) | ||
330 | - .fromApp(applicationId) | ||
331 | - .makePermanent() | ||
332 | - .forTable(TMAC_TABLE).build(); | ||
333 | - ops = ops.add(rule); | ||
334 | 376 | ||
335 | - log.debug("adding IP filtering rules in ACL table"); | ||
336 | for (IPCriterion ipaddr : ips) { | 377 | for (IPCriterion ipaddr : ips) { |
337 | - selector = DefaultTrafficSelector.builder(); | 378 | + // since we ignore port information for IP rules, and the same (gateway) IP |
338 | - treatment = DefaultTrafficTreatment.builder(); | 379 | + // can be configured on multiple ports, we make sure that we send |
339 | - selector.matchEthType(Ethernet.TYPE_IPV4); | 380 | + // only a single rule to the switch. |
340 | - selector.matchIPDst(ipaddr.ip()); | 381 | + if (!sentIpFilters.contains(ipaddr)) { |
341 | - treatment.setOutput(PortNumber.CONTROLLER); | 382 | + sentIpFilters.add(ipaddr); |
342 | - rule = DefaultFlowRule.builder() | 383 | + log.debug("adding IP filtering rules in ACL table {} for dev: {}", |
343 | - .forDevice(deviceId) | 384 | + ipaddr, deviceId); |
344 | - .withSelector(selector.build()) | 385 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
345 | - .withTreatment(treatment.build()) | 386 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); |
346 | - .withPriority(HIGHEST_PRIORITY) | 387 | + selector.matchEthType(Ethernet.TYPE_IPV4); |
347 | - .fromApp(applicationId) | 388 | + selector.matchIPDst(ipaddr.ip()); |
348 | - .makePermanent() | 389 | + treatment.setOutput(PortNumber.CONTROLLER); |
349 | - .forTable(ACL_TABLE).build(); | 390 | + FlowRule rule = DefaultFlowRule.builder() |
350 | - ops = ops.add(rule); | 391 | + .forDevice(deviceId) |
392 | + .withSelector(selector.build()) | ||
393 | + .withTreatment(treatment.build()) | ||
394 | + .withPriority(HIGHEST_PRIORITY) | ||
395 | + .fromApp(applicationId) | ||
396 | + .makePermanent() | ||
397 | + .forTable(ACL_TABLE).build(); | ||
398 | + ops = install ? ops.add(rule) : ops.remove(rule); | ||
399 | + } | ||
351 | } | 400 | } |
352 | 401 | ||
353 | - ops = install ? ops.add(rule) : ops.remove(rule); | ||
354 | // apply filtering flow rules | 402 | // apply filtering flow rules |
355 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | 403 | flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { |
356 | @Override | 404 | @Override |
357 | public void onSuccess(FlowRuleOperations ops) { | 405 | public void onSuccess(FlowRuleOperations ops) { |
358 | - log.info("Applied filtering rules"); | 406 | + log.info("Applied {} filtering rules in device {}", |
407 | + ops.stages().get(0).size(), deviceId); | ||
359 | pass(filt); | 408 | pass(filt); |
360 | } | 409 | } |
361 | 410 | ||
362 | @Override | 411 | @Override |
363 | public void onError(FlowRuleOperations ops) { | 412 | public void onError(FlowRuleOperations ops) { |
364 | - log.info("Failed to apply filtering rules"); | 413 | + log.info("Failed to apply all filtering rules in dev {}", deviceId); |
365 | fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); | 414 | fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); |
366 | } | 415 | } |
367 | })); | 416 | })); |
368 | 417 | ||
369 | } | 418 | } |
370 | 419 | ||
371 | - | ||
372 | /** | 420 | /** |
373 | - * As per the OFDPA 1.0 TTP, packets are sent out of ports by using | 421 | + * Allows untagged packets into pipeline by assigning a vlan id. |
374 | - * a chain of groups, namely an L3 Unicast Group that points to an L2 Interface | 422 | + * Allows tagged packets into pipeline as per configured port-vlan info. |
375 | - * Group which in turns points to an output port. The Next Objective passed | 423 | + * @param portCriterion port on device for which this filter is programmed |
376 | - * in by the application has to be broken up into a group chain | 424 | + * @param vidCriterion vlan assigned to port, or NONE for untagged |
377 | - * to satisfy this TTP. | 425 | + * @param applicationId for application programming this filter |
378 | - * | 426 | + * @return list of FlowRule for port-vlan filters |
379 | - * @param nextObj the nextObjective of type SIMPLE | ||
380 | */ | 427 | */ |
381 | - private void processSimpleNextObjective(NextObjective nextObj) { | 428 | + protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion, |
382 | - // break up simple next objective to GroupChain objects | 429 | + VlanIdCriterion vidCriterion, |
383 | - TrafficTreatment treatment = nextObj.next().iterator().next(); | 430 | + ApplicationId applicationId) { |
384 | - // for the l2interface group, get vlan and port info | 431 | + List<FlowRule> rules = new ArrayList<FlowRule>(); |
385 | - // for the l3unicast group, get the src/dst mac and vlan info | 432 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
386 | - TrafficTreatment.Builder l3utt = DefaultTrafficTreatment.builder(); | 433 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); |
387 | - TrafficTreatment.Builder l2itt = DefaultTrafficTreatment.builder(); | 434 | + selector.matchVlanId(vidCriterion.vlanId()); |
388 | - VlanId vlanid = null; | 435 | + if (vidCriterion.vlanId() == VlanId.NONE) { |
389 | - long portNum = 0; | 436 | + // untagged packets are assigned vlans |
390 | - for (Instruction ins : treatment.allInstructions()) { | 437 | + treatment.pushVlan().setVlanId(VlanId.vlanId(UNTAGGED_ASSIGNED_VLAN)); |
391 | - if (ins.type() == Instruction.Type.L2MODIFICATION) { | 438 | + // XXX ofdpa may require an additional vlan match on the assigned vlan |
392 | - L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; | 439 | + // and it may not require the push. |
393 | - switch (l2ins.subtype()) { | 440 | + } |
394 | - case ETH_DST: | 441 | + treatment.transition(TMAC_TABLE); |
395 | - l3utt.setEthDst(((ModEtherInstruction) l2ins).mac()); | 442 | + |
396 | - break; | 443 | + // ofdpa cannot match on ALL portnumber, so we need to use separate |
397 | - case ETH_SRC: | 444 | + // rules for each port. |
398 | - l3utt.setEthSrc(((ModEtherInstruction) l2ins).mac()); | 445 | + List<PortNumber> portnums = new ArrayList<PortNumber>(); |
399 | - break; | 446 | + if (portCriterion.port() == PortNumber.ALL) { |
400 | - case VLAN_ID: | 447 | + for (Port port : deviceService.getPorts(deviceId)) { |
401 | - vlanid = ((ModVlanIdInstruction) l2ins).vlanId(); | 448 | + if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) { |
402 | - l3utt.setVlanId(vlanid); | 449 | + portnums.add(port.number()); |
403 | - break; | ||
404 | - case DEC_MPLS_TTL: | ||
405 | - case MPLS_LABEL: | ||
406 | - case MPLS_POP: | ||
407 | - case MPLS_PUSH: | ||
408 | - case VLAN_PCP: | ||
409 | - case VLAN_POP: | ||
410 | - case VLAN_PUSH: | ||
411 | - default: | ||
412 | - break; | ||
413 | } | 450 | } |
414 | - } else if (ins.type() == Instruction.Type.OUTPUT) { | ||
415 | - portNum = ((OutputInstruction) ins).port().toLong(); | ||
416 | - l2itt.add(ins); | ||
417 | - } else { | ||
418 | - log.warn("Driver does not handle this type of TrafficTreatment" | ||
419 | - + " instruction in nextObjectives: {}", ins.type()); | ||
420 | } | 451 | } |
452 | + } else { | ||
453 | + portnums.add(portCriterion.port()); | ||
421 | } | 454 | } |
422 | - | 455 | + for (PortNumber pnum : portnums) { |
423 | - // assemble information for ofdpa l2interface group | 456 | + selector.matchInPort(pnum); |
424 | - int l2gk = nextObj.id() | GROUP1MASK; | 457 | + FlowRule rule = DefaultFlowRule.builder() |
425 | - final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk)); | 458 | + .forDevice(deviceId) |
426 | - Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum; | 459 | + .withSelector(selector.build()) |
427 | - | 460 | + .withTreatment(treatment.build()) |
428 | - // assemble information for ofdpa l3unicast group | 461 | + .withPriority(DEFAULT_PRIORITY) |
429 | - int l3gk = nextObj.id() | GROUP0MASK; | 462 | + .fromApp(applicationId) |
430 | - final GroupKey l3groupkey = new DefaultGroupKey(appKryo.serialize(l3gk)); | 463 | + .makePermanent() |
431 | - Integer l3groupId = L3UNICASTMASK | (int) portNum; | 464 | + .forTable(VLAN_TABLE).build(); |
432 | - l3utt.group(new DefaultGroupId(l2groupId)); | 465 | + rules.add(rule); |
433 | - GroupChainElem gce = new GroupChainElem(l3groupkey, l3groupId, | 466 | + } |
434 | - l3utt.build(), nextObj.appId()); | 467 | + return rules; |
435 | - | ||
436 | - // create object for local and distributed storage | ||
437 | - List<GroupKey> gkeys = new ArrayList<GroupKey>(); | ||
438 | - gkeys.add(l3groupkey); // group0 in chain | ||
439 | - gkeys.add(l2groupkey); // group1 in chain | ||
440 | - OfdpaGroupChain ofdpaGrp = new OfdpaGroupChain(gkeys, nextObj); | ||
441 | - | ||
442 | - // store l2groupkey with the groupChainElem for the l3group that depends on it | ||
443 | - pendingGroups.put(l2groupkey, gce); | ||
444 | - | ||
445 | - // store l3groupkey with the ofdpaGroupChain for the nextObjective that depends on it | ||
446 | - pendingNextObjectives.put(l3groupkey, ofdpaGrp); | ||
447 | - | ||
448 | - // create group description for the ofdpa l2interfacegroup and send to groupservice | ||
449 | - GroupBucket bucket = | ||
450 | - DefaultGroupBucket.createIndirectGroupBucket(l2itt.build()); | ||
451 | - GroupDescription groupDescription = new DefaultGroupDescription(deviceId, | ||
452 | - GroupDescription.Type.INDIRECT, | ||
453 | - new GroupBuckets(Collections.singletonList(bucket)), | ||
454 | - l2groupkey, | ||
455 | - l2groupId, | ||
456 | - nextObj.appId()); | ||
457 | - groupService.addGroup(groupDescription); | ||
458 | } | 468 | } |
459 | 469 | ||
460 | /** | 470 | /** |
461 | - * Processes next element of a group chain. Assumption is that if this | 471 | + * Allows routed packets with correct destination MAC to be directed |
462 | - * group points to another group, the latter has already been created | 472 | + * to unicast-IP routing table or MPLS forwarding table. |
463 | - * and this driver has received notification for it. A second assumption is | 473 | + * XXX need to add rule for multicast routing. |
464 | - * that if there is another group waiting for this group then the appropriate | ||
465 | - * stores already have the information to act upon the notification for the | ||
466 | - * creating of this group. | ||
467 | * | 474 | * |
468 | - * @param gce the group chain element to be processed next | 475 | + * @param portCriterion port on device for which this filter is programmed |
476 | + * @param ethCriterion dstMac of device for which is filter is programmed | ||
477 | + * @param vidCriterion vlan assigned to port, or NONE for untagged | ||
478 | + * @param applicationId for application programming this filter | ||
479 | + * @return list of FlowRule for port-vlan filters | ||
480 | + | ||
469 | */ | 481 | */ |
470 | - private void processGroupChain(GroupChainElem gce) { | 482 | + protected List<FlowRule> processEthDstFilter(PortCriterion portCriterion, |
471 | - GroupBucket bucket = DefaultGroupBucket | 483 | + EthCriterion ethCriterion, |
472 | - .createIndirectGroupBucket(gce.getBucketActions()); | 484 | + VlanIdCriterion vidCriterion, |
473 | - GroupDescription groupDesc = new DefaultGroupDescription(deviceId, | 485 | + ApplicationId applicationId) { |
474 | - GroupDescription.Type.INDIRECT, | 486 | + //handling untagged packets via assigned VLAN |
475 | - new GroupBuckets(Collections.singletonList(bucket)), | 487 | + if (vidCriterion.vlanId() == VlanId.NONE) { |
476 | - gce.getGkey(), | 488 | + vidCriterion = (VlanIdCriterion) Criteria |
477 | - gce.getGivenGroupId(), | 489 | + .matchVlanId(VlanId.vlanId(UNTAGGED_ASSIGNED_VLAN)); |
478 | - gce.getAppId()); | 490 | + } |
479 | - groupService.addGroup(groupDesc); | 491 | + // ofdpa cannot match on ALL portnumber, so we need to use separate |
492 | + // rules for each port. | ||
493 | + List<PortNumber> portnums = new ArrayList<PortNumber>(); | ||
494 | + if (portCriterion.port() == PortNumber.ALL) { | ||
495 | + for (Port port : deviceService.getPorts(deviceId)) { | ||
496 | + if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) { | ||
497 | + portnums.add(port.number()); | ||
498 | + } | ||
499 | + } | ||
500 | + } else { | ||
501 | + portnums.add(portCriterion.port()); | ||
502 | + } | ||
503 | + | ||
504 | + List<FlowRule> rules = new ArrayList<FlowRule>(); | ||
505 | + for (PortNumber pnum : portnums) { | ||
506 | + // for unicast IP packets | ||
507 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
508 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
509 | + selector.matchInPort(pnum); | ||
510 | + selector.matchVlanId(vidCriterion.vlanId()); | ||
511 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
512 | + selector.matchEthDst(ethCriterion.mac()); | ||
513 | + treatment.transition(UNICAST_ROUTING_TABLE); | ||
514 | + FlowRule rule = DefaultFlowRule.builder() | ||
515 | + .forDevice(deviceId) | ||
516 | + .withSelector(selector.build()) | ||
517 | + .withTreatment(treatment.build()) | ||
518 | + .withPriority(DEFAULT_PRIORITY) | ||
519 | + .fromApp(applicationId) | ||
520 | + .makePermanent() | ||
521 | + .forTable(TMAC_TABLE).build(); | ||
522 | + rules.add(rule); | ||
523 | + //for MPLS packets | ||
524 | + selector = DefaultTrafficSelector.builder(); | ||
525 | + treatment = DefaultTrafficTreatment.builder(); | ||
526 | + selector.matchInPort(pnum); | ||
527 | + selector.matchVlanId(vidCriterion.vlanId()); | ||
528 | + selector.matchEthType(Ethernet.MPLS_UNICAST); | ||
529 | + selector.matchEthDst(ethCriterion.mac()); | ||
530 | + treatment.transition(MPLS_TABLE_0); | ||
531 | + rule = DefaultFlowRule.builder() | ||
532 | + .forDevice(deviceId) | ||
533 | + .withSelector(selector.build()) | ||
534 | + .withTreatment(treatment.build()) | ||
535 | + .withPriority(DEFAULT_PRIORITY) | ||
536 | + .fromApp(applicationId) | ||
537 | + .makePermanent() | ||
538 | + .forTable(TMAC_TABLE).build(); | ||
539 | + rules.add(rule); | ||
540 | + } | ||
541 | + return rules; | ||
480 | } | 542 | } |
481 | 543 | ||
482 | private Collection<FlowRule> processForward(ForwardingObjective fwd) { | 544 | private Collection<FlowRule> processForward(ForwardingObjective fwd) { |
... | @@ -493,7 +555,7 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -493,7 +555,7 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
493 | } | 555 | } |
494 | 556 | ||
495 | /** | 557 | /** |
496 | - * In the OF-DPA 1.0 pipeline, versatile forwarding objectives go to the | 558 | + * In the OF-DPA 2.0 pipeline, versatile forwarding objectives go to the |
497 | * ACL table. | 559 | * ACL table. |
498 | * @param fwd the forwarding objective of type 'versatile' | 560 | * @param fwd the forwarding objective of type 'versatile' |
499 | * @return a collection of flow rules to be sent to the switch. An empty | 561 | * @return a collection of flow rules to be sent to the switch. An empty |
... | @@ -508,37 +570,46 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -508,37 +570,46 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
508 | (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); | 570 | (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); |
509 | if (ethType == null) { | 571 | if (ethType == null) { |
510 | log.error("Versatile forwarding objective must include ethType"); | 572 | log.error("Versatile forwarding objective must include ethType"); |
511 | - fail(fwd, ObjectiveError.UNKNOWN); | 573 | + fail(fwd, ObjectiveError.BADPARAMS); |
512 | return Collections.emptySet(); | 574 | return Collections.emptySet(); |
513 | } | 575 | } |
514 | - if (ethType.ethType().toShort() == Ethernet.TYPE_ARP) { | 576 | + if (fwd.nextId() == null && fwd.treatment() == null) { |
515 | - log.warn("Installing ARP rule to table 60"); | 577 | + log.error("Forwarding objective {} from {} must contain " |
516 | - | 578 | + + "nextId or Treatment", fwd.selector(), fwd.appId()); |
517 | - // currently need to punt from ACL table should use: | 579 | + return Collections.emptySet(); |
518 | - // OF apply-actions-instruction | 580 | + } |
519 | - // To use OF write-actions-instruction | 581 | + // XXX driver does not currently do type checking as per Tables 65-67 in |
520 | - /*TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); | 582 | + // OFDPA 2.0 spec. The only allowed treatment is a punt to the controller. |
521 | - fwd.treatment().allInstructions().stream() | 583 | + if (fwd.treatment() != null && |
522 | - .forEach(ti -> tb.deferred().add(ti));*/ | 584 | + fwd.treatment().allInstructions().size() == 1 && |
523 | - | 585 | + fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) { |
524 | - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | 586 | + OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0); |
525 | - .fromApp(fwd.appId()) | 587 | + if (o.port() == PortNumber.CONTROLLER) { |
526 | - .withPriority(fwd.priority()) | 588 | + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() |
527 | - .forDevice(deviceId) | 589 | + .fromApp(fwd.appId()) |
528 | - .withSelector(fwd.selector()) | 590 | + .withPriority(fwd.priority()) |
529 | - .withTreatment(fwd.treatment()) | 591 | + .forDevice(deviceId) |
530 | - .makePermanent() | 592 | + .withSelector(fwd.selector()) |
531 | - .forTable(ACL_TABLE); | 593 | + .withTreatment(fwd.treatment()) |
532 | - | 594 | + .makePermanent() |
533 | - return Collections.singletonList(ruleBuilder.build()); | 595 | + .forTable(ACL_TABLE); |
596 | + return Collections.singletonList(ruleBuilder.build()); | ||
597 | + } else { | ||
598 | + log.warn("Only allowed treatments in versatile forwarding " | ||
599 | + + "objectives are punts to the controller"); | ||
600 | + return Collections.emptySet(); | ||
601 | + } | ||
534 | } | 602 | } |
535 | 603 | ||
536 | - // XXX not handling other versatile flows yet | 604 | + if (fwd.nextId() != null) { |
605 | + // XXX overide case | ||
606 | + log.warn("versatile objective --> next Id not yet implemeted"); | ||
607 | + } | ||
537 | return Collections.emptySet(); | 608 | return Collections.emptySet(); |
538 | } | 609 | } |
539 | 610 | ||
540 | /** | 611 | /** |
541 | - * In the OF-DPA 1.0 pipeline, specific forwarding refers to the IP table | 612 | + * In the OF-DPA 2.0 pipeline, specific forwarding refers to the IP table |
542 | * (unicast or multicast) or the L2 table (mac + vlan). | 613 | * (unicast or multicast) or the L2 table (mac + vlan). |
543 | * | 614 | * |
544 | * @param fwd the forwarding objective of type 'specific' | 615 | * @param fwd the forwarding objective of type 'specific' |
... | @@ -602,151 +673,126 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -602,151 +673,126 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
602 | } | 673 | } |
603 | } | 674 | } |
604 | 675 | ||
605 | - | ||
606 | private void fail(Objective obj, ObjectiveError error) { | 676 | private void fail(Objective obj, ObjectiveError error) { |
607 | if (obj.context().isPresent()) { | 677 | if (obj.context().isPresent()) { |
608 | obj.context().get().onError(obj, error); | 678 | obj.context().get().onError(obj, error); |
609 | } | 679 | } |
610 | } | 680 | } |
611 | 681 | ||
682 | + ////////////////////////////////////// | ||
683 | + // Group handling | ||
684 | + ////////////////////////////////////// | ||
612 | 685 | ||
613 | - protected void initializePipeline() { | 686 | + /** |
614 | - processPortTable(); | 687 | + * As per the OFDPA 2.0 TTP, packets are sent out of ports by using |
615 | - processVlanTable(); | 688 | + * a chain of groups, namely an L3 Unicast Group that points to an L2 Interface |
616 | - processTmacTable(); | 689 | + * Group which in turns points to an output port. The Next Objective passed |
617 | - processIpTable(); | 690 | + * in by the application has to be broken up into a group chain |
618 | - //processMcastTable(); | 691 | + * to satisfy this TTP. |
619 | - //processBridgingTable(); | 692 | + * |
620 | - //processAclTable(); | 693 | + * @param nextObj the nextObjective of type SIMPLE |
621 | - //processGroupTable(); | 694 | + */ |
622 | - //processMplsTable(); | 695 | + private void processSimpleNextObjective(NextObjective nextObj) { |
623 | - } | 696 | + // break up simple next objective to GroupChain objects |
697 | + TrafficTreatment treatment = nextObj.next().iterator().next(); | ||
698 | + // for the l2interface group, get vlan and port info | ||
699 | + // for the l3unicast group, get the src/dst mac and vlan info | ||
700 | + TrafficTreatment.Builder l3utt = DefaultTrafficTreatment.builder(); | ||
701 | + TrafficTreatment.Builder l2itt = DefaultTrafficTreatment.builder(); | ||
702 | + VlanId vlanid = null; | ||
703 | + long portNum = 0; | ||
704 | + for (Instruction ins : treatment.allInstructions()) { | ||
705 | + if (ins.type() == Instruction.Type.L2MODIFICATION) { | ||
706 | + L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; | ||
707 | + switch (l2ins.subtype()) { | ||
708 | + case ETH_DST: | ||
709 | + l3utt.setEthDst(((ModEtherInstruction) l2ins).mac()); | ||
710 | + break; | ||
711 | + case ETH_SRC: | ||
712 | + l3utt.setEthSrc(((ModEtherInstruction) l2ins).mac()); | ||
713 | + break; | ||
714 | + case VLAN_ID: | ||
715 | + vlanid = ((ModVlanIdInstruction) l2ins).vlanId(); | ||
716 | + l3utt.setVlanId(vlanid); | ||
717 | + break; | ||
718 | + case DEC_MPLS_TTL: | ||
719 | + case MPLS_LABEL: | ||
720 | + case MPLS_POP: | ||
721 | + case MPLS_PUSH: | ||
722 | + case VLAN_PCP: | ||
723 | + case VLAN_POP: | ||
724 | + case VLAN_PUSH: | ||
725 | + default: | ||
726 | + break; | ||
727 | + } | ||
728 | + } else if (ins.type() == Instruction.Type.OUTPUT) { | ||
729 | + portNum = ((OutputInstruction) ins).port().toLong(); | ||
730 | + l2itt.add(ins); | ||
731 | + } else { | ||
732 | + log.warn("Driver does not handle this type of TrafficTreatment" | ||
733 | + + " instruction in nextObjectives: {}", ins.type()); | ||
734 | + } | ||
735 | + } | ||
624 | 736 | ||
625 | - protected void processMplsTable() { | 737 | + // assemble information for ofdpa l2interface group |
626 | - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | 738 | + int l2gk = nextObj.id() | GROUP1MASK; |
627 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 739 | + final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk)); |
628 | - selector.matchEthType(Ethernet.MPLS_UNICAST); | 740 | + Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum; |
629 | - selector.matchMplsLabel(MplsLabel.mplsLabel(0xff)); | ||
630 | - selector.matchMplsBos(true); | ||
631 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
632 | - treatment.popMpls(Ethernet.TYPE_IPV4); | ||
633 | - treatment.transition(ACL_TABLE); | ||
634 | - FlowRule test = DefaultFlowRule.builder().forDevice(deviceId) | ||
635 | - .withSelector(selector.build()).withTreatment(treatment.build()) | ||
636 | - .withPriority(LOWEST_PRIORITY).fromApp(driverId).makePermanent() | ||
637 | - .forTable(25).build(); | ||
638 | - ops = ops.add(test); | ||
639 | - | ||
640 | - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
641 | - @Override | ||
642 | - public void onSuccess(FlowRuleOperations ops) { | ||
643 | - log.info("Initialized mpls table"); | ||
644 | - } | ||
645 | - | ||
646 | - @Override | ||
647 | - public void onError(FlowRuleOperations ops) { | ||
648 | - log.info("Failed to initialize mpls table"); | ||
649 | - } | ||
650 | - })); | ||
651 | - | ||
652 | - } | ||
653 | 741 | ||
654 | - protected void processPortTable() { | 742 | + // assemble information for ofdpa l3unicast group |
655 | - //XXX is table miss entry enough or do we need to do the maskable in-port 0? | 743 | + int l3gk = nextObj.id() | GROUP0MASK; |
656 | - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | 744 | + final GroupKey l3groupkey = new DefaultGroupKey(appKryo.serialize(l3gk)); |
657 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 745 | + Integer l3groupId = L3UNICASTMASK | (int) portNum; |
658 | - selector.matchInPort(PortNumber.portNumber(0)); // should be maskable? | 746 | + l3utt.group(new DefaultGroupId(l2groupId)); |
659 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | 747 | + GroupChainElem gce = new GroupChainElem(l3groupkey, l3groupId, |
660 | - treatment.transition(VLAN_TABLE); | 748 | + l3utt.build(), nextObj.appId()); |
661 | - FlowRule tmisse = DefaultFlowRule.builder() | ||
662 | - .forDevice(deviceId) | ||
663 | - .withSelector(selector.build()) | ||
664 | - .withTreatment(treatment.build()) | ||
665 | - .withPriority(LOWEST_PRIORITY) | ||
666 | - .fromApp(driverId) | ||
667 | - .makePermanent() | ||
668 | - .forTable(PORT_TABLE).build(); | ||
669 | - /*ops = ops.add(tmisse); | ||
670 | 749 | ||
671 | - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | 750 | + // create object for local and distributed storage |
672 | - @Override | 751 | + List<GroupKey> gkeys = new ArrayList<GroupKey>(); |
673 | - public void onSuccess(FlowRuleOperations ops) { | 752 | + gkeys.add(l3groupkey); // group0 in chain |
674 | - log.info("Initialized port table"); | 753 | + gkeys.add(l2groupkey); // group1 in chain |
675 | - } | 754 | + OfdpaGroupChain ofdpaGrp = new OfdpaGroupChain(gkeys, nextObj); |
676 | 755 | ||
677 | - @Override | 756 | + // store l2groupkey with the groupChainElem for the l3group that depends on it |
678 | - public void onError(FlowRuleOperations ops) { | 757 | + pendingGroups.put(l2groupkey, gce); |
679 | - log.info("Failed to initialize port table"); | ||
680 | - } | ||
681 | - }));*/ | ||
682 | 758 | ||
683 | - } | 759 | + // store l3groupkey with the ofdpaGroupChain for the nextObjective that depends on it |
760 | + pendingNextObjectives.put(l3groupkey, ofdpaGrp); | ||
684 | 761 | ||
685 | - private void processVlanTable() { | 762 | + // create group description for the ofdpa l2interfacegroup and send to groupservice |
686 | - // Table miss entry is not required as ofdpa default is to drop | 763 | + GroupBucket bucket = |
687 | - // In OF terms, the absence of a t.m.e. also implies drop | 764 | + DefaultGroupBucket.createIndirectGroupBucket(l2itt.build()); |
765 | + GroupDescription groupDescription = new DefaultGroupDescription(deviceId, | ||
766 | + GroupDescription.Type.INDIRECT, | ||
767 | + new GroupBuckets(Collections.singletonList(bucket)), | ||
768 | + l2groupkey, | ||
769 | + l2groupId, | ||
770 | + nextObj.appId()); | ||
771 | + groupService.addGroup(groupDescription); | ||
688 | } | 772 | } |
689 | 773 | ||
690 | - | 774 | + /** |
691 | - protected void processTmacTable() { | 775 | + * Processes next element of a group chain. Assumption is that if this |
692 | - //table miss entry | 776 | + * group points to another group, the latter has already been created |
693 | - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | 777 | + * and this driver has received notification for it. A second assumption is |
694 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 778 | + * that if there is another group waiting for this group then the appropriate |
695 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | 779 | + * stores already have the information to act upon the notification for the |
696 | - selector = DefaultTrafficSelector.builder(); | 780 | + * creating of this group. |
697 | - treatment = DefaultTrafficTreatment.builder(); | 781 | + * |
698 | - treatment.transition(BRIDGING_TABLE); | 782 | + * @param gce the group chain element to be processed next |
699 | - FlowRule rule = DefaultFlowRule.builder() | 783 | + */ |
700 | - .forDevice(deviceId) | 784 | + private void processGroupChain(GroupChainElem gce) { |
701 | - .withSelector(selector.build()) | 785 | + GroupBucket bucket = DefaultGroupBucket |
702 | - .withTreatment(treatment.build()) | 786 | + .createIndirectGroupBucket(gce.getBucketActions()); |
703 | - .withPriority(LOWEST_PRIORITY) | 787 | + GroupDescription groupDesc = new DefaultGroupDescription(deviceId, |
704 | - .fromApp(driverId) | 788 | + GroupDescription.Type.INDIRECT, |
705 | - .makePermanent() | 789 | + new GroupBuckets(Collections.singletonList(bucket)), |
706 | - .forTable(TMAC_TABLE).build(); | 790 | + gce.getGkey(), |
707 | - /*ops = ops.add(rule); // XXX bug in ofdpa | 791 | + gce.getGivenGroupId(), |
708 | - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | 792 | + gce.getAppId()); |
709 | - @Override | 793 | + groupService.addGroup(groupDesc); |
710 | - public void onSuccess(FlowRuleOperations ops) { | ||
711 | - log.info("Initialized tmac table"); | ||
712 | - } | ||
713 | - | ||
714 | - @Override | ||
715 | - public void onError(FlowRuleOperations ops) { | ||
716 | - log.info("Failed to initialize tmac table"); | ||
717 | - } | ||
718 | - }));*/ | ||
719 | } | 794 | } |
720 | 795 | ||
721 | - protected void processIpTable() { | ||
722 | - //table miss entry | ||
723 | - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
724 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
725 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
726 | - selector = DefaultTrafficSelector.builder(); | ||
727 | - treatment = DefaultTrafficTreatment.builder(); | ||
728 | - treatment.transition(ACL_TABLE); | ||
729 | - FlowRule rule = DefaultFlowRule.builder() | ||
730 | - .forDevice(deviceId) | ||
731 | - .withSelector(selector.build()) | ||
732 | - .withTreatment(treatment.build()) | ||
733 | - .withPriority(LOWEST_PRIORITY) | ||
734 | - .fromApp(driverId) | ||
735 | - .makePermanent() | ||
736 | - .forTable(UNICAST_ROUTING_TABLE).build(); | ||
737 | - /*ops = ops.add(rule); | ||
738 | - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
739 | - @Override | ||
740 | - public void onSuccess(FlowRuleOperations ops) { | ||
741 | - log.info("Initialized IP table"); | ||
742 | - } | ||
743 | - | ||
744 | - @Override | ||
745 | - public void onError(FlowRuleOperations ops) { | ||
746 | - log.info("Failed to initialize unicast IP table"); | ||
747 | - } | ||
748 | - }));*/ | ||
749 | - } | ||
750 | 796 | ||
751 | private class GroupChecker implements Runnable { | 797 | private class GroupChecker implements Runnable { |
752 | @Override | 798 | @Override |
... | @@ -884,4 +930,416 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -884,4 +930,416 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline |
884 | } | 930 | } |
885 | 931 | ||
886 | } | 932 | } |
933 | + | ||
934 | + ////////////////////////////////////// | ||
935 | + // Test code to be used for future | ||
936 | + // static-flow-pusher app | ||
937 | + ////////////////////////////////////// | ||
938 | + | ||
939 | + public void processStaticFlows() { | ||
940 | + //processPortTable(); | ||
941 | + processGroupTable(); | ||
942 | + processVlanTable(); | ||
943 | + processTmacTable(); | ||
944 | + processIpTable(); | ||
945 | + //processMcastTable(); | ||
946 | + //processBridgingTable(); | ||
947 | + processAclTable(); | ||
948 | + sendPackets(); | ||
949 | + processMplsTable(); | ||
950 | + } | ||
951 | + | ||
952 | + protected void processGroupTable() { | ||
953 | + TrafficTreatment.Builder act = DefaultTrafficTreatment.builder(); | ||
954 | + | ||
955 | + act.popVlan(); // to send out untagged packets | ||
956 | + act.setOutput(PortNumber.portNumber(24)); | ||
957 | + GroupBucket bucket = | ||
958 | + DefaultGroupBucket.createIndirectGroupBucket(act.build()); | ||
959 | + final GroupKey groupkey = new DefaultGroupKey(appKryo.serialize(500)); | ||
960 | + Integer groupId = 0x00c80018; //l2 interface, vlan 200, port 24 | ||
961 | + GroupDescription groupDescription = new DefaultGroupDescription(deviceId, | ||
962 | + GroupDescription.Type.INDIRECT, | ||
963 | + new GroupBuckets(Collections.singletonList(bucket)), | ||
964 | + groupkey, | ||
965 | + groupId, | ||
966 | + driverId); | ||
967 | + groupService.addGroup(groupDescription); | ||
968 | + | ||
969 | + TrafficTreatment.Builder act2 = DefaultTrafficTreatment.builder(); | ||
970 | + act2.setOutput(PortNumber.portNumber(40)); | ||
971 | + GroupBucket bucket2 = DefaultGroupBucket.createIndirectGroupBucket(act2.build()); | ||
972 | + final GroupKey groupkey2 = new DefaultGroupKey(appKryo.serialize(502)); | ||
973 | + Integer groupId2 = 0x00c50028; //l2 interface, vlan 197, port 40 | ||
974 | + GroupDescription groupDescription2 = new DefaultGroupDescription(deviceId, | ||
975 | + GroupDescription.Type.INDIRECT, | ||
976 | + new GroupBuckets(Collections.singletonList(bucket2)), | ||
977 | + groupkey2, | ||
978 | + groupId2, | ||
979 | + driverId); | ||
980 | + groupService.addGroup(groupDescription2); | ||
981 | + | ||
982 | + while (groupService.getGroup(deviceId, groupkey2) == null) { | ||
983 | + try { | ||
984 | + Thread.sleep(500); | ||
985 | + } catch (InterruptedException e) { | ||
986 | + // TODO Auto-generated catch block | ||
987 | + e.printStackTrace(); | ||
988 | + } | ||
989 | + } | ||
990 | + | ||
991 | + //Now for L3 Unicast group | ||
992 | + TrafficTreatment.Builder act3 = DefaultTrafficTreatment.builder(); | ||
993 | + act3.setEthDst(MacAddress.valueOf(0x2020)); | ||
994 | + act3.setEthSrc(MacAddress.valueOf(0x1010)); | ||
995 | + act3.setVlanId(VlanId.vlanId((short) 200)); | ||
996 | + act3.group(new DefaultGroupId(0x00c80018)); // point to L2 interface | ||
997 | + // MPLS interface group - does not work for popping single label | ||
998 | + //Integer secGroupId = MPLSINTERFACEMASK | 38; // 0x90000026 | ||
999 | + Integer groupId3 = L3UNICASTMASK | 1; // 0x20000001 | ||
1000 | + GroupBucket bucket3 = | ||
1001 | + DefaultGroupBucket.createIndirectGroupBucket(act3.build()); | ||
1002 | + final GroupKey groupkey3 = new DefaultGroupKey(appKryo.serialize(503)); | ||
1003 | + GroupDescription groupDescription3 = new DefaultGroupDescription(deviceId, | ||
1004 | + GroupDescription.Type.INDIRECT, | ||
1005 | + new GroupBuckets(Collections.singletonList(bucket3)), | ||
1006 | + groupkey3, | ||
1007 | + groupId3, | ||
1008 | + driverId); | ||
1009 | + groupService.addGroup(groupDescription3); | ||
1010 | + | ||
1011 | + //Another L3 Unicast group | ||
1012 | + TrafficTreatment.Builder act4 = DefaultTrafficTreatment.builder(); | ||
1013 | + act4.setEthDst(MacAddress.valueOf(0x3030)); | ||
1014 | + act4.setEthSrc(MacAddress.valueOf(0x1010)); | ||
1015 | + act4.setVlanId(VlanId.vlanId((short) 197)); | ||
1016 | + act4.group(new DefaultGroupId(0x00c50028)); // point to L2 interface | ||
1017 | + Integer groupId4 = L3UNICASTMASK | 2; // 0x20000002 | ||
1018 | + GroupBucket bucket4 = | ||
1019 | + DefaultGroupBucket.createIndirectGroupBucket(act4.build()); | ||
1020 | + final GroupKey groupkey4 = new DefaultGroupKey(appKryo.serialize(504)); | ||
1021 | + GroupDescription groupDescription4 = new DefaultGroupDescription(deviceId, | ||
1022 | + GroupDescription.Type.INDIRECT, | ||
1023 | + new GroupBuckets(Collections.singletonList(bucket4)), | ||
1024 | + groupkey4, | ||
1025 | + groupId4, | ||
1026 | + driverId); | ||
1027 | + groupService.addGroup(groupDescription4); | ||
1028 | + | ||
1029 | + while (groupService.getGroup(deviceId, groupkey4) == null) { | ||
1030 | + try { | ||
1031 | + Thread.sleep(500); | ||
1032 | + } catch (InterruptedException e) { | ||
1033 | + // TODO Auto-generated catch block | ||
1034 | + e.printStackTrace(); | ||
1035 | + } | ||
1036 | + } | ||
1037 | + | ||
1038 | + // L3 ecmp group | ||
1039 | + TrafficTreatment.Builder act5 = DefaultTrafficTreatment.builder(); | ||
1040 | + act5.group(new DefaultGroupId(0x20000001)); | ||
1041 | + TrafficTreatment.Builder act6 = DefaultTrafficTreatment.builder(); | ||
1042 | + act6.group(new DefaultGroupId(0x20000002)); | ||
1043 | + GroupBucket buckete1 = | ||
1044 | + DefaultGroupBucket.createSelectGroupBucket(act5.build()); | ||
1045 | + GroupBucket buckete2 = | ||
1046 | + DefaultGroupBucket.createSelectGroupBucket(act6.build()); | ||
1047 | + List<GroupBucket> bktlist = new ArrayList<GroupBucket>(); | ||
1048 | + bktlist.add(buckete1); | ||
1049 | + bktlist.add(buckete2); | ||
1050 | + final GroupKey groupkey5 = new DefaultGroupKey(appKryo.serialize(505)); | ||
1051 | + Integer groupId5 = L3ECMPMASK | 5; // 0x70000005 | ||
1052 | + GroupDescription groupDescription5 = new DefaultGroupDescription(deviceId, | ||
1053 | + GroupDescription.Type.SELECT, | ||
1054 | + new GroupBuckets(bktlist), | ||
1055 | + groupkey5, | ||
1056 | + groupId5, | ||
1057 | + driverId); | ||
1058 | + groupService.addGroup(groupDescription5); | ||
1059 | + | ||
1060 | + | ||
1061 | + } | ||
1062 | + | ||
1063 | + @SuppressWarnings("deprecation") | ||
1064 | + protected void processMplsTable() { | ||
1065 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
1066 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
1067 | + selector.matchEthType(Ethernet.MPLS_UNICAST); | ||
1068 | + selector.matchMplsLabel(MplsLabel.mplsLabel(0xff)); //255 | ||
1069 | + selector.matchMplsBos(true); | ||
1070 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
1071 | + treatment.decMplsTtl(); // nw_ttl does not work | ||
1072 | + treatment.copyTtlIn(); | ||
1073 | + treatment.popMpls(Ethernet.TYPE_IPV4); | ||
1074 | + treatment.deferred().group(new DefaultGroupId(0x20000001)); // point to L3 Unicast | ||
1075 | + //treatment.deferred().group(new DefaultGroupId(0x70000005)); // point to L3 ECMP | ||
1076 | + treatment.transition(ACL_TABLE); | ||
1077 | + FlowRule test = DefaultFlowRule.builder().forDevice(deviceId) | ||
1078 | + .withSelector(selector.build()).withTreatment(treatment.build()) | ||
1079 | + .withPriority(DEFAULT_PRIORITY).fromApp(driverId).makePermanent() | ||
1080 | + .forTable(24).build(); | ||
1081 | + ops = ops.add(test); | ||
1082 | + | ||
1083 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
1084 | + @Override | ||
1085 | + public void onSuccess(FlowRuleOperations ops) { | ||
1086 | + log.info("Initialized mpls table"); | ||
1087 | + } | ||
1088 | + | ||
1089 | + @Override | ||
1090 | + public void onError(FlowRuleOperations ops) { | ||
1091 | + log.info("Failed to initialize mpls table"); | ||
1092 | + } | ||
1093 | + })); | ||
1094 | + | ||
1095 | + } | ||
1096 | + | ||
1097 | + protected void processPortTable() { | ||
1098 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
1099 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
1100 | + selector.matchInPort(PortNumber.portNumber(0)); // should be maskable? | ||
1101 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
1102 | + treatment.transition(VLAN_TABLE); | ||
1103 | + FlowRule tmisse = DefaultFlowRule.builder() | ||
1104 | + .forDevice(deviceId) | ||
1105 | + .withSelector(selector.build()) | ||
1106 | + .withTreatment(treatment.build()) | ||
1107 | + .withPriority(LOWEST_PRIORITY) | ||
1108 | + .fromApp(driverId) | ||
1109 | + .makePermanent() | ||
1110 | + .forTable(PORT_TABLE).build(); | ||
1111 | + ops = ops.add(tmisse); | ||
1112 | + | ||
1113 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
1114 | + @Override | ||
1115 | + public void onSuccess(FlowRuleOperations ops) { | ||
1116 | + log.info("Initialized port table"); | ||
1117 | + } | ||
1118 | + | ||
1119 | + @Override | ||
1120 | + public void onError(FlowRuleOperations ops) { | ||
1121 | + log.info("Failed to initialize port table"); | ||
1122 | + } | ||
1123 | + })); | ||
1124 | + | ||
1125 | + } | ||
1126 | + | ||
1127 | + private void processVlanTable() { | ||
1128 | + // Table miss entry is not required as ofdpa default is to drop | ||
1129 | + // In OF terms, the absence of a t.m.e. also implies drop | ||
1130 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
1131 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
1132 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
1133 | + selector.matchInPort(PortNumber.portNumber(12)); | ||
1134 | + selector.matchVlanId(VlanId.vlanId((short) 100)); | ||
1135 | + treatment.transition(TMAC_TABLE); | ||
1136 | + FlowRule rule = DefaultFlowRule.builder() | ||
1137 | + .forDevice(deviceId) | ||
1138 | + .withSelector(selector.build()) | ||
1139 | + .withTreatment(treatment.build()) | ||
1140 | + .withPriority(DEFAULT_PRIORITY) | ||
1141 | + .fromApp(driverId) | ||
1142 | + .makePermanent() | ||
1143 | + .forTable(VLAN_TABLE).build(); | ||
1144 | + ops = ops.add(rule); | ||
1145 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
1146 | + @Override | ||
1147 | + public void onSuccess(FlowRuleOperations ops) { | ||
1148 | + log.info("Initialized vlan table"); | ||
1149 | + } | ||
1150 | + | ||
1151 | + @Override | ||
1152 | + public void onError(FlowRuleOperations ops) { | ||
1153 | + log.info("Failed to initialize vlan table"); | ||
1154 | + } | ||
1155 | + })); | ||
1156 | + } | ||
1157 | + | ||
1158 | + protected void processTmacTable() { | ||
1159 | + //table miss entry | ||
1160 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
1161 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
1162 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
1163 | + selector.matchInPort(PortNumber.portNumber(12)); | ||
1164 | + selector.matchVlanId(VlanId.vlanId((short) 100)); | ||
1165 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
1166 | + selector.matchEthDst(MacAddress.valueOf("00:00:00:00:00:02")); | ||
1167 | + treatment.transition(UNICAST_ROUTING_TABLE); | ||
1168 | + FlowRule rule = DefaultFlowRule.builder() | ||
1169 | + .forDevice(deviceId) | ||
1170 | + .withSelector(selector.build()) | ||
1171 | + .withTreatment(treatment.build()) | ||
1172 | + .withPriority(DEFAULT_PRIORITY) | ||
1173 | + .fromApp(driverId) | ||
1174 | + .makePermanent() | ||
1175 | + .forTable(TMAC_TABLE).build(); | ||
1176 | + ops = ops.add(rule); | ||
1177 | + | ||
1178 | + selector.matchEthType(Ethernet.MPLS_UNICAST); | ||
1179 | + treatment.transition(MPLS_TABLE_0); | ||
1180 | + FlowRule rulempls = DefaultFlowRule.builder() | ||
1181 | + .forDevice(deviceId) | ||
1182 | + .withSelector(selector.build()) | ||
1183 | + .withTreatment(treatment.build()) | ||
1184 | + .withPriority(DEFAULT_PRIORITY) | ||
1185 | + .fromApp(driverId) | ||
1186 | + .makePermanent() | ||
1187 | + .forTable(TMAC_TABLE).build(); | ||
1188 | + ops = ops.add(rulempls); | ||
1189 | + | ||
1190 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
1191 | + @Override | ||
1192 | + public void onSuccess(FlowRuleOperations ops) { | ||
1193 | + log.info("Initialized tmac table"); | ||
1194 | + } | ||
1195 | + | ||
1196 | + @Override | ||
1197 | + public void onError(FlowRuleOperations ops) { | ||
1198 | + log.info("Failed to initialize tmac table"); | ||
1199 | + } | ||
1200 | + })); | ||
1201 | + } | ||
1202 | + | ||
1203 | + protected void processIpTable() { | ||
1204 | + //table miss entry | ||
1205 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
1206 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
1207 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
1208 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
1209 | + selector.matchIPDst(IpPrefix.valueOf("2.0.0.0/16")); | ||
1210 | + treatment.deferred().group(new DefaultGroupId(0x20000001)); | ||
1211 | + treatment.transition(ACL_TABLE); | ||
1212 | + FlowRule rule = DefaultFlowRule.builder() | ||
1213 | + .forDevice(deviceId) | ||
1214 | + .withSelector(selector.build()) | ||
1215 | + .withTreatment(treatment.build()) | ||
1216 | + .withPriority(30000) | ||
1217 | + .fromApp(driverId) | ||
1218 | + .makePermanent() | ||
1219 | + .forTable(UNICAST_ROUTING_TABLE).build(); | ||
1220 | + ops = ops.add(rule); | ||
1221 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
1222 | + @Override | ||
1223 | + public void onSuccess(FlowRuleOperations ops) { | ||
1224 | + log.info("Initialized IP table"); | ||
1225 | + } | ||
1226 | + | ||
1227 | + @Override | ||
1228 | + public void onError(FlowRuleOperations ops) { | ||
1229 | + log.info("Failed to initialize unicast IP table"); | ||
1230 | + } | ||
1231 | + })); | ||
1232 | + } | ||
1233 | + | ||
1234 | + protected void processAclTable() { | ||
1235 | + //table miss entry | ||
1236 | + FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); | ||
1237 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
1238 | + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | ||
1239 | + selector.matchEthDst(MacAddress.valueOf("00:00:00:00:00:02")); | ||
1240 | + treatment.deferred().group(new DefaultGroupId(0x20000001)); | ||
1241 | + FlowRule rule = DefaultFlowRule.builder() | ||
1242 | + .forDevice(deviceId) | ||
1243 | + .withSelector(selector.build()) | ||
1244 | + .withTreatment(treatment.build()) | ||
1245 | + .withPriority(60000) | ||
1246 | + .fromApp(driverId) | ||
1247 | + .makePermanent() | ||
1248 | + .forTable(ACL_TABLE).build(); | ||
1249 | + ops = ops.add(rule); | ||
1250 | + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { | ||
1251 | + @Override | ||
1252 | + public void onSuccess(FlowRuleOperations ops) { | ||
1253 | + log.info("Initialized Acl table"); | ||
1254 | + } | ||
1255 | + | ||
1256 | + @Override | ||
1257 | + public void onError(FlowRuleOperations ops) { | ||
1258 | + log.info("Failed to initialize Acl table"); | ||
1259 | + } | ||
1260 | + })); | ||
1261 | + } | ||
1262 | + | ||
1263 | + private void sendPackets() { | ||
1264 | + Ethernet eth = new Ethernet(); | ||
1265 | + eth.setDestinationMACAddress("00:00:00:00:00:02"); | ||
1266 | + eth.setSourceMACAddress("00:00:00:11:22:33"); | ||
1267 | + eth.setVlanID((short) 100); | ||
1268 | + eth.setEtherType(Ethernet.MPLS_UNICAST); | ||
1269 | + MPLS mplsPkt = new MPLS(); | ||
1270 | + mplsPkt.setLabel(255); | ||
1271 | + mplsPkt.setTtl((byte) 5); | ||
1272 | + | ||
1273 | + IPv4 ipv4 = new IPv4(); | ||
1274 | + | ||
1275 | + ipv4.setDestinationAddress("4.0.5.6"); | ||
1276 | + ipv4.setSourceAddress("1.0.2.3"); | ||
1277 | + ipv4.setTtl((byte) 64); | ||
1278 | + ipv4.setChecksum((short) 0); | ||
1279 | + | ||
1280 | + UDP udp = new UDP(); | ||
1281 | + udp.setDestinationPort(666); | ||
1282 | + udp.setSourcePort(333); | ||
1283 | + udp.setPayload(new Data(new byte[]{(byte) 1, (byte) 2})); | ||
1284 | + udp.setChecksum((short) 0); | ||
1285 | + | ||
1286 | + ipv4.setPayload(udp); | ||
1287 | + mplsPkt.setPayload(ipv4); | ||
1288 | + eth.setPayload(mplsPkt); | ||
1289 | + | ||
1290 | + TrafficTreatment treatment = DefaultTrafficTreatment.builder() | ||
1291 | + .setOutput(PortNumber.portNumber(24)) | ||
1292 | + .build(); | ||
1293 | + OutboundPacket packet = new DefaultOutboundPacket(deviceId, | ||
1294 | + treatment, | ||
1295 | + ByteBuffer.wrap(eth.serialize())); | ||
1296 | + | ||
1297 | + | ||
1298 | + Ethernet eth2 = new Ethernet(); | ||
1299 | + eth2.setDestinationMACAddress("00:00:00:00:00:02"); | ||
1300 | + eth2.setSourceMACAddress("00:00:00:11:22:33"); | ||
1301 | + eth2.setVlanID((short) 100); | ||
1302 | + eth2.setEtherType(Ethernet.TYPE_IPV4); | ||
1303 | + | ||
1304 | + IPv4 ipv42 = new IPv4(); | ||
1305 | + ipv42.setDestinationAddress("2.0.0.2"); | ||
1306 | + ipv42.setSourceAddress("1.0.9.9"); | ||
1307 | + ipv42.setTtl((byte) 64); | ||
1308 | + ipv42.setChecksum((short) 0); | ||
1309 | + | ||
1310 | + UDP udp2 = new UDP(); | ||
1311 | + udp2.setDestinationPort(999); | ||
1312 | + udp2.setSourcePort(333); | ||
1313 | + udp2.setPayload(new Data(new byte[]{(byte) 1, (byte) 2})); | ||
1314 | + udp2.setChecksum((short) 0); | ||
1315 | + | ||
1316 | + ipv42.setPayload(udp2); | ||
1317 | + eth2.setPayload(ipv42); | ||
1318 | + | ||
1319 | + TrafficTreatment treatment2 = DefaultTrafficTreatment.builder() | ||
1320 | + .setOutput(PortNumber.portNumber(26)) | ||
1321 | + .build(); | ||
1322 | + OutboundPacket packet2 = new DefaultOutboundPacket(deviceId, | ||
1323 | + treatment2, | ||
1324 | + ByteBuffer.wrap(eth2.serialize())); | ||
1325 | + | ||
1326 | + | ||
1327 | + log.info("Emitting packets now"); | ||
1328 | + packetService.emit(packet); | ||
1329 | + packetService.emit(packet); | ||
1330 | + packetService.emit(packet2); | ||
1331 | + packetService.emit(packet); | ||
1332 | + packetService.emit(packet); | ||
1333 | + log.info("Done emitting packets"); | ||
1334 | + } | ||
1335 | + | ||
1336 | + private class InternalPacketProcessor implements PacketProcessor { | ||
1337 | + | ||
1338 | + @Override | ||
1339 | + public void process(PacketContext context) { | ||
1340 | + | ||
1341 | + | ||
1342 | + } | ||
1343 | + } | ||
1344 | + | ||
887 | } | 1345 | } | ... | ... |
... | @@ -53,6 +53,7 @@ import org.onosproject.net.flow.criteria.MplsCriterion; | ... | @@ -53,6 +53,7 @@ import org.onosproject.net.flow.criteria.MplsCriterion; |
53 | import org.onosproject.net.flow.criteria.PortCriterion; | 53 | import org.onosproject.net.flow.criteria.PortCriterion; |
54 | import org.onosproject.net.flow.criteria.VlanIdCriterion; | 54 | import org.onosproject.net.flow.criteria.VlanIdCriterion; |
55 | import org.onosproject.net.flow.instructions.Instruction; | 55 | import org.onosproject.net.flow.instructions.Instruction; |
56 | +import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; | ||
56 | import org.onosproject.net.flowobjective.FilteringObjective; | 57 | import org.onosproject.net.flowobjective.FilteringObjective; |
57 | import org.onosproject.net.flowobjective.FlowObjectiveStore; | 58 | import org.onosproject.net.flowobjective.FlowObjectiveStore; |
58 | import org.onosproject.net.flowobjective.ForwardingObjective; | 59 | import org.onosproject.net.flowobjective.ForwardingObjective; |
... | @@ -383,7 +384,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -383,7 +384,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
383 | private Collection<FlowRule> processVersatile(ForwardingObjective fwd) { | 384 | private Collection<FlowRule> processVersatile(ForwardingObjective fwd) { |
384 | log.debug("Processing versatile forwarding objective"); | 385 | log.debug("Processing versatile forwarding objective"); |
385 | TrafficSelector selector = fwd.selector(); | 386 | TrafficSelector selector = fwd.selector(); |
386 | - | 387 | + TrafficTreatment treatment = null; |
387 | EthTypeCriterion ethType = | 388 | EthTypeCriterion ethType = |
388 | (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); | 389 | (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); |
389 | if (ethType == null) { | 390 | if (ethType == null) { |
... | @@ -410,15 +411,26 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -410,15 +411,26 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
410 | return Collections.emptySet(); | 411 | return Collections.emptySet(); |
411 | } | 412 | } |
412 | treatmentBuilder.deferred().group(group.id()); | 413 | treatmentBuilder.deferred().group(group.id()); |
414 | + treatment = treatmentBuilder.build(); | ||
413 | log.debug("Adding OUTGROUP action"); | 415 | log.debug("Adding OUTGROUP action"); |
414 | } | 416 | } |
417 | + } else if (fwd.treatment() != null) { | ||
418 | + if (fwd.treatment().allInstructions().size() == 1 && | ||
419 | + fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) { | ||
420 | + OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0); | ||
421 | + if (o.port() == PortNumber.CONTROLLER) { | ||
422 | + log.warn("Punts to the controller are handled by misses in" | ||
423 | + + " the TMAC, IP and MPLS tables."); | ||
424 | + return Collections.emptySet(); | ||
425 | + } | ||
426 | + } | ||
427 | + treatment = fwd.treatment(); | ||
415 | } else { | 428 | } else { |
416 | - log.warn("VERSATILE forwarding objective need next objective ID."); | 429 | + log.warn("VERSATILE forwarding objective needs next objective ID " |
430 | + + "or treatment."); | ||
417 | return Collections.emptySet(); | 431 | return Collections.emptySet(); |
418 | } | 432 | } |
419 | 433 | ||
420 | - TrafficTreatment treatment = treatmentBuilder.build(); | ||
421 | - | ||
422 | FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() | 434 | FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() |
423 | .fromApp(fwd.appId()).withPriority(fwd.priority()) | 435 | .fromApp(fwd.appId()).withPriority(fwd.priority()) |
424 | .forDevice(deviceId).withSelector(fwd.selector()) | 436 | .forDevice(deviceId).withSelector(fwd.selector()) |
... | @@ -616,21 +628,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -616,21 +628,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
616 | ops = install ? ops.add(rule) : ops.remove(rule); | 628 | ops = install ? ops.add(rule) : ops.remove(rule); |
617 | } | 629 | } |
618 | } else if (c.type() == Criterion.Type.IPV4_DST) { | 630 | } else if (c.type() == Criterion.Type.IPV4_DST) { |
619 | - IPCriterion ip = (IPCriterion) c; | 631 | + log.debug("driver does not process IP filtering rules as it " + |
620 | - log.debug("adding rule for IP: {}", ip.ip()); | 632 | + "sends all misses in the IP table to the controller"); |
621 | - TrafficSelector.Builder selector = DefaultTrafficSelector | ||
622 | - .builder(); | ||
623 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment | ||
624 | - .builder(); | ||
625 | - selector.matchEthType(Ethernet.TYPE_IPV4); | ||
626 | - selector.matchIPDst(ip.ip()); | ||
627 | - treatment.transition(aclTableId); | ||
628 | - FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId) | ||
629 | - .withSelector(selector.build()) | ||
630 | - .withTreatment(treatment.build()) | ||
631 | - .withPriority(filt.priority()).fromApp(applicationId) | ||
632 | - .makePermanent().forTable(ipv4UnicastTableId).build(); | ||
633 | - ops = install ? ops.add(rule) : ops.remove(rule); | ||
634 | } else { | 633 | } else { |
635 | log.warn("Driver does not currently process filtering condition" | 634 | log.warn("Driver does not currently process filtering condition" |
636 | + " of type: {}", c.type()); | 635 | + " of type: {}", c.type()); |
... | @@ -762,6 +761,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour | ... | @@ -762,6 +761,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour |
762 | this.key = key; | 761 | this.key = key; |
763 | } | 762 | } |
764 | 763 | ||
764 | + @SuppressWarnings("unused") | ||
765 | public GroupKey key() { | 765 | public GroupKey key() { |
766 | return key; | 766 | return key; |
767 | } | 767 | } | ... | ... |
... | @@ -38,6 +38,9 @@ | ... | @@ -38,6 +38,9 @@ |
38 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 38 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
39 | impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> | 39 | impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> |
40 | </driver> | 40 | </driver> |
41 | + <!-- Emulation of the spring-open pipeline using a CPqD OF 1.3 software switch. | ||
42 | + ~ This driver is the default driver assigned to the CPqD switch. | ||
43 | + --> | ||
41 | <driver name="spring-open-cpqd" extends="default" | 44 | <driver name="spring-open-cpqd" extends="default" |
42 | manufacturer="Stanford University, Ericsson Research and CPqD Research" | 45 | manufacturer="Stanford University, Ericsson Research and CPqD Research" |
43 | hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*"> | 46 | hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*"> |
... | @@ -66,7 +69,7 @@ | ... | @@ -66,7 +69,7 @@ |
66 | <driver name="ofdpa" extends="default" | 69 | <driver name="ofdpa" extends="default" |
67 | manufacturer="Broadcom Corp." hwVersion="OF-DPA.*" swVersion="OF-DPA.*"> | 70 | manufacturer="Broadcom Corp." hwVersion="OF-DPA.*" swVersion="OF-DPA.*"> |
68 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 71 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
69 | - impl="org.onosproject.driver.pipeline.OFDPA1Pipeline"/> | 72 | + impl="org.onosproject.driver.pipeline.OFDPA2Pipeline"/> |
70 | </driver> | 73 | </driver> |
71 | <driver name="pmc-olt" extends="default" | 74 | <driver name="pmc-olt" extends="default" |
72 | manufacturer="Big Switch Networks" hwVersion="ivs 0.5" swVersion="ivs 0.5"> | 75 | manufacturer="Big Switch Networks" hwVersion="ivs 0.5" swVersion="ivs 0.5"> |
... | @@ -109,7 +112,7 @@ | ... | @@ -109,7 +112,7 @@ |
109 | manufacturer="ONF" | 112 | manufacturer="ONF" |
110 | hwVersion="OF1.3 Software Switch from CPqD" swVersion="for Group Chaining"> | 113 | hwVersion="OF1.3 Software Switch from CPqD" swVersion="for Group Chaining"> |
111 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 114 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" |
112 | - impl="org.onosproject.driver.pipeline.CpqdOFDPA1Pipeline"/> | 115 | + impl="org.onosproject.driver.pipeline.CpqdOFDPA2Pipeline"/> |
113 | </driver> | 116 | </driver> |
114 | <driver name="calient" extends="default" | 117 | <driver name="calient" extends="default" |
115 | manufacturer="calient inc" hwVersion="calient hardware" | 118 | manufacturer="calient inc" hwVersion="calient hardware" | ... | ... |
-
Please register or login to post a comment