blob: ff2ef9bd9730a469e853316ea14fd0773adb5afc [file] [log] [blame]
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);
}
}