Moved default flows logic into the PacketManager.
This prevents us duplicating code in each of the apps and allows us to manage
packet requests better in the future.
Change-Id: I5656b2f0f3cecd3e42fe7b4a0a5ab7cb6582bb25
diff --git a/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java b/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
index a8195e4..94c75dd 100644
--- a/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
+++ b/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
@@ -18,7 +18,9 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
+import java.util.Collections;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.felix.scr.annotations.Activate;
@@ -27,11 +29,21 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
+import org.onosproject.core.ApplicationId;
import org.onosproject.net.Device;
+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.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.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketEvent;
+import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketProvider;
import org.onosproject.net.packet.PacketProviderRegistry;
@@ -60,19 +72,55 @@
private DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private FlowRuleService flowService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private PacketStore store;
+ private final DeviceListener deviceListener = new InternalDeviceListener();
+
private final Map<Integer, PacketProcessor> processors = new ConcurrentHashMap<>();
+ private Set<PacketRequest> packetRequests =
+ Collections.newSetFromMap(new ConcurrentHashMap<>());
+
+ private final class PacketRequest {
+ private final TrafficSelector selector;
+ private final PacketPriority priority;
+ private final ApplicationId appId;
+
+ public PacketRequest(TrafficSelector selector, PacketPriority priority,
+ ApplicationId appId) {
+ this.selector = selector;
+ this.priority = priority;
+ this.appId = appId;
+ }
+
+ public TrafficSelector selector() {
+ return selector;
+ }
+
+ public PacketPriority priority() {
+ return priority;
+ }
+
+ public ApplicationId appId() {
+ return appId;
+ }
+
+ }
+
@Activate
public void activate() {
store.setDelegate(delegate);
+ deviceService.addListener(deviceListener);
log.info("Started");
}
@Deactivate
public void deactivate() {
store.unsetDelegate(delegate);
+ deviceService.removeListener(deviceListener);
log.info("Stopped");
}
@@ -89,6 +137,52 @@
}
@Override
+ public void requestPackets(TrafficSelector selector, PacketPriority priority,
+ ApplicationId appId) {
+ checkNotNull(selector, "Selector cannot be null");
+ checkNotNull(appId, "Application ID cannot be null");
+
+ PacketRequest request =
+ new PacketRequest(selector, priority, appId);
+
+ packetRequests.add(request);
+ pushToAllDevices(request);
+ }
+
+ /**
+ * Pushes a packet request flow rule to all devices.
+ *
+ * @param request the packet request
+ */
+ private void pushToAllDevices(PacketRequest request) {
+ for (Device device : deviceService.getDevices()) {
+ pushRule(device, request);
+ }
+ }
+
+ /**
+ * Pushes flow rules to the device to request packets be sent to the
+ * controller.
+ *
+ * @param device the device to push the rules to
+ * @param request the packet request
+ */
+ private void pushRule(Device device, PacketRequest request) {
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .punt()
+ .build();
+
+ FlowRule flow = new DefaultFlowRule(device.id(),
+ request.selector(),
+ treatment,
+ request.priority().priorityValue(),
+ request.appId(),
+ 0, true);
+
+ flowService.applyFlowRules(flow);
+ }
+
+ @Override
public void emit(OutboundPacket packet) {
checkNotNull(packet, "Packet cannot be null");
@@ -125,6 +219,7 @@
@Override
public void processPacket(PacketContext context) {
+ // TODO filter packets sent to processors based on registrations
for (PacketProcessor processor : processors.values()) {
processor.process(context);
}
@@ -143,4 +238,19 @@
}
}
+ /**
+ * Internal listener for device service events.
+ */
+ private class InternalDeviceListener implements DeviceListener {
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ if (event.type() == DeviceEvent.Type.DEVICE_ADDED) {
+ for (PacketRequest request : packetRequests) {
+ pushRule(device, request);
+ }
+ }
+ }
+ }
+
}