· 7 years ago · Dec 10, 2018, 09:18 PM
1package net.floodlightcontroller.cgrmodule;
2
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.Collections;
6import java.util.HashMap;
7import java.util.HashSet;
8import java.util.Iterator;
9import java.util.List;
10import java.util.Map;
11import java.util.Map.Entry;
12import java.util.Set;
13import java.util.concurrent.ConcurrentHashMap;
14
15import org.projectfloodlight.openflow.protocol.OFFlowMod;
16import org.projectfloodlight.openflow.protocol.OFFlowModCommand;
17import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
18import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
19import org.projectfloodlight.openflow.protocol.OFMessage;
20import org.projectfloodlight.openflow.protocol.OFPacketIn;
21import org.projectfloodlight.openflow.protocol.OFPacketOut;
22import org.projectfloodlight.openflow.protocol.OFType;
23import org.projectfloodlight.openflow.protocol.OFVersion;
24import org.projectfloodlight.openflow.protocol.action.OFAction;
25import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
26import org.projectfloodlight.openflow.protocol.action.OFActions;
27import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
28import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
29import org.projectfloodlight.openflow.protocol.instruction.OFInstructions;
30import org.projectfloodlight.openflow.protocol.match.Match;
31import org.projectfloodlight.openflow.protocol.match.MatchField;
32import org.projectfloodlight.openflow.types.EthType;
33import org.projectfloodlight.openflow.types.IPv4Address;
34import org.projectfloodlight.openflow.types.IpProtocol;
35import org.projectfloodlight.openflow.types.MacAddress;
36import org.projectfloodlight.openflow.types.OFBufferId;
37import org.projectfloodlight.openflow.types.OFPort;
38import org.projectfloodlight.openflow.types.OFVlanVidMatch;
39import org.projectfloodlight.openflow.types.TableId;
40import org.projectfloodlight.openflow.types.TransportPort;
41import org.projectfloodlight.openflow.types.U64;
42import org.projectfloodlight.openflow.types.VlanVid;
43import org.projectfloodlight.openflow.util.LRULinkedHashMap;
44import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46
47import javafx.util.Pair;
48import net.floodlightcontroller.cgrmodule.util.*;
49import net.floodlightcontroller.core.FloodlightContext;
50import net.floodlightcontroller.core.IControllerCompletionListener;
51import net.floodlightcontroller.core.IFloodlightProviderService;
52import net.floodlightcontroller.core.IOFMessageListener;
53import net.floodlightcontroller.core.IOFSwitch;
54import net.floodlightcontroller.core.module.FloodlightModuleContext;
55import net.floodlightcontroller.core.module.FloodlightModuleException;
56import net.floodlightcontroller.core.module.IFloodlightModule;
57import net.floodlightcontroller.core.module.IFloodlightService;
58import net.floodlightcontroller.learningswitch.LearningSwitch;
59import net.floodlightcontroller.packet.Ethernet;
60import net.floodlightcontroller.packet.IPv4;
61import net.floodlightcontroller.packet.TCP;
62import net.floodlightcontroller.util.OFMessageUtils;
63
64public class CGRmodule implements IFloodlightModule, IOFMessageListener {
65 protected static Logger log = LoggerFactory.getLogger(CGRmodule.class);
66
67 // Module dependencies
68 protected IFloodlightProviderService floodlightProviderService;
69
70 // Stores the learned state for each switch
71 protected Map<IOFSwitch, Map<MacAddress, OFPort>> ControllerMap;
72
73 // Stores the number of connections for a given MAC address.
74 protected Map<IOFSwitch, Map<Pair<IPv4Address,TransportPort>, Integer>> TCPLinkCounterMap;
75
76 // flow-mod - for use in the cookie
77 public static final int LEARNING_SWITCH_APP_ID = 1;
78 // LOOK! This should probably go in some class that encapsulates
79 // the app cookie management
80 public static final int APP_ID_BITS = 12;
81 public static final int APP_ID_SHIFT = (64 - APP_ID_BITS);
82 public static final long LEARNING_SWITCH_COOKIE = (long) (LEARNING_SWITCH_APP_ID & ((1 << APP_ID_BITS) - 1)) << APP_ID_SHIFT;
83
84 // more flow-mod defaults
85 protected static short FLOWMOD_DEFAULT_IDLE_TIMEOUT = 5; // in seconds
86 protected static short FLOWMOD_DEFAULT_HARD_TIMEOUT = 0; // infinite
87 protected static short FLOWMOD_PRIORITY = 100;
88 protected static short DEFAULT_PRIORITY = 10;
89
90 // for managing our map sizes
91 protected static final int MAX_MACS_PER_SWITCH = 1000;
92
93 // CGR Firewall module
94 protected static final int MAX_DESTINATION_NUMBER = 3;
95 protected static final int MAX_ELEPHANT_FLOWS = 3;
96 protected static final int ELEPHANT_FLOW_BW = 10;
97
98 // normally, setup reverse flow as well. Disable only for using cbench for comparison with NOX etc.
99 protected static final boolean LEARNING_SWITCH_REVERSE_FLOW = true;
100
101 /**
102 * @param floodlightProvider the floodlightProvider to set
103 */
104 public void setFloodlightProvider(IFloodlightProviderService floodlightProviderService) {
105 this.floodlightProviderService = floodlightProviderService;
106 }
107
108 @Override
109 public String getName() {
110 return "CGRModule";
111 }
112
113 /**
114 * Adds a host to the MAC->SwitchPort mapping
115 * @param sw The switch to add the mapping to
116 * @param mac The MAC address of the host to add
117 * @param portVal The switchport that the host is on
118 */
119 protected void addToPortMap(IOFSwitch sw, MacAddress mac, OFPort portVal)
120 {
121 Map<MacAddress, OFPort> swMap = ControllerMap.get(sw);
122
123 // Check if the switch already exists
124 if (swMap == null) {
125 swMap = new LRULinkedHashMap<MacAddress, OFPort>(MAX_MACS_PER_SWITCH);
126 ControllerMap.put(sw, swMap);
127 }
128
129 if ( swMap.putIfAbsent(mac, portVal) != portVal) {
130 swMap.replace(mac, portVal);
131 log.info( "Sw: " + sw
132 + " --- New PortMAC: "
133 + " MAC {} PORT {}",
134 new Object[]{ mac.toString(),
135 portVal});
136 }
137 }
138 protected void addToTCPLinkCounterMap(IOFSwitch sw, Pair<IPv4Address,TransportPort> ipport)
139 {
140 Map<Pair<IPv4Address,TransportPort>, Integer> TCPmap = TCPLinkCounterMap.get(sw);
141
142 // Check if the switch already exists
143 if (TCPmap == null)
144 {
145 TCPmap = new LRULinkedHashMap<Pair<IPv4Address,TransportPort>,Integer>(MAX_MACS_PER_SWITCH);
146 TCPLinkCounterMap.put(sw, TCPmap);
147 }
148
149 if ( TCPmap.containsKey(ipport))
150 {
151 TCPmap.replace(ipport, TCPmap.get(ipport)+1);
152 log.info( "Sw: " + sw
153 + " --- New PortTCP: "
154 + " IP/TCP {} Counter {}",
155 new Object[]{ ipport.toString(), //pode dar merda
156 TCPmap.get(ipport)+1});
157 }
158 else
159 {
160 TCPmap.put(ipport, 1);
161 }
162
163 }
164
165 /**
166 * Removes a host from the MAC->SwitchPort mapping
167 * @param sw The switch to remove the mapping from
168 * @param mac The MAC address of the host to remove
169 */
170 protected void removeFromPortMap(IOFSwitch sw, MacAddress mac) {
171
172 Map<MacAddress, OFPort> swMap = ControllerMap.get(sw);
173 if (swMap != null) {
174 swMap.remove(mac);
175 log.info( "Sw: " + sw
176 + " --- Removed PortMAC: "
177 + " MAC {}",
178 new Object[]{ mac.toString()});
179 }
180 }
181
182 /**
183 * Get the port that a MAC is associated with
184 * @param sw The switch to get the mapping from
185 * @param mac The MAC address to get
186 * @return The port the host is on
187 */
188 public OFPort getFromPortMap(IOFSwitch sw, MacAddress mac) {
189 Map<MacAddress, OFPort> swMap = ControllerMap.get(sw);
190 if (swMap != null) {
191 return swMap.get(mac);
192 }
193
194 // if none found
195 return null;
196 }
197
198 /**
199 * Clears the MAC -> SwitchPort map for all switches
200 */
201 public void clearLearnedTable() {
202 ControllerMap.clear();
203 }
204
205 /**
206 * Clears the MAC/VLAN -> SwitchPort map for a single switch
207 * @param sw The switch to clear the mapping for
208 */
209 public void clearLearnedTable(IOFSwitch sw) {
210 Map<MacAddress, OFPort> swMap = ControllerMap.get(sw);
211 if (swMap != null) {
212 swMap.clear();
213 }
214 }
215
216 protected Match createMatchFromPacket(IOFSwitch sw, OFPort inPort, FloodlightContext cntx)
217 {
218 // The packet in match will only contain the port number.
219 // We need to add in specifics for the hosts we're routing between.
220 Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
221 MacAddress srcMac = eth.getSourceMACAddress();
222 MacAddress dstMac = eth.getDestinationMACAddress();
223
224 Match.Builder mb = sw.getOFFactory().buildMatch();
225 mb.setExact(MatchField.IN_PORT, inPort)
226 .setExact(MatchField.ETH_SRC, srcMac)
227 .setExact(MatchField.ETH_DST, dstMac);
228 //.setExact(MatchField.TCP_DST)
229 return mb.build();
230 }
231
232 protected Match createMatchFromTCPPacket(IOFSwitch sw, OFPort inPort, FloodlightContext cntx)
233 {
234 // The packet in match will only contain the port number.
235 // We need to add in specifics for the hosts we're routing between.
236 Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
237 MacAddress srcMac = eth.getSourceMACAddress();
238 MacAddress dstMac = eth.getDestinationMACAddress();
239
240 if ( eth.getEtherType() == EthType.IPv4 )
241 {
242 IPv4 ipv4 = (IPv4) eth.getPayload();
243 IPv4Address ipv4Src = ipv4.getSourceAddress();
244 IPv4Address ipv4Dest = ipv4.getDestinationAddress();
245
246 if ( ipv4.getProtocol() == IpProtocol.TCP )
247 {
248 TCP tcp = (TCP) ipv4.getPayload();
249 TransportPort portSrc = tcp.getSourcePort();
250 TransportPort portDest = tcp.getDestinationPort();
251
252 Match.Builder mb = sw.getOFFactory().buildMatch();
253 mb.setExact(MatchField.IN_PORT, inPort)
254 .setExact(MatchField.ETH_SRC, srcMac)
255 .setExact(MatchField.ETH_DST, dstMac)
256 .setExact(MatchField.IPV4_SRC, ipv4Src)
257 .setExact(MatchField.IPV4_DST, ipv4Dest)
258 .setExact(MatchField.TCP_DST, portDest)
259 .setExact(MatchField.TCP_SRC, portSrc);
260 return mb.build();
261 } // End of TCP
262 } // End of IPv4
263 return null;
264 }
265
266 protected Match createReverseMatchfromMatch(IOFSwitch sw, OFPort outPort, Match match)
267 {
268 Match.Builder rev_match = match.createBuilder();
269 rev_match.setExact(MatchField.IN_PORT, outPort)
270 .setExact(MatchField.ETH_SRC, match.get(MatchField.ETH_DST))
271 .setExact(MatchField.ETH_DST, match.get(MatchField.ETH_SRC));
272 return rev_match.build();
273 }
274
275 protected Match createReverseMatchfromMatch(IOFSwitch sw, Match match)
276 {
277 Match.Builder rev_match = match.createBuilder();
278 rev_match.setExact(MatchField.ETH_SRC, match.get(MatchField.ETH_DST))
279 .setExact(MatchField.ETH_DST, match.get(MatchField.ETH_SRC));
280
281 return rev_match.build();
282 }
283
284 protected void createFlowMod(IOFSwitch sw, OFPort Port, Match match, OFVersion version, short prio, Boolean remFlag)
285 {
286 // Action List
287 List<OFAction> al = new ArrayList<OFAction>();
288 OFActionOutput output = sw.getOFFactory().actions().buildOutput()
289 .setPort(Port) // outPort is the port trough which the sw should send the Matching Packets
290 .setMaxLen(0xffFFffFF)
291 .build();
292 al.add(output);
293
294
295 // Write the flow mod using SwitchCommands install rule method since it receives either instructions or actions
296 // depending on the OpenFlow Version you should do the following:
297 if (version.compareTo(OFVersion.OF_13) == 0 )
298 {
299 OFInstructionApplyActions applyActions = sw.getOFFactory().instructions().buildApplyActions().setActions(al).build(); //use the instructions builder to build an applyActions instruction with the given action list.
300 ArrayList<OFInstruction> instructionList = new ArrayList<OFInstruction>();
301 instructionList.add(applyActions); //add the applyActions Instruction to the Instruction list
302 SwitchCommands.installRule(sw, TableId.of(0), prio, match, instructionList, null, CGRmodule.FLOWMOD_DEFAULT_HARD_TIMEOUT, CGRmodule.FLOWMOD_DEFAULT_IDLE_TIMEOUT, OFBufferId.NO_BUFFER, remFlag);
303
304 } else {
305 SwitchCommands.installRule(sw, null, prio, match, null, al, CGRmodule.FLOWMOD_DEFAULT_HARD_TIMEOUT, CGRmodule.FLOWMOD_DEFAULT_IDLE_TIMEOUT, OFBufferId.NO_BUFFER, remFlag);
306 }
307 }
308
309 /**
310 * Processes a OFPacketIn message. If the switch has learned the MAC to port mapping
311 * for the pair it will write a FlowMod for. If the mapping has not been learned the
312 * we will flood the packet.
313 * @param sw
314 * @param pi
315 * @param cntx
316 * @return
317 */
318 @SuppressWarnings("unused")
319 private Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx)
320 {
321 Integer lnk_count;
322
323 // Read inPort and declare outPort
324 OFPort inPort = (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT));
325 OFPort outPort;
326
327 /* Read packet header attributes into a Match object */
328 Match match = createMatchFromPacket(sw, inPort, cntx);
329 MacAddress sourceMac = match.get(MatchField.ETH_SRC);
330 MacAddress destMac = match.get(MatchField.ETH_DST);
331
332 if (sourceMac == null)
333 {
334 sourceMac = MacAddress.NONE;
335 }
336 if (destMac == null)
337 {
338 destMac = MacAddress.NONE;
339 }
340
341 if ((destMac.getLong() & 0xfffffffffff0L) == 0x0180c2000000L)
342 {
343 if (log.isTraceEnabled())
344 {
345 log.info("ignoring packet addressed to 802.1D/Q reserved addr: switch {} dest MAC {}",
346 new Object[]{ sw,
347 destMac.toString() });
348 }
349 return Command.STOP;
350 }
351
352 if ( (sourceMac.getLong() & 0x010000000000L) == 0)
353 {
354 // If source MAC is a unicast address, learn the port for this MAC/VLAN
355 addToPortMap(sw, sourceMac, inPort); // If the entry already exists, it is replaced
356 }
357
358 // Check if port for destination MAC is known
359 // If so output flow-mod and/or packet
360 // If link destination number is exceeded, drop
361 if ( (outPort = getFromPortMap(sw, destMac)) == null)
362 {
363 // No port entry for the given MAC - Flood the packet
364 SwitchCommands.sendPacketOutPacketIn(sw, OFPort.FLOOD, pi);
365 log.info( "Sw: " + sw
366 + " ... Flooding: "
367 + "SRC {} DEST {}",
368 new Object[]{ sourceMac.toString(),
369 destMac.toString()});
370 } // End of Flood
371 else
372 {
373 // If there is no MacLinkCounter entry for the SourceMAC
374 // Push packet to switch
375 SwitchCommands.sendPacketOutPacketIn(sw, outPort, pi);
376 log.info( "Sw: " + sw
377 + " ... Sending packet to known destination port: "
378 + "SRC {} DEST {} inP {} outP {} {}",
379 new Object[]{ sourceMac.toString(),
380 destMac.toString(),
381 inPort.getPortNumber(),
382 outPort.getPortNumber() });
383
384 // Extract Ethernet Packet
385 Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
386
387 if ( eth.getEtherType() == EthType.IPv4 )
388 {
389 IPv4 ipv4 = (IPv4) eth.getPayload();
390
391 IPv4Address ipv4src = ipv4.getSourceAddress();
392 IPv4Address ipv4dest = ipv4.getDestinationAddress();
393
394 if ( ipv4.getProtocol() == IpProtocol.TCP )
395 {
396 TCP tcp = (TCP) ipv4.getPayload();
397
398 TransportPort portSrc = tcp.getSourcePort();
399 TransportPort portDest = tcp.getDestinationPort();
400
401 Pair<IPv4Address,TransportPort> ipport = new Pair<IPv4Address,TransportPort>(ipv4src, portSrc);
402
403 Match tcpmatch = createMatchFromTCPPacket(sw, outPort, cntx);
404
405 if ( ( lnk_count = TCPLinkCounterMap.get(ipport) ) != null && lnk_count >= MAX_DESTINATION_NUMBER)
406 {
407 // Link Destinations exceeded, drop packet.
408 log.info( "Sw: " + sw
409 + " ---> Excessive Connections: "
410 + "TCP {} IP {} LinkCount {}",
411 new Object[]{ portSrc.toString(),
412 ipv4src.toString(),
413 lnk_count });
414
415 } // End of Max Connections
416 else
417 {
418 // Create or Increment MAC Counter entry
419 if ( (lnk_count = TCPLinkCounterMap.putIfAbsent(ipport, 1)) != null)
420 {
421 TCPLinkCounterMap.replace(ipport, ++lnk_count);
422 } // End of Increment Table
423
424 log.info( "Sw: " + sw
425 + " *** Link Count Update: "
426 + "TCP {} IP {} LinkCount {}",
427 new Object[]{ portSrc.toString(),
428 ipv4src.toString(),
429 TCPLinkCounterMap.get(new Pair<IPv4Address, TransportPort>(ipv4src, portSrc)) });
430
431 // Create TCP/PORT Flow
432 createFlowMod(sw, outPort, tcpmatch, pi.getVersion(), CGRmodule.FLOWMOD_PRIORITY, true);
433
434
435 log.info( "Sw: " + sw
436 + " *** New TCP Flow: "
437 + "IP_SRC {}:{} IP_DEST {}:{} PORT {}",
438 new Object[]{ ipv4src.toString(),
439 portSrc.toString(),
440 ipv4dest.toString(),
441 portDest.toString(),
442 outPort.getPortNumber() });
443
444 } // End of Create New Flow - Maximum Connections not reached
445 } // End of TCP Packet
446 } // End of IPv4 Packet
447
448 if (sourceMac != null && destMac != null)
449 {
450 // Add flow table entry matching source MAC, dest MAC and input port
451 // that sends to the port we previously learned for the dest MAC.
452 // We write FlowMods with Buffer ID none then explicitly PacketOut the buffered packet
453 createFlowMod(sw, outPort, match, pi.getVersion(), CGRmodule.DEFAULT_PRIORITY, false);
454
455 // Also add a flow table entry with source and destination MACs reversed, and
456 // input and output ports reversed.
457 if (LEARNING_SWITCH_REVERSE_FLOW && false)
458 {
459 // Create Reserve Match
460 Match rev_match = createReverseMatchfromMatch(sw, inPort, match); // CHECK PORT TO USE /IN/OUT
461 createFlowMod(sw, inPort, rev_match, pi.getVersion(), CGRmodule.DEFAULT_PRIORITY, false);
462 }
463
464 } // End of srcMac & srcDest != NULL
465 } // End of Know Destination Port
466 return Command.STOP;
467 }
468
469 /**
470 * Processes a flow removed message.
471 * @param sw The switch that sent the flow removed message.
472 * @param flowRemovedMessage The flow removed message.
473 * @return Whether to continue processing this message or stop.
474 */
475 @SuppressWarnings("unused")
476 private Command processFlowRemovedMessage(IOFSwitch sw, OFFlowRemoved flowRemovedMessage) {
477 Integer lnk_count;
478 Match match = flowRemovedMessage.getMatch();
479 MacAddress srcMac = match.get(MatchField.ETH_SRC);
480 MacAddress dstMac = match.get(MatchField.ETH_DST);
481
482 IPv4Address srcIPv4 = match.get(MatchField.IPV4_SRC);
483 IPv4Address dstIPv4 = match.get(MatchField.IPV4_DST);
484
485 TransportPort srcPort = match.get(MatchField.TCP_SRC);
486 TransportPort dstPort = match.get(MatchField.TCP_DST);
487
488 if (srcIPv4 != null
489 && dstIPv4 != null
490 && srcPort != null
491 && dstPort != null)
492 {
493 Pair<IPv4Address,TransportPort> ipport = new Pair<IPv4Address,TransportPort>(srcIPv4, srcPort);
494
495 // Decrement MAC counter links
496 if ( (lnk_count = TCPLinkCounterMap.get(ipport) ) != null /*&& lnk_count > 0*/)
497 {
498 TCPLinkCounterMap.replace(ipport, --lnk_count);
499 }
500
501 log.info( "Sw: " + sw
502 + " *** TCP Flow Removed: "
503 + "SRC {} LinkCount {}",
504 new Object[]{ ipport.toString(),
505 TCPLinkCounterMap.get(ipport) });
506 } // End of TCP Match
507
508
509
510
511 // When a flow entry expires, it means the device with the matching source
512 // MAC address either stopped sending packets or moved to a different
513 // port. If the device moved, we can't know where it went until it sends
514 // another packet, allowing us to re-learn its port. Meanwhile we remove
515 // it from the macToPortMap to revert to flooding packets to this device.
516 removeFromPortMap(sw, srcMac);
517
518 // Also, if packets keep coming from another device (e.g. from ping), the
519 // corresponding reverse flow entry will never expire on its own and will
520 // send the packets to the wrong port (the matching input port of the
521 // expired flow entry), so we must delete the reverse entry explicitly.
522 if(LEARNING_SWITCH_REVERSE_FLOW && false) {
523 Match rev_match = createReverseMatchfromMatch(sw, match);
524 SwitchCommands.removeRules(sw, rev_match, flowRemovedMessage.getVersion() );
525 }
526
527 return Command.CONTINUE;
528 }
529
530 // IOFMessageListener
531
532 @Override
533 public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
534 switch (msg.getType()) {
535 case PACKET_IN:
536 return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx);
537 case FLOW_REMOVED:
538 return this.processFlowRemovedMessage(sw, (OFFlowRemoved) msg);
539 case ERROR:
540 log.info("received an error {} from switch {}", msg, sw);
541 return Command.CONTINUE;
542 default:
543 log.error("received an unexpected message {} from switch {}", msg, sw);
544 return Command.CONTINUE;
545 }
546 }
547
548 @Override
549 public boolean isCallbackOrderingPrereq(OFType type, String name) {
550 return false;
551 }
552
553 @Override
554 public boolean isCallbackOrderingPostreq(OFType type, String name) {
555 return (type.equals(OFType.PACKET_IN) && name.equals("forwarding")) ;
556 }
557
558 // IFloodlightModule
559
560 /**
561 * Tell the module system which services we provide.
562 */
563 @Override
564 public Collection<Class<? extends IFloodlightService>> getModuleServices()
565 { return null; }
566
567 /**
568 * Tell the module system which services we implement.
569 */
570 @Override
571 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls()
572 { return null; }
573
574 @Override
575 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
576 Collection<Class<? extends IFloodlightService>> l =
577 new ArrayList<Class<? extends IFloodlightService>>();
578 l.add(IFloodlightProviderService.class);
579 return l;
580 }
581
582 @Override
583 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
584 ControllerMap = new ConcurrentHashMap<IOFSwitch, Map<MacAddress, OFPort>>();
585 TCPLinkCounterMap = new ConcurrentHashMap< Pair<IPv4Address,TransportPort>, Integer>();
586 floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class);
587 log.info("CGR module started {}");
588 }
589
590 @Override
591 public void startUp(FloodlightModuleContext context)
592 {
593 // paag: register the IControllerCompletionListener
594 floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);
595 floodlightProviderService.addOFMessageListener(OFType.FLOW_REMOVED, this);
596 floodlightProviderService.addOFMessageListener(OFType.ERROR, this);
597
598 // read our config options
599 Map<String, String> configOptions = context.getConfigParams(this);
600 try {
601 String idleTimeout = configOptions.get("idletimeout");
602 if (idleTimeout != null) {
603 FLOWMOD_DEFAULT_IDLE_TIMEOUT = Short.parseShort(idleTimeout);
604 }
605 } catch (NumberFormatException e) {
606 log.warn("Error parsing flow idle timeout, " +
607 "using default of {} seconds", FLOWMOD_DEFAULT_IDLE_TIMEOUT);
608 }
609 try {
610 String hardTimeout = configOptions.get("hardtimeout");
611 if (hardTimeout != null) {
612 FLOWMOD_DEFAULT_HARD_TIMEOUT = Short.parseShort(hardTimeout);
613 }
614 } catch (NumberFormatException e) {
615 log.warn("Error parsing flow hard timeout, " +
616 "using default of {} seconds", FLOWMOD_DEFAULT_HARD_TIMEOUT);
617 }
618 try {
619 String priority = configOptions.get("priority");
620 if (priority != null) {
621 FLOWMOD_PRIORITY = Short.parseShort(priority);
622 }
623 } catch (NumberFormatException e) {
624 log.warn("Error parsing flow priority, " +
625 "using default of {}",
626 FLOWMOD_PRIORITY);
627 }
628 log.debug("FlowMod idle timeout set to {} seconds", FLOWMOD_DEFAULT_IDLE_TIMEOUT);
629 log.debug("FlowMod hard timeout set to {} seconds", FLOWMOD_DEFAULT_HARD_TIMEOUT);
630 log.debug("FlowMod priority set to {}", FLOWMOD_PRIORITY);
631 }
632
633}