New module DefaultRules. It installs default rules on switches when they connect.

Change-Id: Ife95d28dac90c96b87b4da8a765a1d632a5cf178
diff --git a/src/main/java/net/onrc/onos/apps/defaultrules/DefaultRules.java b/src/main/java/net/onrc/onos/apps/defaultrules/DefaultRules.java
new file mode 100644
index 0000000..ff2ef9b
--- /dev/null
+++ b/src/main/java/net/onrc/onos/apps/defaultrules/DefaultRules.java
@@ -0,0 +1,199 @@
+package net.onrc.onos.apps.defaultrules;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.IOFSwitch.PortChangeType;
+import net.floodlightcontroller.core.IOFSwitchListener;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
+import net.onrc.onos.core.util.Dpid;
+
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFBufferId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Pushing default flows for SDN IP.
+ * <p/>
+ * The module is a temporary solution to push default flows
+ * upon switch connection. Specifically, when a switch connects
+ * is pushed a default drop flow, a flow that allow ARP and a flow
+ * that allow LLDP.
+ * The module is not synchronized with other potential applications
+ * sending different flows.
+ * TODO: The module should talk to the Intent or MatchAction framework
+ * to synchronize its behavior with the rest of the system.
+ */
+public class DefaultRules implements IFloodlightModule, IOFSwitchListener {
+
+    private IFloodlightProviderService floodlightProvider;
+    private IFlowPusherService flowPusher;
+    private static final Logger log = LoggerFactory.getLogger(DefaultRules.class);
+    private static final String APP_NAME = "DefaultRules";
+
+    private static final short IDLE_TIMEOUT = 0;
+    private static final short HARD_TIMEOUT = 0;
+    private static final short DROP_RULE_PRIORITY = 1;
+    private static final short DEFAULT_RULE_PRIORITY = 2;
+    private static final MacAddress LLDP_MAC_ADDRESS =
+            MacAddress.of("01:80:c2:00:00:0e");
+
+    @Override
+    public String getName() {
+        return DefaultRules.APP_NAME;
+    }
+
+    @Override
+    public void switchActivatedMaster(long swId) {
+         // Install default drop rule sending a FlowMod
+        this.writeDefaultDrop(swId);
+         // Permit standard LLDP and ARP
+        this.permitStdLLDP(swId);
+        this.permitARP(swId);
+    }
+
+    /**
+     * Installs a default FlowMod on the switch to DROP by default all packet-ins.
+     *
+     * @param swId The switch ID
+     */
+    private void writeDefaultDrop(long swId) {
+        IOFSwitch sw = floodlightProvider.getMasterSwitch(swId);
+        OFFactory factory = sw.getFactory();
+        OFFlowMod.Builder builder = factory.buildFlowAdd();
+        Match match = factory.buildMatch().build();
+        List<OFAction> actionList = new ArrayList<OFAction>();
+        builder.setMatch(match)
+            .setActions(actionList)
+            .setIdleTimeout(IDLE_TIMEOUT)
+            .setHardTimeout(HARD_TIMEOUT)
+            .setBufferId(OFBufferId.NO_BUFFER)
+            .setPriority(DROP_RULE_PRIORITY);
+        OFMessage ofMessage = builder.build();
+        log.debug("Sending 'default drop' OF messsage to switch {}.", swId);
+        flowPusher.add(new Dpid(swId), ofMessage);
+    }
+
+    /**
+     * Installs a default FlowMod on the switch to allow LLDP traffic.
+     * LLDP flows have an higher priority than the DROP ones.
+     *
+     * @param swId The switch ID
+     */
+    private void permitStdLLDP(long swId) {
+        IOFSwitch sw = floodlightProvider.getMasterSwitch(swId);
+        OFFactory factory = sw.getFactory();
+        OFFlowMod.Builder builder = factory.buildFlowAdd();
+        Match match = factory.buildMatch()
+                .setExact(MatchField.ETH_TYPE, EthType.LLDP)
+                .setExact(MatchField.ETH_DST, LLDP_MAC_ADDRESS)
+                .build();
+        List<OFAction> actionList = new ArrayList<OFAction>();
+        OFAction action = factory.actions().output(OFPort.CONTROLLER, Short.MAX_VALUE);
+        actionList.add(action);
+        builder.setMatch(match)
+            .setActions(actionList)
+            .setIdleTimeout(IDLE_TIMEOUT)
+            .setHardTimeout(HARD_TIMEOUT)
+            .setBufferId(OFBufferId.NO_BUFFER)
+            .setPriority(DEFAULT_RULE_PRIORITY);
+        OFMessage ofMessage = builder.build();
+        log.debug("Sending 'LLDP permit' OF message to switch {}.", swId);
+        flowPusher.add(new Dpid(swId), ofMessage);
+    }
+
+    /**
+     * The method installs a default FlowMod on the switch to allow ARP traffic.
+     * ARP flows have an higher priority than the DROP ones
+     *
+     * @param swId The switch ID
+     */
+    private void permitARP(long swId) {
+        IOFSwitch sw = floodlightProvider.getMasterSwitch(swId);
+        OFFactory factory = sw.getFactory();
+        OFFlowMod.Builder builder = factory.buildFlowAdd();
+        Match match = factory.buildMatch()
+                .setExact(MatchField.ETH_TYPE, EthType.ARP)
+                .build();
+        List<OFAction> actionList = new ArrayList<OFAction>();
+        OFAction action = factory.actions().output(OFPort.CONTROLLER, Short.MAX_VALUE);
+        actionList.add(action);
+        builder.setMatch(match)
+            .setActions(actionList)
+            .setIdleTimeout(IDLE_TIMEOUT)
+            .setHardTimeout(HARD_TIMEOUT)
+            .setBufferId(OFBufferId.NO_BUFFER)
+            .setPriority(DEFAULT_RULE_PRIORITY);
+        OFMessage ofMessage = builder.build();
+        log.debug("Sending 'ARP permit' OF message to the switch {}.", swId);
+        flowPusher.add(new Dpid(swId), ofMessage);
+    }
+
+    @Override
+    public void switchActivatedEqual(long swId) {
+    }
+
+    @Override
+    public void switchMasterToEqual(long swId) {
+    }
+
+    @Override
+    public void switchEqualToMaster(long swId) {
+    }
+
+    @Override
+    public void switchDisconnected(long swId) {
+    }
+
+    @Override
+    public void switchPortChanged(long swId, OFPortDesc port, PortChangeType changeType) {
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+        return null;
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+        return null;
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+        List<Class<? extends IFloodlightService>> dependencies =
+                new ArrayList<Class<? extends IFloodlightService>>();
+        dependencies.add(IFloodlightProviderService.class);
+        dependencies.add(IFlowPusherService.class);
+        return dependencies;
+    }
+
+    @Override
+    public void init(FloodlightModuleContext context) throws FloodlightModuleException {
+        this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+        this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
+    }
+
+    @Override
+    public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
+        floodlightProvider.addOFSwitchListener(this);
+    }
+}