Reactive forwarding apps should explicitly ask for packets they want to receive.
Previously we relied on the table-miss entry set up for OVS switches, but
this doesn't work for non-OVS switches 1.3 switches.
Fixes ONOS-661.
Change-Id: Ibc0aee09f304eaf240691a4d5d2f8765a5f8cdd5
diff --git a/apps/fwd/src/main/java/org/onosproject/fwd/ReactiveForwarding.java b/apps/fwd/src/main/java/org/onosproject/fwd/ReactiveForwarding.java
index 06febb1..0d0dda9 100644
--- a/apps/fwd/src/main/java/org/onosproject/fwd/ReactiveForwarding.java
+++ b/apps/fwd/src/main/java/org/onosproject/fwd/ReactiveForwarding.java
@@ -30,10 +30,14 @@
import org.onlab.packet.Ethernet;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.net.Device;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -58,6 +62,7 @@
private static final int TIMEOUT = 10;
private static final int PRIORITY = 10;
+ private static final int PUNT_RULE_PRIORITY = 5;
private final Logger log = getLogger(getClass());
@@ -74,6 +79,9 @@
protected FlowRuleService flowRuleService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
private ReactivePacketProcessor processor = new ReactivePacketProcessor();
@@ -91,6 +99,8 @@
@Activate
public void activate(ComponentContext context) {
appId = coreService.registerApplication("org.onosproject.fwd");
+ deviceService.addListener(new InternalDeviceListener());
+ pushRules();
packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
readComponentConfiguration(context);
log.info("Started with Application ID {}", appId.id());
@@ -293,6 +303,58 @@
}
}
+ /**
+ * Pushes flow rules to all devices.
+ */
+ private void pushRules() {
+ for (Device device : deviceService.getDevices()) {
+ pushRules(device);
+ }
+ }
+
+ /**
+ * Pushes flow rules to the device to receive packets that need
+ * to be processed.
+ *
+ * @param device the device to push the rules to
+ */
+ private synchronized void pushRules(Device device) {
+ TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
+
+ // Get all IPv4 packets
+ sbuilder.matchEthType(Ethernet.TYPE_IPV4);
+ tbuilder.punt();
+ FlowRule flowArp =
+ new DefaultFlowRule(device.id(),
+ sbuilder.build(), tbuilder.build(),
+ PUNT_RULE_PRIORITY, appId, 0, true);
+
+ flowRuleService.applyFlowRules(flowArp);
+ }
+
+ public class InternalDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ switch (event.type()) {
+ case DEVICE_ADDED:
+ pushRules(device);
+ break;
+ case DEVICE_AVAILABILITY_CHANGED:
+ case DEVICE_SUSPENDED:
+ case DEVICE_UPDATED:
+ case DEVICE_REMOVED:
+ case PORT_ADDED:
+ case PORT_UPDATED:
+ case PORT_REMOVED:
+ default:
+ break;
+ }
+ }
+ }
+
}
diff --git a/apps/ifwd/src/main/java/org/onosproject/ifwd/IntentReactiveForwarding.java b/apps/ifwd/src/main/java/org/onosproject/ifwd/IntentReactiveForwarding.java
index 5450bb4..9dd657e 100644
--- a/apps/ifwd/src/main/java/org/onosproject/ifwd/IntentReactiveForwarding.java
+++ b/apps/ifwd/src/main/java/org/onosproject/ifwd/IntentReactiveForwarding.java
@@ -25,11 +25,18 @@
import org.onlab.packet.Ethernet;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.net.Device;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
@@ -52,6 +59,8 @@
private final Logger log = getLogger(getClass());
+ private static final int PUNT_RULE_PRIORITY = 5;
+
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@@ -67,12 +76,20 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowRuleService flowRuleService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
private ReactivePacketProcessor processor = new ReactivePacketProcessor();
private ApplicationId appId;
@Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.ifwd");
+ deviceService.addListener(new InternalDeviceListener());
+ pushRules();
packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
log.info("Started");
}
@@ -155,4 +172,56 @@
intentService.submit(intent);
}
+ /**
+ * Pushes flow rules to all devices.
+ */
+ private void pushRules() {
+ for (Device device : deviceService.getDevices()) {
+ pushRules(device);
+ }
+ }
+
+ /**
+ * Pushes flow rules to the device to receive packets that need
+ * to be processed.
+ *
+ * @param device the device to push the rules to
+ */
+ private synchronized void pushRules(Device device) {
+ TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
+
+ // Get all IPv4 packets
+ sbuilder.matchEthType(Ethernet.TYPE_IPV4);
+ tbuilder.punt();
+ FlowRule flowArp =
+ new DefaultFlowRule(device.id(),
+ sbuilder.build(), tbuilder.build(),
+ PUNT_RULE_PRIORITY, appId, 0, true);
+
+ flowRuleService.applyFlowRules(flowArp);
+ }
+
+ public class InternalDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ switch (event.type()) {
+ case DEVICE_ADDED:
+ pushRules(device);
+ break;
+ case DEVICE_AVAILABILITY_CHANGED:
+ case DEVICE_SUSPENDED:
+ case DEVICE_UPDATED:
+ case DEVICE_REMOVED:
+ case PORT_ADDED:
+ case PORT_UPDATED:
+ case PORT_REMOVED:
+ default:
+ break;
+ }
+ }
+ }
+
}