blob: 4dfb60b5b8469d38785ea9889fd118cd00e98f54 [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/**
18 * Dampens OFMessages sent to an OF switch. A message is only written to
19 * 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
21 * @author gregor
22 *
23 */
24public class OFMessageDamper {
25 /**
26 * An entry in the TimedCache. A cache entry consists of the sent message
27 * as well as the switch to which the message was sent.
28 *
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 *
33 * 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.
36 *
37 * @author gregor
38 */
39 protected static class DamperEntry {
40 OFMessage msg;
41 IOFSwitch sw;
42 public DamperEntry(OFMessage msg, IOFSwitch sw) {
43 super();
44 this.msg = msg;
45 this.sw = sw;
46 }
47 /* (non-Javadoc)
48 * @see java.lang.Object#hashCode()
49 */
50 @Override
51 public int hashCode() {
52 final int prime = 31;
53 int result = 1;
54 result = prime * result + ((msg == null) ? 0 : msg.hashCode());
55 result = prime * result + ((sw == null) ? 0 : sw.hashCode());
56 return result;
57 }
58 /* (non-Javadoc)
59 * @see java.lang.Object#equals(java.lang.Object)
60 */
61 @Override
62 public boolean equals(Object obj) {
63 if (this == obj) return true;
64 if (obj == null) return false;
65 if (getClass() != obj.getClass()) return false;
66 DamperEntry other = (DamperEntry) obj;
67 if (msg == null) {
68 if (other.msg != null) return false;
69 } else if (!msg.equals(other.msg)) return false;
70 if (sw == null) {
71 if (other.sw != null) return false;
72 } else if (!sw.equals(other.sw)) return false;
73 return true;
74 }
75
76
77 }
78 TimedCache<DamperEntry> cache;
79 EnumSet<OFType> msgTypesToCache;
80 /**
81 *
82 * @param capacity the maximum number of messages that should be
83 * kept
84 * @param typesToDampen The set of OFMessageTypes that should be
85 * dampened by this instance. Other types will be passed through
86 * @param timeout The dampening timeout. A message will only be
87 * written if the last write for the an equal message more than
88 * timeout ms ago.
89 */
90 public OFMessageDamper(int capacity,
91 Set<OFType> typesToDampen,
92 int timeout) {
93 cache = new TimedCache<DamperEntry>(capacity, timeout);
94 msgTypesToCache = EnumSet.copyOf(typesToDampen);
95 }
96
97 /**
98 * write the messag to the switch according to our dampening settings
99 * @param sw
100 * @param msg
101 * @param cntx
102 * @return true if the message was written to the switch, false if
103 * the message was dampened.
104 * @throws IOException
105 */
106 public boolean write(IOFSwitch sw, OFMessage msg, FloodlightContext cntx)
107 throws IOException {
108 return write(sw, msg, cntx, false);
109 }
110
111 /**
112 * write the messag to the switch according to our dampening settings
113 * @param sw
114 * @param msg
115 * @param cntx
116 * @param flush true to flush the packet immidiately
117 * @return true if the message was written to the switch, false if
118 * the message was dampened.
119 * @throws IOException
120 */
121 public boolean write(IOFSwitch sw, OFMessage msg,
122 FloodlightContext cntx, boolean flush)
123 throws IOException {
124 if (! msgTypesToCache.contains(msg.getType())) {
125 sw.write(msg, cntx);
126 if (flush) {
127 sw.flush();
128 }
129 return true;
130 }
131
132 DamperEntry entry = new DamperEntry(msg, sw);
133 if (cache.update(entry)) {
134 // entry exists in cache. Dampening.
135 return false;
136 } else {
137 sw.write(msg, cntx);
138 if (flush) {
139 sw.flush();
140 }
141 return true;
142 }
143 }
144}