| 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); |
| } |
| } |