refactored RoleManager to handle multiple pending requests
Change-Id: I669e0527107c5bd29c1600f4667424bc4e6f6b7e
Showing
2 changed files
with
44 additions
and
43 deletions
... | @@ -300,7 +300,6 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { | ... | @@ -300,7 +300,6 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { |
300 | this.transitionToEqualSwitch(); | 300 | this.transitionToEqualSwitch(); |
301 | } | 301 | } |
302 | } else { | 302 | } else { |
303 | - log.warn(">>> mismatch with expected role - got {} - Disconnecting", r); | ||
304 | this.disconnectSwitch(); | 303 | this.disconnectSwitch(); |
305 | } | 304 | } |
306 | } | 305 | } | ... | ... |
... | @@ -17,6 +17,7 @@ package org.onlab.onos.openflow.controller.impl; | ... | @@ -17,6 +17,7 @@ package org.onlab.onos.openflow.controller.impl; |
17 | 17 | ||
18 | import java.io.IOException; | 18 | import java.io.IOException; |
19 | import java.util.Collections; | 19 | import java.util.Collections; |
20 | +import java.util.concurrent.TimeUnit; | ||
20 | 21 | ||
21 | import org.onlab.onos.openflow.controller.RoleState; | 22 | import org.onlab.onos.openflow.controller.RoleState; |
22 | import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver; | 23 | import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver; |
... | @@ -41,6 +42,9 @@ import org.projectfloodlight.openflow.types.U64; | ... | @@ -41,6 +42,9 @@ import org.projectfloodlight.openflow.types.U64; |
41 | import org.slf4j.Logger; | 42 | import org.slf4j.Logger; |
42 | import org.slf4j.LoggerFactory; | 43 | import org.slf4j.LoggerFactory; |
43 | 44 | ||
45 | +import com.google.common.cache.Cache; | ||
46 | +import com.google.common.cache.CacheBuilder; | ||
47 | + | ||
44 | 48 | ||
45 | /** | 49 | /** |
46 | * A utility class to handle role requests and replies for this channel. | 50 | * A utility class to handle role requests and replies for this channel. |
... | @@ -59,13 +63,15 @@ class RoleManager implements RoleHandler { | ... | @@ -59,13 +63,15 @@ class RoleManager implements RoleHandler { |
59 | protected static final long NICIRA_EXPERIMENTER = 0x2320; | 63 | protected static final long NICIRA_EXPERIMENTER = 0x2320; |
60 | 64 | ||
61 | private static Logger log = LoggerFactory.getLogger(RoleManager.class); | 65 | private static Logger log = LoggerFactory.getLogger(RoleManager.class); |
62 | - // indicates that a request is currently pending | 66 | + |
63 | - // needs to be volatile to allow correct double-check idiom | 67 | + // The time until cached XID is evicted. Arbitray for now. |
64 | - private volatile boolean requestPending; | 68 | + private final int pendingXidTimeoutSeconds = 60; |
65 | - // the transaction Id of the pending request | 69 | + |
66 | - private int pendingXid; | 70 | + // The cache for pending expected RoleReplies keyed on expected XID |
67 | - // the role that's pending | 71 | + private Cache<Integer, RoleState> pendingReplies = |
68 | - private RoleState pendingRole; | 72 | + CacheBuilder.newBuilder() |
73 | + .expireAfterWrite(pendingXidTimeoutSeconds, TimeUnit.SECONDS) | ||
74 | + .build(); | ||
69 | 75 | ||
70 | // the expectation set by the caller for the returned role | 76 | // the expectation set by the caller for the returned role |
71 | private RoleRecvStatus expectation; | 77 | private RoleRecvStatus expectation; |
... | @@ -73,9 +79,6 @@ class RoleManager implements RoleHandler { | ... | @@ -73,9 +79,6 @@ class RoleManager implements RoleHandler { |
73 | 79 | ||
74 | 80 | ||
75 | public RoleManager(OpenFlowSwitchDriver sw) { | 81 | public RoleManager(OpenFlowSwitchDriver sw) { |
76 | - this.requestPending = false; | ||
77 | - this.pendingXid = -1; | ||
78 | - this.pendingRole = null; | ||
79 | this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE; | 82 | this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE; |
80 | this.sw = sw; | 83 | this.sw = sw; |
81 | } | 84 | } |
... | @@ -157,15 +160,11 @@ class RoleManager implements RoleHandler { | ... | @@ -157,15 +160,11 @@ class RoleManager implements RoleHandler { |
157 | } | 160 | } |
158 | // OF1.0 switch with support for NX_ROLE_REQUEST vendor extn. | 161 | // OF1.0 switch with support for NX_ROLE_REQUEST vendor extn. |
159 | // make Role.EQUAL become Role.SLAVE | 162 | // make Role.EQUAL become Role.SLAVE |
160 | - pendingRole = role; | 163 | + RoleState roleToSend = (role == RoleState.EQUAL) ? RoleState.SLAVE : role; |
161 | - role = (role == RoleState.EQUAL) ? RoleState.SLAVE : role; | 164 | + pendingReplies.put(sendNxRoleRequest(roleToSend), role); |
162 | - pendingXid = sendNxRoleRequest(role); | ||
163 | - requestPending = true; | ||
164 | } else { | 165 | } else { |
165 | // OF1.3 switch, use OFPT_ROLE_REQUEST message | 166 | // OF1.3 switch, use OFPT_ROLE_REQUEST message |
166 | - pendingXid = sendOF13RoleRequest(role); | 167 | + pendingReplies.put(sendOF13RoleRequest(role), role); |
167 | - pendingRole = role; | ||
168 | - requestPending = true; | ||
169 | } | 168 | } |
170 | return true; | 169 | return true; |
171 | } | 170 | } |
... | @@ -192,12 +191,17 @@ class RoleManager implements RoleHandler { | ... | @@ -192,12 +191,17 @@ class RoleManager implements RoleHandler { |
192 | @Override | 191 | @Override |
193 | public synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri) | 192 | public synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri) |
194 | throws SwitchStateException { | 193 | throws SwitchStateException { |
195 | - if (!requestPending) { | 194 | + int xid = (int) rri.getXid(); |
195 | + RoleState receivedRole = rri.getRole(); | ||
196 | + RoleState expectedRole = pendingReplies.getIfPresent(xid); | ||
197 | + | ||
198 | + if (expectedRole == null) { | ||
196 | RoleState currentRole = (sw != null) ? sw.getRole() : null; | 199 | RoleState currentRole = (sw != null) ? sw.getRole() : null; |
197 | if (currentRole != null) { | 200 | if (currentRole != null) { |
198 | if (currentRole == rri.getRole()) { | 201 | if (currentRole == rri.getRole()) { |
199 | // Don't disconnect if the role reply we received is | 202 | // Don't disconnect if the role reply we received is |
200 | // for the same role we are already in. | 203 | // for the same role we are already in. |
204 | + // FIXME: but we do from the caller anyways. | ||
201 | log.debug("Received unexpected RoleReply from " | 205 | log.debug("Received unexpected RoleReply from " |
202 | + "Switch: {}. " | 206 | + "Switch: {}. " |
203 | + "Role in reply is same as current role of this " | 207 | + "Role in reply is same as current role of this " |
... | @@ -223,26 +227,24 @@ class RoleManager implements RoleHandler { | ... | @@ -223,26 +227,24 @@ class RoleManager implements RoleHandler { |
223 | return RoleRecvStatus.OTHER_EXPECTATION; | 227 | return RoleRecvStatus.OTHER_EXPECTATION; |
224 | } | 228 | } |
225 | 229 | ||
226 | - int xid = (int) rri.getXid(); | ||
227 | - RoleState receivedRole = rri.getRole(); | ||
228 | // XXX Should check generation id meaningfully and other cases of expectations | 230 | // XXX Should check generation id meaningfully and other cases of expectations |
229 | - | 231 | + //if (pendingXid != xid) { |
230 | - if (pendingXid != xid) { | 232 | + // log.info("Received older role reply from " + |
231 | - log.debug("Received older role reply from " + | 233 | + // "switch {} ({}). Ignoring. " + |
232 | - "switch {} ({}). Ignoring. " + | 234 | + // "Waiting for {}, xid={}", |
233 | - "Waiting for {}, xid={}", | 235 | + // new Object[] {sw.getStringId(), rri, |
234 | - new Object[] {sw.getStringId(), rri, | 236 | + // pendingRole, pendingXid }); |
235 | - pendingRole, pendingXid }); | 237 | + // return RoleRecvStatus.OLD_REPLY; |
236 | - return RoleRecvStatus.OLD_REPLY; | 238 | + //} |
237 | - } | 239 | + sw.returnRoleReply(expectedRole, receivedRole); |
238 | - | 240 | + |
239 | - sw.returnRoleReply(pendingRole, receivedRole); | 241 | + if (expectedRole == receivedRole) { |
240 | - | ||
241 | - if (pendingRole == receivedRole) { | ||
242 | log.debug("Received role reply message from {} that matched " | 242 | log.debug("Received role reply message from {} that matched " |
243 | + "expected role-reply {} with expectations {}", | 243 | + "expected role-reply {} with expectations {}", |
244 | new Object[] {sw.getStringId(), receivedRole, expectation}); | 244 | new Object[] {sw.getStringId(), receivedRole, expectation}); |
245 | 245 | ||
246 | + // Done with this RoleReply; Invalidate | ||
247 | + pendingReplies.invalidate(xid); | ||
246 | if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE || | 248 | if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE || |
247 | expectation == RoleRecvStatus.MATCHED_SET_ROLE) { | 249 | expectation == RoleRecvStatus.MATCHED_SET_ROLE) { |
248 | return expectation; | 250 | return expectation; |
... | @@ -251,6 +253,7 @@ class RoleManager implements RoleHandler { | ... | @@ -251,6 +253,7 @@ class RoleManager implements RoleHandler { |
251 | } | 253 | } |
252 | } | 254 | } |
253 | 255 | ||
256 | + pendingReplies.invalidate(xid); | ||
254 | // if xids match but role's don't, perhaps its a query (OF1.3) | 257 | // if xids match but role's don't, perhaps its a query (OF1.3) |
255 | if (expectation == RoleRecvStatus.REPLY_QUERY) { | 258 | if (expectation == RoleRecvStatus.REPLY_QUERY) { |
256 | return expectation; | 259 | return expectation; |
... | @@ -270,18 +273,17 @@ class RoleManager implements RoleHandler { | ... | @@ -270,18 +273,17 @@ class RoleManager implements RoleHandler { |
270 | @Override | 273 | @Override |
271 | public synchronized RoleRecvStatus deliverError(OFErrorMsg error) | 274 | public synchronized RoleRecvStatus deliverError(OFErrorMsg error) |
272 | throws SwitchStateException { | 275 | throws SwitchStateException { |
273 | - if (!requestPending) { | 276 | + RoleState errorRole = pendingReplies.getIfPresent(error.getXid()); |
274 | - log.debug("Received an error msg from sw {}, but no pending " | 277 | + if (errorRole == null) { |
275 | - + "requests in role-changer; not handling ...", | ||
276 | - sw.getStringId()); | ||
277 | - return RoleRecvStatus.OTHER_EXPECTATION; | ||
278 | - } | ||
279 | - if (pendingXid != error.getXid()) { | ||
280 | if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) { | 278 | if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) { |
281 | log.debug("Received an error msg from sw {} for a role request," | 279 | log.debug("Received an error msg from sw {} for a role request," |
282 | + " but not for pending request in role-changer; " | 280 | + " but not for pending request in role-changer; " |
283 | + " ignoring error {} ...", | 281 | + " ignoring error {} ...", |
284 | sw.getStringId(), error); | 282 | sw.getStringId(), error); |
283 | + } else { | ||
284 | + log.debug("Received an error msg from sw {}, but no pending " | ||
285 | + + "requests in role-changer; not handling ...", | ||
286 | + sw.getStringId()); | ||
285 | } | 287 | } |
286 | return RoleRecvStatus.OTHER_EXPECTATION; | 288 | return RoleRecvStatus.OTHER_EXPECTATION; |
287 | } | 289 | } |
... | @@ -292,7 +294,7 @@ class RoleManager implements RoleHandler { | ... | @@ -292,7 +294,7 @@ class RoleManager implements RoleHandler { |
292 | + "role-messaging is supported. Possible issues in " | 294 | + "role-messaging is supported. Possible issues in " |
293 | + "switch driver configuration?", new Object[] { | 295 | + "switch driver configuration?", new Object[] { |
294 | ((OFBadRequestErrorMsg) error).toString(), | 296 | ((OFBadRequestErrorMsg) error).toString(), |
295 | - sw.getStringId(), pendingRole | 297 | + sw.getStringId(), errorRole |
296 | }); | 298 | }); |
297 | return RoleRecvStatus.UNSUPPORTED; | 299 | return RoleRecvStatus.UNSUPPORTED; |
298 | } | 300 | } |
... | @@ -316,7 +318,7 @@ class RoleManager implements RoleHandler { | ... | @@ -316,7 +318,7 @@ class RoleManager implements RoleHandler { |
316 | + "received Error to for pending role request [%s]. " | 318 | + "received Error to for pending role request [%s]. " |
317 | + "Error:[%s]. Disconnecting switch ... ", | 319 | + "Error:[%s]. Disconnecting switch ... ", |
318 | sw.getStringId(), | 320 | sw.getStringId(), |
319 | - pendingRole, rrerr); | 321 | + errorRole, rrerr); |
320 | throw new SwitchStateException(msgx); | 322 | throw new SwitchStateException(msgx); |
321 | default: | 323 | default: |
322 | break; | 324 | break; | ... | ... |
-
Please register or login to post a comment