luca | c0afcf9 | 2014-08-16 20:51:53 -0700 | [diff] [blame] | 1 | package net.onrc.onos.apps.defaultrules; |
| 2 | |
| 3 | import java.util.ArrayList; |
| 4 | import java.util.Collection; |
| 5 | import java.util.List; |
| 6 | import java.util.Map; |
| 7 | |
| 8 | import net.floodlightcontroller.core.IFloodlightProviderService; |
| 9 | import net.floodlightcontroller.core.IOFSwitch; |
| 10 | import net.floodlightcontroller.core.IOFSwitch.PortChangeType; |
| 11 | import net.floodlightcontroller.core.IOFSwitchListener; |
| 12 | import net.floodlightcontroller.core.module.FloodlightModuleContext; |
| 13 | import net.floodlightcontroller.core.module.FloodlightModuleException; |
| 14 | import net.floodlightcontroller.core.module.IFloodlightModule; |
| 15 | import net.floodlightcontroller.core.module.IFloodlightService; |
| 16 | import net.onrc.onos.core.flowprogrammer.IFlowPusherService; |
| 17 | import net.onrc.onos.core.util.Dpid; |
| 18 | |
| 19 | import org.projectfloodlight.openflow.protocol.OFFactory; |
| 20 | import org.projectfloodlight.openflow.protocol.OFFlowMod; |
| 21 | import org.projectfloodlight.openflow.protocol.OFMessage; |
| 22 | import org.projectfloodlight.openflow.protocol.OFPortDesc; |
| 23 | import org.projectfloodlight.openflow.protocol.action.OFAction; |
| 24 | import org.projectfloodlight.openflow.protocol.match.Match; |
| 25 | import org.projectfloodlight.openflow.protocol.match.MatchField; |
| 26 | import org.projectfloodlight.openflow.types.EthType; |
| 27 | import org.projectfloodlight.openflow.types.MacAddress; |
| 28 | import org.projectfloodlight.openflow.types.OFBufferId; |
| 29 | import org.projectfloodlight.openflow.types.OFPort; |
| 30 | import org.slf4j.Logger; |
| 31 | import org.slf4j.LoggerFactory; |
| 32 | |
| 33 | /** |
| 34 | * Pushing default flows for SDN IP. |
| 35 | * <p/> |
| 36 | * The module is a temporary solution to push default flows |
| 37 | * upon switch connection. Specifically, when a switch connects |
| 38 | * is pushed a default drop flow, a flow that allow ARP and a flow |
| 39 | * that allow LLDP. |
| 40 | * The module is not synchronized with other potential applications |
| 41 | * sending different flows. |
| 42 | * TODO: The module should talk to the Intent or MatchAction framework |
| 43 | * to synchronize its behavior with the rest of the system. |
| 44 | */ |
| 45 | public class DefaultRules implements IFloodlightModule, IOFSwitchListener { |
| 46 | |
| 47 | private IFloodlightProviderService floodlightProvider; |
| 48 | private IFlowPusherService flowPusher; |
| 49 | private static final Logger log = LoggerFactory.getLogger(DefaultRules.class); |
| 50 | private static final String APP_NAME = "DefaultRules"; |
| 51 | |
| 52 | private static final short IDLE_TIMEOUT = 0; |
| 53 | private static final short HARD_TIMEOUT = 0; |
| 54 | private static final short DROP_RULE_PRIORITY = 1; |
| 55 | private static final short DEFAULT_RULE_PRIORITY = 2; |
| 56 | private static final MacAddress LLDP_MAC_ADDRESS = |
| 57 | MacAddress.of("01:80:c2:00:00:0e"); |
| 58 | |
| 59 | @Override |
| 60 | public String getName() { |
| 61 | return DefaultRules.APP_NAME; |
| 62 | } |
| 63 | |
| 64 | @Override |
| 65 | public void switchActivatedMaster(long swId) { |
| 66 | // Install default drop rule sending a FlowMod |
| 67 | this.writeDefaultDrop(swId); |
| 68 | // Permit standard LLDP and ARP |
| 69 | this.permitStdLLDP(swId); |
| 70 | this.permitARP(swId); |
| 71 | } |
| 72 | |
| 73 | /** |
| 74 | * Installs a default FlowMod on the switch to DROP by default all packet-ins. |
| 75 | * |
| 76 | * @param swId The switch ID |
| 77 | */ |
| 78 | private void writeDefaultDrop(long swId) { |
| 79 | IOFSwitch sw = floodlightProvider.getMasterSwitch(swId); |
| 80 | OFFactory factory = sw.getFactory(); |
| 81 | OFFlowMod.Builder builder = factory.buildFlowAdd(); |
| 82 | Match match = factory.buildMatch().build(); |
| 83 | List<OFAction> actionList = new ArrayList<OFAction>(); |
| 84 | builder.setMatch(match) |
| 85 | .setActions(actionList) |
| 86 | .setIdleTimeout(IDLE_TIMEOUT) |
| 87 | .setHardTimeout(HARD_TIMEOUT) |
| 88 | .setBufferId(OFBufferId.NO_BUFFER) |
| 89 | .setPriority(DROP_RULE_PRIORITY); |
| 90 | OFMessage ofMessage = builder.build(); |
| 91 | log.debug("Sending 'default drop' OF messsage to switch {}.", swId); |
| 92 | flowPusher.add(new Dpid(swId), ofMessage); |
| 93 | } |
| 94 | |
| 95 | /** |
| 96 | * Installs a default FlowMod on the switch to allow LLDP traffic. |
| 97 | * LLDP flows have an higher priority than the DROP ones. |
| 98 | * |
| 99 | * @param swId The switch ID |
| 100 | */ |
| 101 | private void permitStdLLDP(long swId) { |
| 102 | IOFSwitch sw = floodlightProvider.getMasterSwitch(swId); |
| 103 | OFFactory factory = sw.getFactory(); |
| 104 | OFFlowMod.Builder builder = factory.buildFlowAdd(); |
| 105 | Match match = factory.buildMatch() |
| 106 | .setExact(MatchField.ETH_TYPE, EthType.LLDP) |
| 107 | .setExact(MatchField.ETH_DST, LLDP_MAC_ADDRESS) |
| 108 | .build(); |
| 109 | List<OFAction> actionList = new ArrayList<OFAction>(); |
| 110 | OFAction action = factory.actions().output(OFPort.CONTROLLER, Short.MAX_VALUE); |
| 111 | actionList.add(action); |
| 112 | builder.setMatch(match) |
| 113 | .setActions(actionList) |
| 114 | .setIdleTimeout(IDLE_TIMEOUT) |
| 115 | .setHardTimeout(HARD_TIMEOUT) |
| 116 | .setBufferId(OFBufferId.NO_BUFFER) |
| 117 | .setPriority(DEFAULT_RULE_PRIORITY); |
| 118 | OFMessage ofMessage = builder.build(); |
| 119 | log.debug("Sending 'LLDP permit' OF message to switch {}.", swId); |
| 120 | flowPusher.add(new Dpid(swId), ofMessage); |
| 121 | } |
| 122 | |
| 123 | /** |
| 124 | * The method installs a default FlowMod on the switch to allow ARP traffic. |
| 125 | * ARP flows have an higher priority than the DROP ones |
| 126 | * |
| 127 | * @param swId The switch ID |
| 128 | */ |
| 129 | private void permitARP(long swId) { |
| 130 | IOFSwitch sw = floodlightProvider.getMasterSwitch(swId); |
| 131 | OFFactory factory = sw.getFactory(); |
| 132 | OFFlowMod.Builder builder = factory.buildFlowAdd(); |
| 133 | Match match = factory.buildMatch() |
| 134 | .setExact(MatchField.ETH_TYPE, EthType.ARP) |
| 135 | .build(); |
| 136 | List<OFAction> actionList = new ArrayList<OFAction>(); |
| 137 | OFAction action = factory.actions().output(OFPort.CONTROLLER, Short.MAX_VALUE); |
| 138 | actionList.add(action); |
| 139 | builder.setMatch(match) |
| 140 | .setActions(actionList) |
| 141 | .setIdleTimeout(IDLE_TIMEOUT) |
| 142 | .setHardTimeout(HARD_TIMEOUT) |
| 143 | .setBufferId(OFBufferId.NO_BUFFER) |
| 144 | .setPriority(DEFAULT_RULE_PRIORITY); |
| 145 | OFMessage ofMessage = builder.build(); |
| 146 | log.debug("Sending 'ARP permit' OF message to the switch {}.", swId); |
| 147 | flowPusher.add(new Dpid(swId), ofMessage); |
| 148 | } |
| 149 | |
| 150 | @Override |
| 151 | public void switchActivatedEqual(long swId) { |
| 152 | } |
| 153 | |
| 154 | @Override |
| 155 | public void switchMasterToEqual(long swId) { |
| 156 | } |
| 157 | |
| 158 | @Override |
| 159 | public void switchEqualToMaster(long swId) { |
| 160 | } |
| 161 | |
| 162 | @Override |
| 163 | public void switchDisconnected(long swId) { |
| 164 | } |
| 165 | |
| 166 | @Override |
| 167 | public void switchPortChanged(long swId, OFPortDesc port, PortChangeType changeType) { |
| 168 | } |
| 169 | |
| 170 | @Override |
| 171 | public Collection<Class<? extends IFloodlightService>> getModuleServices() { |
| 172 | return null; |
| 173 | } |
| 174 | |
| 175 | @Override |
| 176 | public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { |
| 177 | return null; |
| 178 | } |
| 179 | |
| 180 | @Override |
| 181 | public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { |
| 182 | List<Class<? extends IFloodlightService>> dependencies = |
| 183 | new ArrayList<Class<? extends IFloodlightService>>(); |
| 184 | dependencies.add(IFloodlightProviderService.class); |
| 185 | dependencies.add(IFlowPusherService.class); |
| 186 | return dependencies; |
| 187 | } |
| 188 | |
| 189 | @Override |
| 190 | public void init(FloodlightModuleContext context) throws FloodlightModuleException { |
| 191 | this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); |
| 192 | this.flowPusher = context.getServiceImpl(IFlowPusherService.class); |
| 193 | } |
| 194 | |
| 195 | @Override |
| 196 | public void startUp(FloodlightModuleContext context) throws FloodlightModuleException { |
| 197 | floodlightProvider.addOFSwitchListener(this); |
| 198 | } |
| 199 | } |