Advertisement
Guest User

Untitled

a guest
Dec 6th, 2018
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.85 KB | None | 0 0
  1. package net.floodlightcontroller.cgrmodule;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Collection;
  5. import java.util.Collections;
  6. import java.util.HashMap;
  7. import java.util.HashSet;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Set;
  11. import java.util.concurrent.ConcurrentHashMap;
  12.  
  13. import org.projectfloodlight.openflow.protocol.OFFlowMod;
  14. import org.projectfloodlight.openflow.protocol.OFFlowModCommand;
  15. import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
  16. import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
  17. import org.projectfloodlight.openflow.protocol.OFMessage;
  18. import org.projectfloodlight.openflow.protocol.OFPacketIn;
  19. import org.projectfloodlight.openflow.protocol.OFPacketOut;
  20. import org.projectfloodlight.openflow.protocol.OFType;
  21. import org.projectfloodlight.openflow.protocol.OFVersion;
  22. import org.projectfloodlight.openflow.protocol.action.OFAction;
  23. import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
  24. import org.projectfloodlight.openflow.protocol.action.OFActions;
  25. import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
  26. import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
  27. import org.projectfloodlight.openflow.protocol.instruction.OFInstructions;
  28. import org.projectfloodlight.openflow.protocol.match.Match;
  29. import org.projectfloodlight.openflow.protocol.match.MatchField;
  30. import org.projectfloodlight.openflow.types.MacAddress;
  31. import org.projectfloodlight.openflow.types.OFBufferId;
  32. import org.projectfloodlight.openflow.types.OFPort;
  33. import org.projectfloodlight.openflow.types.OFVlanVidMatch;
  34. import org.projectfloodlight.openflow.types.TableId;
  35. import org.projectfloodlight.openflow.types.U64;
  36. import org.projectfloodlight.openflow.types.VlanVid;
  37. import org.projectfloodlight.openflow.util.LRULinkedHashMap;
  38. import org.slf4j.Logger;
  39. import org.slf4j.LoggerFactory;
  40.  
  41. import net.floodlightcontroller.cgrmodule.util.*;
  42. import net.floodlightcontroller.core.FloodlightContext;
  43. import net.floodlightcontroller.core.IControllerCompletionListener;
  44. import net.floodlightcontroller.core.IFloodlightProviderService;
  45. import net.floodlightcontroller.core.IOFMessageListener;
  46. import net.floodlightcontroller.core.IOFSwitch;
  47. import net.floodlightcontroller.core.module.FloodlightModuleContext;
  48. import net.floodlightcontroller.core.module.FloodlightModuleException;
  49. import net.floodlightcontroller.core.module.IFloodlightModule;
  50. import net.floodlightcontroller.core.module.IFloodlightService;
  51. import net.floodlightcontroller.learningswitch.LearningSwitch;
  52. import net.floodlightcontroller.packet.Ethernet;
  53. import net.floodlightcontroller.util.OFMessageUtils;
  54.  
  55. public class CGRmodule implements IFloodlightModule, IOFMessageListener {
  56. protected static Logger log = LoggerFactory.getLogger(CGRmodule.class);
  57.  
  58. // Module dependencies
  59. protected IFloodlightProviderService floodlightProviderService;
  60.  
  61. // Stores the learned state for each switch
  62. protected Map<IOFSwitch, Map<MacAddress, OFPort>> macToSwitchPortMap;
  63.  
  64. // flow-mod - for use in the cookie
  65. public static final int LEARNING_SWITCH_APP_ID = 1;
  66. // LOOK! This should probably go in some class that encapsulates
  67. // the app cookie management
  68. public static final int APP_ID_BITS = 12;
  69. public static final int APP_ID_SHIFT = (64 - APP_ID_BITS);
  70. public static final long LEARNING_SWITCH_COOKIE = (long) (LEARNING_SWITCH_APP_ID & ((1 << APP_ID_BITS) - 1)) << APP_ID_SHIFT;
  71.  
  72. // more flow-mod defaults
  73. protected static short FLOWMOD_DEFAULT_IDLE_TIMEOUT = 5; // in seconds
  74. protected static short FLOWMOD_DEFAULT_HARD_TIMEOUT = 0; // infinite
  75. protected static short FLOWMOD_PRIORITY = 100;
  76.  
  77. // for managing our map sizes
  78. protected static final int MAX_MACS_PER_SWITCH = 1000;
  79.  
  80. // normally, setup reverse flow as well. Disable only for using cbench for comparison with NOX etc.
  81. protected static final boolean LEARNING_SWITCH_REVERSE_FLOW = true;
  82.  
  83. /**
  84. * @param floodlightProvider the floodlightProvider to set
  85. */
  86. public void setFloodlightProvider(IFloodlightProviderService floodlightProviderService) {
  87. this.floodlightProviderService = floodlightProviderService;
  88. }
  89.  
  90. @Override
  91. public String getName() {
  92. return "CGRModule";
  93. }
  94.  
  95. /**
  96. * Adds a host to the MAC->SwitchPort mapping
  97. * @param sw The switch to add the mapping to
  98. * @param mac The MAC address of the host to add
  99. * @param portVal The switchport that the host is on
  100. */
  101. protected void addToPortMap(IOFSwitch sw, MacAddress mac, OFPort portVal) {
  102. Map<MacAddress, OFPort> swMap = macToSwitchPortMap.get(sw);
  103.  
  104. if (swMap == null) {
  105. swMap = new LRULinkedHashMap<MacAddress, OFPort>(MAX_MACS_PER_SWITCH);
  106. macToSwitchPortMap.put(sw, swMap);
  107. }
  108. swMap.put(mac, portVal);
  109. }
  110.  
  111. /**
  112. * Removes a host from the MAC->SwitchPort mapping
  113. * @param sw The switch to remove the mapping from
  114. * @param mac The MAC address of the host to remove
  115. */
  116. protected void removeFromPortMap(IOFSwitch sw, MacAddress mac) {
  117.  
  118. Map<MacAddress, OFPort> swMap = macToSwitchPortMap.get(sw);
  119. if (swMap != null) {
  120. swMap.remove(mac);
  121. }
  122. }
  123.  
  124. /**
  125. * Get the port that a MAC is associated with
  126. * @param sw The switch to get the mapping from
  127. * @param mac The MAC address to get
  128. * @return The port the host is on
  129. */
  130. public OFPort getFromPortMap(IOFSwitch sw, MacAddress mac) {
  131. Map<MacAddress, OFPort> swMap = macToSwitchPortMap.get(sw);
  132. if (swMap != null) {
  133. return swMap.get(mac);
  134. }
  135.  
  136. // if none found
  137. return null;
  138. }
  139.  
  140. /**
  141. * Clears the MAC -> SwitchPort map for all switches
  142. */
  143. public void clearLearnedTable() {
  144. macToSwitchPortMap.clear();
  145. }
  146.  
  147. /**
  148. * Clears the MAC/VLAN -> SwitchPort map for a single switch
  149. * @param sw The switch to clear the mapping for
  150. */
  151. public void clearLearnedTable(IOFSwitch sw) {
  152. Map<MacAddress, OFPort> swMap = macToSwitchPortMap.get(sw);
  153. if (swMap != null) {
  154. swMap.clear();
  155. }
  156. }
  157.  
  158. protected Match createMatchFromPacket(IOFSwitch sw, OFPort inPort, FloodlightContext cntx) {
  159. // The packet in match will only contain the port number.
  160. // We need to add in specifics for the hosts we're routing between.
  161. Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
  162. MacAddress srcMac = eth.getSourceMACAddress();
  163. MacAddress dstMac = eth.getDestinationMACAddress();
  164.  
  165. Match.Builder mb = sw.getOFFactory().buildMatch();
  166. mb.setExact(MatchField.IN_PORT, inPort)
  167. .setExact(MatchField.ETH_SRC, srcMac)
  168. .setExact(MatchField.ETH_DST, dstMac);
  169. return mb.build();
  170. }
  171.  
  172. /**
  173. * Processes a OFPacketIn message. If the switch has learned the MAC to port mapping
  174. * for the pair it will write a FlowMod for. If the mapping has not been learned the
  175. * we will flood the packet.
  176. * @param sw
  177. * @param pi
  178. * @param cntx
  179. * @return
  180. */
  181. private Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
  182. OFPort inPort = (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT));
  183.  
  184. /* Read packet header attributes into a Match object */
  185. Match m = createMatchFromPacket(sw, inPort, cntx);
  186. MacAddress sourceMac = m.get(MatchField.ETH_SRC);
  187. MacAddress destMac = m.get(MatchField.ETH_DST);
  188.  
  189. if (sourceMac == null) {
  190. sourceMac = MacAddress.NONE;
  191. }
  192. if (destMac == null) {
  193. destMac = MacAddress.NONE;
  194. }
  195.  
  196. if ((destMac.getLong() & 0xfffffffffff0L) == 0x0180c2000000L) {
  197. if (log.isTraceEnabled()) {
  198. log.trace("ignoring packet addressed to 802.1D/Q reserved addr: switch {} dest MAC {}",
  199. new Object[]{ sw, destMac.toString() });
  200. }
  201. return Command.STOP;
  202. }
  203. if ((sourceMac.getLong() & 0x010000000000L) == 0) {
  204. // If source MAC is a unicast address, learn the port for this MAC/VLAN
  205.  
  206. }
  207. //check if port for destination MAC is known
  208. // If so output flow-mod and/or packet
  209.  
  210. //for now it floods trough all ports like a hub.
  211. SwitchCommands.sendPacketOutPacketIn(sw, OFPort.FLOOD, pi);
  212. // Add flow table entry matching source MAC, dest MAC and input port
  213. // that sends to the port we previously learned for the dest MAC. Also
  214. // add a flow table entry with source and destination MACs reversed, and
  215. // input and output ports reversed. When either entry expires due to idle
  216. // timeout, remove the other one. This ensures that if a device moves to
  217. // a different port, a constant stream of packets headed to the device at
  218. // its former location does not keep the stale entry alive forever.
  219. // We write FlowMods with Buffer ID none then explicitly PacketOut the buffered packet
  220.  
  221. // to send the packet in back as a packet out to the previously learned port outPort use;
  222. //SwitchCommands.sendPacketOutPacketIn(outSw, outPort, pi)
  223.  
  224. // you should then write the flow mod using SwitchCommands install rule method since it receives either instructions or actions
  225. // depending on the OpenFlow Version you should do the following:
  226. /*
  227. OFActions actions = sw.getOFFactory().actions(); //actions builder
  228. List<OFAction> al = new ArrayList<OFAction>();
  229. OFActionOutput output = actions.buildOutput()
  230. .setPort(outPort) // outPort is the port trough which the sw should send the Matching Packets
  231. .setMaxLen(0xffFFffFF)
  232. .build();
  233. al.add(output);
  234.  
  235. if (pi.getVersion().compareTo(OFVersion.OF_13)==0){
  236. OFInstructions instructions = sw.getOFFactory().instructions(); //instructions builder
  237. OFInstructionApplyActions applyActions = instructions.buildApplyActions().setActions(al).build(); //use the instructions builder to build an applyActions instruction with the given action list.
  238. ArrayList<OFInstruction> instructionList = new ArrayList<OFInstruction>();
  239. instructionList.add(applyActions); //add the applyActions Instruction to the Instruction list
  240. SwitchCommands.installRule(sw, TableId.of(0), CGRL2Switch.FLOWMOD_PRIORITY, match, instructionList, null, CGRL2Switch.FLOWMOD_DEFAULT_HARD_TIMEOUT, CGRL2Switch.FLOWMOD_DEFAULT_IDLE_TIMEOUT, OFBufferId.NO_BUFFER);
  241. } else SwitchCommands.installRule(sw, TableId.of(0), CGRL2Switch.FLOWMOD_PRIORITY, match, null, al, CGRL2Switch.FLOWMOD_DEFAULT_HARD_TIMEOUT, CGRL2Switch.FLOWMOD_DEFAULT_IDLE_TIMEOUT, OFBufferId.NO_BUFFER);
  242. */
  243.  
  244. //
  245. return Command.STOP;
  246. }
  247.  
  248. /**
  249. * Processes a flow removed message.
  250. * @param sw The switch that sent the flow removed message.
  251. * @param flowRemovedMessage The flow removed message.
  252. * @return Whether to continue processing this message or stop.
  253. */
  254. private Command processFlowRemovedMessage(IOFSwitch sw, OFFlowRemoved flowRemovedMessage) {
  255. if (log.isTraceEnabled()) {
  256. log.trace("{} flow entry removed {}", sw, flowRemovedMessage);
  257. }
  258. Match match = flowRemovedMessage.getMatch();
  259. // When a flow entry expires, it means the device with the matching source
  260. // MAC address either stopped sending packets or moved to a different
  261. // port. If the device moved, we can't know where it went until it sends
  262. // another packet, allowing us to re-learn its port. Meanwhile we remove
  263. // it from the macToPortMap to revert to flooding packets to this device.
  264.  
  265. // Also, if packets keep coming from another device (e.g. from ping), the
  266. // corresponding reverse flow entry will never expire on its own and will
  267. // send the packets to the wrong port (the matching input port of the
  268. // expired flow entry), so we must delete the reverse entry explicitly.
  269.  
  270. return Command.CONTINUE;
  271. }
  272.  
  273. // IOFMessageListener
  274.  
  275. @Override
  276. public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
  277. switch (msg.getType()) {
  278. case PACKET_IN:
  279. return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx);
  280. case FLOW_REMOVED:
  281. return this.processFlowRemovedMessage(sw, (OFFlowRemoved) msg);
  282. case ERROR:
  283. log.info("received an error {} from switch {}", msg, sw);
  284. return Command.CONTINUE;
  285. default:
  286. log.error("received an unexpected message {} from switch {}", msg, sw);
  287. return Command.CONTINUE;
  288. }
  289. }
  290.  
  291. @Override
  292. public boolean isCallbackOrderingPrereq(OFType type, String name) {
  293. return false;
  294. }
  295.  
  296. @Override
  297. public boolean isCallbackOrderingPostreq(OFType type, String name) {
  298. return (type.equals(OFType.PACKET_IN) && name.equals("forwarding")) ;
  299. }
  300.  
  301. // IFloodlightModule
  302.  
  303. /**
  304. * Tell the module system which services we provide.
  305. */
  306. @Override
  307. public Collection<Class<? extends IFloodlightService>> getModuleServices()
  308. { return null; }
  309.  
  310. /**
  311. * Tell the module system which services we implement.
  312. */
  313. @Override
  314. public Map<Class<? extends IFloodlightService>, IFloodlightService>
  315. getServiceImpls()
  316. { return null; }
  317.  
  318. @Override
  319. public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
  320. Collection<Class<? extends IFloodlightService>> l =
  321. new ArrayList<Class<? extends IFloodlightService>>();
  322. l.add(IFloodlightProviderService.class);
  323. return l;
  324. }
  325.  
  326. @Override
  327. public void init(FloodlightModuleContext context) throws FloodlightModuleException {
  328. macToSwitchPortMap = new ConcurrentHashMap<IOFSwitch, Map<MacAddress, OFPort>>();
  329. floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class);
  330. log.info("CGR module started {}");
  331. }
  332.  
  333. @Override
  334. public void startUp(FloodlightModuleContext context) {
  335. // paag: register the IControllerCompletionListener
  336. floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);
  337. floodlightProviderService.addOFMessageListener(OFType.FLOW_REMOVED, this);
  338. floodlightProviderService.addOFMessageListener(OFType.ERROR, this);
  339.  
  340. // read our config options
  341. Map<String, String> configOptions = context.getConfigParams(this);
  342. try {
  343. String idleTimeout = configOptions.get("idletimeout");
  344. if (idleTimeout != null) {
  345. FLOWMOD_DEFAULT_IDLE_TIMEOUT = Short.parseShort(idleTimeout);
  346. }
  347. } catch (NumberFormatException e) {
  348. log.warn("Error parsing flow idle timeout, " +
  349. "using default of {} seconds", FLOWMOD_DEFAULT_IDLE_TIMEOUT);
  350. }
  351. try {
  352. String hardTimeout = configOptions.get("hardtimeout");
  353. if (hardTimeout != null) {
  354. FLOWMOD_DEFAULT_HARD_TIMEOUT = Short.parseShort(hardTimeout);
  355. }
  356. } catch (NumberFormatException e) {
  357. log.warn("Error parsing flow hard timeout, " +
  358. "using default of {} seconds", FLOWMOD_DEFAULT_HARD_TIMEOUT);
  359. }
  360. try {
  361. String priority = configOptions.get("priority");
  362. if (priority != null) {
  363. FLOWMOD_PRIORITY = Short.parseShort(priority);
  364. }
  365. } catch (NumberFormatException e) {
  366. log.warn("Error parsing flow priority, " +
  367. "using default of {}",
  368. FLOWMOD_PRIORITY);
  369. }
  370. log.debug("FlowMod idle timeout set to {} seconds", FLOWMOD_DEFAULT_IDLE_TIMEOUT);
  371. log.debug("FlowMod hard timeout set to {} seconds", FLOWMOD_DEFAULT_HARD_TIMEOUT);
  372. log.debug("FlowMod priority set to {}", FLOWMOD_PRIORITY);
  373. }
  374.  
  375. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement