Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Showing
13 changed files
with
465 additions
and
6 deletions
1 | +package org.onlab.onos.cluster; | ||
2 | + | ||
3 | +import org.onlab.onos.net.DeviceId; | ||
4 | + | ||
5 | +// TODO give me a better name | ||
6 | +/** | ||
7 | + * Service to obtain mastership term information. | ||
8 | + */ | ||
9 | +public interface MastershipTermService { | ||
10 | + | ||
11 | + // TBD: manage/increment per device mastership change | ||
12 | + // or increment on any change | ||
13 | + /** | ||
14 | + * Returns the term number of mastership change occurred for given device. | ||
15 | + * | ||
16 | + * @param deviceId the identifier of the device | ||
17 | + * @return current master's term. | ||
18 | + */ | ||
19 | + MastershipTerm getMastershipTerm(DeviceId deviceId); | ||
20 | +} |
... | @@ -51,7 +51,7 @@ public interface DeviceProviderService extends ProviderService<DeviceProvider> { | ... | @@ -51,7 +51,7 @@ public interface DeviceProviderService extends ProviderService<DeviceProvider> { |
51 | * mastership role on the device. | 51 | * mastership role on the device. |
52 | * | 52 | * |
53 | * @param deviceId identity of the device | 53 | * @param deviceId identity of the device |
54 | - * @param role mastership role being asserted | 54 | + * @param role mastership role that was asserted but failed |
55 | */ | 55 | */ |
56 | void unableToAssertRole(DeviceId deviceId, MastershipRole role); | 56 | void unableToAssertRole(DeviceId deviceId, MastershipRole role); |
57 | 57 | ... | ... |
1 | +package org.onlab.onos.store.impl; | ||
2 | + | ||
3 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
4 | +import static com.google.common.base.Preconditions.checkArgument; | ||
5 | + | ||
6 | +import java.util.Objects; | ||
7 | + | ||
8 | +import org.onlab.onos.net.ElementId; | ||
9 | +import org.onlab.onos.store.Timestamp; | ||
10 | + | ||
11 | +import com.google.common.base.MoreObjects; | ||
12 | +import com.google.common.collect.ComparisonChain; | ||
13 | + | ||
14 | +// If it is store specific, implement serializable interfaces? | ||
15 | +/** | ||
16 | + * Default implementation of Timestamp. | ||
17 | + */ | ||
18 | +public final class OnosTimestamp implements Timestamp { | ||
19 | + | ||
20 | + private final ElementId id; | ||
21 | + private final int termNumber; | ||
22 | + private final int sequenceNumber; | ||
23 | + | ||
24 | + /** | ||
25 | + * Default version tuple. | ||
26 | + * | ||
27 | + * @param id identifier of the element | ||
28 | + * @param termNumber the mastership termNumber | ||
29 | + * @param sequenceNumber the sequenceNumber number within the termNumber | ||
30 | + */ | ||
31 | + public OnosTimestamp(ElementId id, int termNumber, int sequenceNumber) { | ||
32 | + this.id = checkNotNull(id); | ||
33 | + this.termNumber = termNumber; | ||
34 | + this.sequenceNumber = sequenceNumber; | ||
35 | + } | ||
36 | + | ||
37 | + @Override | ||
38 | + public int compareTo(Timestamp o) { | ||
39 | + checkArgument(o instanceof OnosTimestamp, "Must be OnosTimestamp", o); | ||
40 | + OnosTimestamp that = (OnosTimestamp) o; | ||
41 | + checkArgument(this.id.equals(that.id), | ||
42 | + "Cannot compare version for different element this:%s, that:%s", | ||
43 | + this, that); | ||
44 | + | ||
45 | + return ComparisonChain.start() | ||
46 | + .compare(this.termNumber, that.termNumber) | ||
47 | + .compare(this.sequenceNumber, that.sequenceNumber) | ||
48 | + .result(); | ||
49 | + } | ||
50 | + | ||
51 | + @Override | ||
52 | + public int hashCode() { | ||
53 | + return Objects.hash(id, termNumber, sequenceNumber); | ||
54 | + } | ||
55 | + | ||
56 | + @Override | ||
57 | + public boolean equals(Object obj) { | ||
58 | + if (this == obj) { | ||
59 | + return true; | ||
60 | + } | ||
61 | + if (!(obj instanceof OnosTimestamp)) { | ||
62 | + return false; | ||
63 | + } | ||
64 | + OnosTimestamp that = (OnosTimestamp) obj; | ||
65 | + return Objects.equals(this.id, that.id) && | ||
66 | + Objects.equals(this.termNumber, that.termNumber) && | ||
67 | + Objects.equals(this.sequenceNumber, that.sequenceNumber); | ||
68 | + } | ||
69 | + | ||
70 | + @Override | ||
71 | + public String toString() { | ||
72 | + return MoreObjects.toStringHelper(getClass()) | ||
73 | + .add("id", id) | ||
74 | + .add("termNumber", termNumber) | ||
75 | + .add("sequenceNumber", sequenceNumber) | ||
76 | + .toString(); | ||
77 | + } | ||
78 | + | ||
79 | + /** | ||
80 | + * Returns the element. | ||
81 | + * | ||
82 | + * @return element identifier | ||
83 | + */ | ||
84 | + public ElementId id() { | ||
85 | + return id; | ||
86 | + } | ||
87 | + | ||
88 | + /** | ||
89 | + * Returns the termNumber. | ||
90 | + * | ||
91 | + * @return termNumber | ||
92 | + */ | ||
93 | + public int termNumber() { | ||
94 | + return termNumber; | ||
95 | + } | ||
96 | + | ||
97 | + /** | ||
98 | + * Returns the sequenceNumber number. | ||
99 | + * | ||
100 | + * @return sequenceNumber | ||
101 | + */ | ||
102 | + public int sequenceNumber() { | ||
103 | + return sequenceNumber; | ||
104 | + } | ||
105 | +} |
... | @@ -4,7 +4,9 @@ import com.hazelcast.config.Config; | ... | @@ -4,7 +4,9 @@ import com.hazelcast.config.Config; |
4 | import com.hazelcast.config.FileSystemXmlConfig; | 4 | import com.hazelcast.config.FileSystemXmlConfig; |
5 | import com.hazelcast.core.Hazelcast; | 5 | import com.hazelcast.core.Hazelcast; |
6 | import com.hazelcast.core.HazelcastInstance; | 6 | import com.hazelcast.core.HazelcastInstance; |
7 | + | ||
7 | import de.javakaffee.kryoserializers.URISerializer; | 8 | import de.javakaffee.kryoserializers.URISerializer; |
9 | + | ||
8 | import org.apache.felix.scr.annotations.Activate; | 10 | import org.apache.felix.scr.annotations.Activate; |
9 | import org.apache.felix.scr.annotations.Component; | 11 | import org.apache.felix.scr.annotations.Component; |
10 | import org.apache.felix.scr.annotations.Deactivate; | 12 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -26,6 +28,7 @@ import org.onlab.onos.store.serializers.DefaultPortSerializer; | ... | @@ -26,6 +28,7 @@ import org.onlab.onos.store.serializers.DefaultPortSerializer; |
26 | import org.onlab.onos.store.serializers.DeviceIdSerializer; | 28 | import org.onlab.onos.store.serializers.DeviceIdSerializer; |
27 | import org.onlab.onos.store.serializers.IpPrefixSerializer; | 29 | import org.onlab.onos.store.serializers.IpPrefixSerializer; |
28 | import org.onlab.onos.store.serializers.NodeIdSerializer; | 30 | import org.onlab.onos.store.serializers.NodeIdSerializer; |
31 | +import org.onlab.onos.store.serializers.OnosTimestampSerializer; | ||
29 | import org.onlab.onos.store.serializers.PortNumberSerializer; | 32 | import org.onlab.onos.store.serializers.PortNumberSerializer; |
30 | import org.onlab.onos.store.serializers.ProviderIdSerializer; | 33 | import org.onlab.onos.store.serializers.ProviderIdSerializer; |
31 | import org.onlab.packet.IpPrefix; | 34 | import org.onlab.packet.IpPrefix; |
... | @@ -90,6 +93,7 @@ public class StoreManager implements StoreService { | ... | @@ -90,6 +93,7 @@ public class StoreManager implements StoreService { |
90 | .register(DeviceId.class, new DeviceIdSerializer()) | 93 | .register(DeviceId.class, new DeviceIdSerializer()) |
91 | .register(PortNumber.class, new PortNumberSerializer()) | 94 | .register(PortNumber.class, new PortNumberSerializer()) |
92 | .register(DefaultPort.class, new DefaultPortSerializer()) | 95 | .register(DefaultPort.class, new DefaultPortSerializer()) |
96 | + .register(OnosTimestamp.class, new OnosTimestampSerializer()) | ||
93 | .build() | 97 | .build() |
94 | .populate(10); | 98 | .populate(10); |
95 | } | 99 | } | ... | ... |
... | @@ -9,7 +9,6 @@ import com.esotericsoftware.kryo.Serializer; | ... | @@ -9,7 +9,6 @@ import com.esotericsoftware.kryo.Serializer; |
9 | import com.esotericsoftware.kryo.io.Input; | 9 | import com.esotericsoftware.kryo.io.Input; |
10 | import com.esotericsoftware.kryo.io.Output; | 10 | import com.esotericsoftware.kryo.io.Output; |
11 | 11 | ||
12 | -// TODO move to util, etc. | ||
13 | /** | 12 | /** |
14 | * Kryo Serializer for {@link DefaultPort}. | 13 | * Kryo Serializer for {@link DefaultPort}. |
15 | */ | 14 | */ | ... | ... |
... | @@ -9,7 +9,6 @@ import com.esotericsoftware.kryo.Serializer; | ... | @@ -9,7 +9,6 @@ import com.esotericsoftware.kryo.Serializer; |
9 | import com.esotericsoftware.kryo.io.Input; | 9 | import com.esotericsoftware.kryo.io.Input; |
10 | import com.esotericsoftware.kryo.io.Output; | 10 | import com.esotericsoftware.kryo.io.Output; |
11 | 11 | ||
12 | -//TODO move to util, etc. | ||
13 | /** | 12 | /** |
14 | * Kryo Serializer for {@link DeviceId}. | 13 | * Kryo Serializer for {@link DeviceId}. |
15 | */ | 14 | */ | ... | ... |
... | @@ -7,7 +7,6 @@ import com.esotericsoftware.kryo.Serializer; | ... | @@ -7,7 +7,6 @@ import com.esotericsoftware.kryo.Serializer; |
7 | import com.esotericsoftware.kryo.io.Input; | 7 | import com.esotericsoftware.kryo.io.Input; |
8 | import com.esotericsoftware.kryo.io.Output; | 8 | import com.esotericsoftware.kryo.io.Output; |
9 | 9 | ||
10 | -// TODO move to util, etc. | ||
11 | /** | 10 | /** |
12 | * Kryo Serializer for {@link IpPrefix}. | 11 | * Kryo Serializer for {@link IpPrefix}. |
13 | */ | 12 | */ | ... | ... |
1 | +package org.onlab.onos.store.serializers; | ||
2 | + | ||
3 | +import org.onlab.onos.net.ElementId; | ||
4 | +import org.onlab.onos.store.impl.OnosTimestamp; | ||
5 | + | ||
6 | +import com.esotericsoftware.kryo.Kryo; | ||
7 | +import com.esotericsoftware.kryo.Serializer; | ||
8 | +import com.esotericsoftware.kryo.io.Input; | ||
9 | +import com.esotericsoftware.kryo.io.Output; | ||
10 | + | ||
11 | +/** | ||
12 | + * Kryo Serializer for {@link OnosTimestamp}. | ||
13 | + */ | ||
14 | +public class OnosTimestampSerializer extends Serializer<OnosTimestamp> { | ||
15 | + | ||
16 | + /** | ||
17 | + * Default constructor. | ||
18 | + */ | ||
19 | + public OnosTimestampSerializer() { | ||
20 | + // non-null, immutable | ||
21 | + super(false, true); | ||
22 | + } | ||
23 | + @Override | ||
24 | + public void write(Kryo kryo, Output output, OnosTimestamp object) { | ||
25 | + kryo.writeClassAndObject(output, object.id()); | ||
26 | + output.writeInt(object.termNumber()); | ||
27 | + output.writeInt(object.sequenceNumber()); | ||
28 | + } | ||
29 | + | ||
30 | + @Override | ||
31 | + public OnosTimestamp read(Kryo kryo, Input input, Class<OnosTimestamp> type) { | ||
32 | + ElementId id = (ElementId) kryo.readClassAndObject(input); | ||
33 | + final int term = input.readInt(); | ||
34 | + final int sequence = input.readInt(); | ||
35 | + return new OnosTimestamp(id, term, sequence); | ||
36 | + } | ||
37 | +} |
... | @@ -7,7 +7,6 @@ import com.esotericsoftware.kryo.Serializer; | ... | @@ -7,7 +7,6 @@ import com.esotericsoftware.kryo.Serializer; |
7 | import com.esotericsoftware.kryo.io.Input; | 7 | import com.esotericsoftware.kryo.io.Input; |
8 | import com.esotericsoftware.kryo.io.Output; | 8 | import com.esotericsoftware.kryo.io.Output; |
9 | 9 | ||
10 | -// TODO move to util, etc. | ||
11 | /** | 10 | /** |
12 | * Serializer for {@link PortNumber}. | 11 | * Serializer for {@link PortNumber}. |
13 | */ | 12 | */ | ... | ... |
... | @@ -7,7 +7,6 @@ import com.esotericsoftware.kryo.Serializer; | ... | @@ -7,7 +7,6 @@ import com.esotericsoftware.kryo.Serializer; |
7 | import com.esotericsoftware.kryo.io.Input; | 7 | import com.esotericsoftware.kryo.io.Input; |
8 | import com.esotericsoftware.kryo.io.Output; | 8 | import com.esotericsoftware.kryo.io.Output; |
9 | 9 | ||
10 | -//TODO move to util, etc. | ||
11 | /** | 10 | /** |
12 | * Serializer for {@link ProviderId}. | 11 | * Serializer for {@link ProviderId}. |
13 | */ | 12 | */ | ... | ... |
1 | +package org.onlab.onos.openflow.controller.impl; | ||
2 | + | ||
3 | +import java.io.IOException; | ||
4 | +import java.util.List; | ||
5 | + | ||
6 | +import org.jboss.netty.channel.Channel; | ||
7 | +import org.junit.After; | ||
8 | +import org.junit.Before; | ||
9 | +import org.junit.Test; | ||
10 | +import org.onlab.onos.openflow.controller.RoleState; | ||
11 | +import org.onlab.onos.openflow.controller.driver.OpenFlowAgent; | ||
12 | +import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver; | ||
13 | +import org.onlab.onos.openflow.controller.driver.RoleHandler; | ||
14 | +import org.onlab.onos.openflow.controller.driver.RoleRecvStatus; | ||
15 | +import org.onlab.onos.openflow.controller.driver.RoleReplyInfo; | ||
16 | +import org.onlab.onos.openflow.controller.driver.SwitchStateException; | ||
17 | +import org.projectfloodlight.openflow.protocol.OFDescStatsReply; | ||
18 | +import org.projectfloodlight.openflow.protocol.OFErrorMsg; | ||
19 | +import org.projectfloodlight.openflow.protocol.OFFactories; | ||
20 | +import org.projectfloodlight.openflow.protocol.OFFactory; | ||
21 | +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; | ||
22 | +import org.projectfloodlight.openflow.protocol.OFMessage; | ||
23 | +import org.projectfloodlight.openflow.protocol.OFPortDesc; | ||
24 | +import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply; | ||
25 | +import org.projectfloodlight.openflow.protocol.OFVersion; | ||
26 | +import org.projectfloodlight.openflow.types.U64; | ||
27 | + | ||
28 | +import static org.junit.Assert.assertEquals; | ||
29 | +import static org.onlab.onos.openflow.controller.RoleState.*; | ||
30 | +import static org.onlab.onos.openflow.controller.driver.RoleRecvStatus.*; | ||
31 | + | ||
32 | +public class RoleManagerTest { | ||
33 | + | ||
34 | + private static final U64 GID = U64.of(10L); | ||
35 | + private static final long XID = 1L; | ||
36 | + | ||
37 | + private OpenFlowSwitchDriver sw; | ||
38 | + private RoleManager manager; | ||
39 | + | ||
40 | + @Before | ||
41 | + public void setUp() { | ||
42 | + sw = new TestSwitchDriver(); | ||
43 | + manager = new RoleManager(sw); | ||
44 | + } | ||
45 | + | ||
46 | + @After | ||
47 | + public void tearDown() { | ||
48 | + manager = null; | ||
49 | + sw = null; | ||
50 | + } | ||
51 | + | ||
52 | + @Test | ||
53 | + public void deliverRoleReply() { | ||
54 | + RoleRecvStatus status; | ||
55 | + | ||
56 | + RoleReplyInfo asserted = new RoleReplyInfo(MASTER, GID, XID); | ||
57 | + RoleReplyInfo unasserted = new RoleReplyInfo(SLAVE, GID, XID); | ||
58 | + | ||
59 | + try { | ||
60 | + //call without sendRoleReq() for requestPending = false | ||
61 | + //first, sw.role == null | ||
62 | + status = manager.deliverRoleReply(asserted); | ||
63 | + assertEquals("expectation wrong", OTHER_EXPECTATION, status); | ||
64 | + | ||
65 | + sw.setRole(MASTER); | ||
66 | + assertEquals("expectation wrong", OTHER_EXPECTATION, status); | ||
67 | + sw.setRole(SLAVE); | ||
68 | + | ||
69 | + //match to pendingRole = MASTER, requestPending = true | ||
70 | + manager.sendRoleRequest(MASTER, MATCHED_CURRENT_ROLE); | ||
71 | + status = manager.deliverRoleReply(asserted); | ||
72 | + assertEquals("expectation wrong", MATCHED_CURRENT_ROLE, status); | ||
73 | + | ||
74 | + //requestPending never gets reset -- this might be a bug. | ||
75 | + status = manager.deliverRoleReply(unasserted); | ||
76 | + assertEquals("expectation wrong", OTHER_EXPECTATION, status); | ||
77 | + assertEquals("pending role mismatch", MASTER, ((TestSwitchDriver) sw).failed); | ||
78 | + | ||
79 | + } catch (IOException | SwitchStateException e) { | ||
80 | + assertEquals("unexpected error thrown", | ||
81 | + SwitchStateException.class, e.getClass()); | ||
82 | + } | ||
83 | + } | ||
84 | + | ||
85 | + private class TestSwitchDriver implements OpenFlowSwitchDriver { | ||
86 | + | ||
87 | + RoleState failed = null; | ||
88 | + RoleState current = null; | ||
89 | + | ||
90 | + @Override | ||
91 | + public void sendMsg(OFMessage msg) { | ||
92 | + } | ||
93 | + | ||
94 | + @Override | ||
95 | + public void sendMsg(List<OFMessage> msgs) { | ||
96 | + } | ||
97 | + | ||
98 | + @Override | ||
99 | + public void handleMessage(OFMessage fromSwitch) { | ||
100 | + } | ||
101 | + | ||
102 | + @Override | ||
103 | + public void setRole(RoleState role) { | ||
104 | + current = role; | ||
105 | + } | ||
106 | + | ||
107 | + @Override | ||
108 | + public RoleState getRole() { | ||
109 | + return current; | ||
110 | + } | ||
111 | + | ||
112 | + @Override | ||
113 | + public List<OFPortDesc> getPorts() { | ||
114 | + return null; | ||
115 | + } | ||
116 | + | ||
117 | + @Override | ||
118 | + public OFFactory factory() { | ||
119 | + // return what-ever triggers requestPending = true | ||
120 | + return OFFactories.getFactory(OFVersion.OF_10); | ||
121 | + } | ||
122 | + | ||
123 | + @Override | ||
124 | + public String getStringId() { | ||
125 | + return "100"; | ||
126 | + } | ||
127 | + | ||
128 | + @Override | ||
129 | + public long getId() { | ||
130 | + return 0; | ||
131 | + } | ||
132 | + | ||
133 | + @Override | ||
134 | + public String manfacturerDescription() { | ||
135 | + return null; | ||
136 | + } | ||
137 | + | ||
138 | + @Override | ||
139 | + public String datapathDescription() { | ||
140 | + return null; | ||
141 | + } | ||
142 | + | ||
143 | + @Override | ||
144 | + public String hardwareDescription() { | ||
145 | + return null; | ||
146 | + } | ||
147 | + | ||
148 | + @Override | ||
149 | + public String softwareDescription() { | ||
150 | + return null; | ||
151 | + } | ||
152 | + | ||
153 | + @Override | ||
154 | + public String serialNumber() { | ||
155 | + return null; | ||
156 | + } | ||
157 | + | ||
158 | + @Override | ||
159 | + public void disconnectSwitch() { | ||
160 | + } | ||
161 | + | ||
162 | + @Override | ||
163 | + public void returnRoleAssertFailure(RoleState role) { | ||
164 | + failed = role; | ||
165 | + } | ||
166 | + | ||
167 | + @Override | ||
168 | + public void setAgent(OpenFlowAgent agent) { | ||
169 | + } | ||
170 | + | ||
171 | + @Override | ||
172 | + public void setRoleHandler(RoleHandler roleHandler) { | ||
173 | + } | ||
174 | + | ||
175 | + @Override | ||
176 | + public void reassertRole() { | ||
177 | + } | ||
178 | + | ||
179 | + @Override | ||
180 | + public boolean handleRoleError(OFErrorMsg error) { | ||
181 | + return false; | ||
182 | + } | ||
183 | + | ||
184 | + @Override | ||
185 | + public void handleNiciraRole(OFMessage m) throws SwitchStateException { | ||
186 | + } | ||
187 | + | ||
188 | + @Override | ||
189 | + public void handleRole(OFMessage m) throws SwitchStateException { | ||
190 | + } | ||
191 | + | ||
192 | + @Override | ||
193 | + public void startDriverHandshake() { | ||
194 | + } | ||
195 | + | ||
196 | + @Override | ||
197 | + public boolean isDriverHandshakeComplete() { | ||
198 | + return false; | ||
199 | + } | ||
200 | + | ||
201 | + @Override | ||
202 | + public void processDriverHandshakeMessage(OFMessage m) { | ||
203 | + } | ||
204 | + | ||
205 | + @Override | ||
206 | + public boolean connectSwitch() { | ||
207 | + return false; | ||
208 | + } | ||
209 | + | ||
210 | + @Override | ||
211 | + public boolean activateMasterSwitch() { | ||
212 | + return false; | ||
213 | + } | ||
214 | + | ||
215 | + @Override | ||
216 | + public boolean activateEqualSwitch() { | ||
217 | + return false; | ||
218 | + } | ||
219 | + | ||
220 | + @Override | ||
221 | + public void transitionToEqualSwitch() { | ||
222 | + } | ||
223 | + | ||
224 | + @Override | ||
225 | + public void transitionToMasterSwitch() { | ||
226 | + } | ||
227 | + | ||
228 | + @Override | ||
229 | + public void removeConnectedSwitch() { | ||
230 | + } | ||
231 | + | ||
232 | + @Override | ||
233 | + public void setPortDescReply(OFPortDescStatsReply portDescReply) { | ||
234 | + } | ||
235 | + | ||
236 | + @Override | ||
237 | + public void setFeaturesReply(OFFeaturesReply featuresReply) { | ||
238 | + } | ||
239 | + | ||
240 | + @Override | ||
241 | + public void setSwitchDescription(OFDescStatsReply desc) { | ||
242 | + } | ||
243 | + | ||
244 | + @Override | ||
245 | + public int getNextTransactionId() { | ||
246 | + return (int) XID; | ||
247 | + } | ||
248 | + | ||
249 | + @Override | ||
250 | + public Boolean supportNxRole() { | ||
251 | + return true; | ||
252 | + } | ||
253 | + | ||
254 | + @Override | ||
255 | + public void setOFVersion(OFVersion ofV) { | ||
256 | + } | ||
257 | + | ||
258 | + @Override | ||
259 | + public void setTableFull(boolean full) { | ||
260 | + } | ||
261 | + | ||
262 | + @Override | ||
263 | + public void setChannel(Channel channel) { | ||
264 | + } | ||
265 | + | ||
266 | + @Override | ||
267 | + public void setConnected(boolean connected) { | ||
268 | + } | ||
269 | + | ||
270 | + @Override | ||
271 | + public boolean isConnected() { | ||
272 | + return false; | ||
273 | + } | ||
274 | + | ||
275 | + @Override | ||
276 | + public void write(OFMessage msg) { | ||
277 | + } | ||
278 | + | ||
279 | + @Override | ||
280 | + public void write(List<OFMessage> msgs) { | ||
281 | + } | ||
282 | + | ||
283 | + } | ||
284 | +} |
-
Please register or login to post a comment