blob: 47a92a9f6e9730274f11ac7f7443336a432de2a6 [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/*
2 * Copyright Big Switch Networks 2012
3 */
4
5package net.floodlightcontroller.util;
6
7import java.io.IOException;
8import java.util.EnumSet;
9import java.util.Set;
10
11import net.floodlightcontroller.core.FloodlightContext;
12import net.floodlightcontroller.core.IOFSwitch;
13
14import org.openflow.protocol.OFMessage;
15import org.openflow.protocol.OFType;
16
17/**
Ray Milkey269ffb92014-04-03 14:43:30 -070018 * Dampens OFMessages sent to an OF switch. A message is only written to
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080019 * a switch if the same message (as defined by .equals()) has not been written
20 * in the last n milliseconds. Timer granularity is based on TimedCache
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080021 *
Ray Milkey269ffb92014-04-03 14:43:30 -070022 * @author gregor
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080023 */
24public class OFMessageDamper {
25 /**
26 * An entry in the TimedCache. A cache entry consists of the sent message
Ray Milkey269ffb92014-04-03 14:43:30 -070027 * as well as the switch to which the message was sent.
28 * <p/>
29 * NOTE: We currently use the full OFMessage object. To save space, we
30 * could use a cryptographic hash (e.g., SHA-1). However, this would
31 * obviously be more time-consuming....
32 * <p/>
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080033 * We also store a reference to the actual IOFSwitch object and /not/
34 * the switch DPID. This way we are guarnteed to not dampen messages if
35 * a switch disconnects and then reconnects.
Ray Milkey269ffb92014-04-03 14:43:30 -070036 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080037 * @author gregor
38 */
39 protected static class DamperEntry {
40 OFMessage msg;
41 IOFSwitch sw;
Ray Milkey269ffb92014-04-03 14:43:30 -070042
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080043 public DamperEntry(OFMessage msg, IOFSwitch sw) {
44 super();
45 this.msg = msg;
46 this.sw = sw;
47 }
Ray Milkey269ffb92014-04-03 14:43:30 -070048
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080049 /* (non-Javadoc)
50 * @see java.lang.Object#hashCode()
51 */
52 @Override
53 public int hashCode() {
54 final int prime = 31;
55 int result = 1;
56 result = prime * result + ((msg == null) ? 0 : msg.hashCode());
57 result = prime * result + ((sw == null) ? 0 : sw.hashCode());
58 return result;
59 }
Ray Milkey269ffb92014-04-03 14:43:30 -070060
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080061 /* (non-Javadoc)
62 * @see java.lang.Object#equals(java.lang.Object)
63 */
64 @Override
65 public boolean equals(Object obj) {
66 if (this == obj) return true;
67 if (obj == null) return false;
68 if (getClass() != obj.getClass()) return false;
69 DamperEntry other = (DamperEntry) obj;
70 if (msg == null) {
71 if (other.msg != null) return false;
72 } else if (!msg.equals(other.msg)) return false;
73 if (sw == null) {
74 if (other.sw != null) return false;
75 } else if (!sw.equals(other.sw)) return false;
76 return true;
77 }
Ray Milkey269ffb92014-04-03 14:43:30 -070078
79
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080080 }
Ray Milkey269ffb92014-04-03 14:43:30 -070081
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080082 TimedCache<DamperEntry> cache;
83 EnumSet<OFType> msgTypesToCache;
Ray Milkey269ffb92014-04-03 14:43:30 -070084
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080085 /**
Ray Milkey269ffb92014-04-03 14:43:30 -070086 * @param capacity the maximum number of messages that should be
87 * kept
88 * @param typesToDampen The set of OFMessageTypes that should be
89 * dampened by this instance. Other types will be passed through
90 * @param timeout The dampening timeout. A message will only be
91 * written if the last write for the an equal message more than
92 * timeout ms ago.
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080093 */
Ray Milkey269ffb92014-04-03 14:43:30 -070094 public OFMessageDamper(int capacity,
95 Set<OFType> typesToDampen,
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080096 int timeout) {
97 cache = new TimedCache<DamperEntry>(capacity, timeout);
98 msgTypesToCache = EnumSet.copyOf(typesToDampen);
Ray Milkey269ffb92014-04-03 14:43:30 -070099 }
100
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800101 /**
102 * write the messag to the switch according to our dampening settings
Ray Milkey269ffb92014-04-03 14:43:30 -0700103 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800104 * @param sw
105 * @param msg
106 * @param cntx
107 * @return true if the message was written to the switch, false if
Ray Milkey269ffb92014-04-03 14:43:30 -0700108 * the message was dampened.
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800109 * @throws IOException
110 */
111 public boolean write(IOFSwitch sw, OFMessage msg, FloodlightContext cntx)
Ray Milkey269ffb92014-04-03 14:43:30 -0700112 throws IOException {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800113 return write(sw, msg, cntx, false);
114 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700115
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800116 /**
117 * write the messag to the switch according to our dampening settings
Ray Milkey269ffb92014-04-03 14:43:30 -0700118 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800119 * @param sw
120 * @param msg
121 * @param cntx
122 * @param flush true to flush the packet immidiately
123 * @return true if the message was written to the switch, false if
Ray Milkey269ffb92014-04-03 14:43:30 -0700124 * the message was dampened.
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800125 * @throws IOException
126 */
127 public boolean write(IOFSwitch sw, OFMessage msg,
Ray Milkey269ffb92014-04-03 14:43:30 -0700128 FloodlightContext cntx, boolean flush)
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800129 throws IOException {
Ray Milkey269ffb92014-04-03 14:43:30 -0700130 if (!msgTypesToCache.contains(msg.getType())) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800131 sw.write(msg, cntx);
132 if (flush) {
133 sw.flush();
134 }
135 return true;
136 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700137
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800138 DamperEntry entry = new DamperEntry(msg, sw);
139 if (cache.update(entry)) {
140 // entry exists in cache. Dampening.
Ray Milkey269ffb92014-04-03 14:43:30 -0700141 return false;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800142 } else {
143 sw.write(msg, cntx);
144 if (flush) {
145 sw.flush();
146 }
147 return true;
148 }
149 }
150}