Saurav Das
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
...@@ -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"
......