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