Committed by
Pavlin Radoslavov
ONOS-973: Implemented a unit test for OpenFlowGroupProvider implmentation.
- Fixed a bug in OpenFlowGroupProvider of wrong handling of pending group operations. Change-Id: I70b80629f4eed000110d242f3558abe49b6b13bc
Showing
3 changed files
with
65 additions
and
31 deletions
... | @@ -28,7 +28,6 @@ import org.projectfloodlight.openflow.types.OFGroup; | ... | @@ -28,7 +28,6 @@ import org.projectfloodlight.openflow.types.OFGroup; |
28 | import org.slf4j.Logger; | 28 | import org.slf4j.Logger; |
29 | 29 | ||
30 | import java.util.concurrent.TimeUnit; | 30 | import java.util.concurrent.TimeUnit; |
31 | -import java.util.concurrent.atomic.AtomicLong; | ||
32 | 31 | ||
33 | import static org.slf4j.LoggerFactory.getLogger; | 32 | import static org.slf4j.LoggerFactory.getLogger; |
34 | 33 | ||
... | @@ -43,7 +42,6 @@ public class GroupStatsCollector implements TimerTask { | ... | @@ -43,7 +42,6 @@ public class GroupStatsCollector implements TimerTask { |
43 | private final int refreshInterval; | 42 | private final int refreshInterval; |
44 | 43 | ||
45 | private Timeout timeout; | 44 | private Timeout timeout; |
46 | - private final AtomicLong xidCounter = new AtomicLong(1); | ||
47 | 45 | ||
48 | private boolean stopTimer = false; | 46 | private boolean stopTimer = false; |
49 | 47 | ||
... | @@ -79,7 +77,7 @@ public class GroupStatsCollector implements TimerTask { | ... | @@ -79,7 +77,7 @@ public class GroupStatsCollector implements TimerTask { |
79 | if (sw.getRole() != RoleState.MASTER) { | 77 | if (sw.getRole() != RoleState.MASTER) { |
80 | return; | 78 | return; |
81 | } | 79 | } |
82 | - Long statsXid = xidCounter.getAndAdd(2); | 80 | + Long statsXid = OpenFlowGroupProvider.getXidAndAdd(2); |
83 | OFGroupStatsRequest statsRequest = sw.factory().buildGroupStatsRequest() | 81 | OFGroupStatsRequest statsRequest = sw.factory().buildGroupStatsRequest() |
84 | .setGroup(OFGroup.ALL) | 82 | .setGroup(OFGroup.ALL) |
85 | .setXid(statsXid) | 83 | .setXid(statsXid) | ... | ... |
... | @@ -83,12 +83,15 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv | ... | @@ -83,12 +83,15 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv |
83 | 83 | ||
84 | private final InternalGroupProvider listener = new InternalGroupProvider(); | 84 | private final InternalGroupProvider listener = new InternalGroupProvider(); |
85 | 85 | ||
86 | - private final AtomicLong xidCounter = new AtomicLong(1); | 86 | + private static final AtomicLong XID_COUNTER = new AtomicLong(1); |
87 | private final Map<Dpid, GroupStatsCollector> collectors = Maps.newHashMap(); | 87 | private final Map<Dpid, GroupStatsCollector> collectors = Maps.newHashMap(); |
88 | - private final Map<Long, OFStatsReply> groupStats = Maps.newHashMap(); | 88 | + private final Map<Long, OFStatsReply> groupStats = Maps.newConcurrentMap(); |
89 | - private final Map<Long, GroupOperation> pendingGroupOperations = | 89 | + private final Map<Integer, GroupOperation> pendingGroupOperations = |
90 | Maps.newConcurrentMap(); | 90 | Maps.newConcurrentMap(); |
91 | 91 | ||
92 | + /* Map<Group ID, Transaction ID> */ | ||
93 | + private final Map<Integer, Long> pendingXidMaps = Maps.newConcurrentMap(); | ||
94 | + | ||
92 | /** | 95 | /** |
93 | * Creates a OpenFlow group provider. | 96 | * Creates a OpenFlow group provider. |
94 | */ | 97 | */ |
... | @@ -126,10 +129,10 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv | ... | @@ -126,10 +129,10 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv |
126 | OpenFlowSwitch sw = controller.getSwitch(dpid); | 129 | OpenFlowSwitch sw = controller.getSwitch(dpid); |
127 | for (GroupOperation groupOperation: groupOps.operations()) { | 130 | for (GroupOperation groupOperation: groupOps.operations()) { |
128 | if (sw == null) { | 131 | if (sw == null) { |
129 | - log.error("SW {} is not found", sw.getStringId()); | 132 | + log.error("SW {} is not found", dpid); |
130 | return; | 133 | return; |
131 | } | 134 | } |
132 | - final Long groupModXid = xidCounter.getAndIncrement(); | 135 | + final Long groupModXid = XID_COUNTER.getAndIncrement(); |
133 | GroupModBuilder builder = | 136 | GroupModBuilder builder = |
134 | GroupModBuilder.builder(groupOperation.buckets(), | 137 | GroupModBuilder.builder(groupOperation.buckets(), |
135 | groupOperation.groupId(), | 138 | groupOperation.groupId(), |
... | @@ -151,7 +154,9 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv | ... | @@ -151,7 +154,9 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv |
151 | log.error("Unsupported Group operation"); | 154 | log.error("Unsupported Group operation"); |
152 | } | 155 | } |
153 | sw.sendMsg(groupMod); | 156 | sw.sendMsg(groupMod); |
154 | - pendingGroupOperations.put(groupModXid, groupOperation); | 157 | + pendingGroupOperations.put(groupMod.getGroup().getGroupNumber(), |
158 | + groupOperation); | ||
159 | + pendingXidMaps.put(groupMod.getGroup().getGroupNumber(), groupModXid); | ||
155 | } | 160 | } |
156 | } | 161 | } |
157 | 162 | ||
... | @@ -161,23 +166,25 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv | ... | @@ -161,23 +166,25 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv |
161 | OFGroupStatsReply groupStatsReply = null; | 166 | OFGroupStatsReply groupStatsReply = null; |
162 | OFGroupDescStatsReply groupDescStatsReply = null; | 167 | OFGroupDescStatsReply groupDescStatsReply = null; |
163 | 168 | ||
164 | - if (statsReply.getStatsType() == OFStatsType.GROUP) { | 169 | + synchronized (groupStats) { |
165 | - OFStatsReply reply = groupStats.get(statsReply.getXid() + 1); | 170 | + if (statsReply.getStatsType() == OFStatsType.GROUP) { |
166 | - if (reply != null) { | 171 | + OFStatsReply reply = groupStats.get(statsReply.getXid() + 1); |
167 | - groupStatsReply = (OFGroupStatsReply) statsReply; | 172 | + if (reply != null) { |
168 | - groupDescStatsReply = (OFGroupDescStatsReply) reply; | 173 | + groupStatsReply = (OFGroupStatsReply) statsReply; |
169 | - groupStats.remove(statsReply.getXid() + 1); | 174 | + groupDescStatsReply = (OFGroupDescStatsReply) reply; |
170 | - } else { | 175 | + groupStats.remove(statsReply.getXid() + 1); |
171 | - groupStats.put(statsReply.getXid(), statsReply); | 176 | + } else { |
172 | - } | 177 | + groupStats.put(statsReply.getXid(), statsReply); |
173 | - } else if (statsReply.getStatsType() == OFStatsType.GROUP_DESC) { | 178 | + } |
174 | - OFStatsReply reply = groupStats.get(statsReply.getXid() - 1); | 179 | + } else if (statsReply.getStatsType() == OFStatsType.GROUP_DESC) { |
175 | - if (reply != null) { | 180 | + OFStatsReply reply = groupStats.get(statsReply.getXid() - 1); |
176 | - groupStatsReply = (OFGroupStatsReply) reply; | 181 | + if (reply != null) { |
177 | - groupDescStatsReply = (OFGroupDescStatsReply) statsReply; | 182 | + groupStatsReply = (OFGroupStatsReply) reply; |
178 | - groupStats.remove(statsReply.getXid() - 1); | 183 | + groupDescStatsReply = (OFGroupDescStatsReply) statsReply; |
179 | - } else { | 184 | + groupStats.remove(statsReply.getXid() - 1); |
180 | - groupStats.put(statsReply.getXid(), statsReply); | 185 | + } else { |
186 | + groupStats.put(statsReply.getXid(), statsReply); | ||
187 | + } | ||
181 | } | 188 | } |
182 | } | 189 | } |
183 | 190 | ||
... | @@ -187,6 +194,7 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv | ... | @@ -187,6 +194,7 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv |
187 | providerService.pushGroupMetrics(deviceId, groups); | 194 | providerService.pushGroupMetrics(deviceId, groups); |
188 | for (Group group: groups) { | 195 | for (Group group: groups) { |
189 | pendingGroupOperations.remove(group.id()); | 196 | pendingGroupOperations.remove(group.id()); |
197 | + pendingXidMaps.remove(group.id()); | ||
190 | } | 198 | } |
191 | } | 199 | } |
192 | } | 200 | } |
... | @@ -238,6 +246,17 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv | ... | @@ -238,6 +246,17 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv |
238 | return null; | 246 | return null; |
239 | } | 247 | } |
240 | 248 | ||
249 | + /** | ||
250 | + * Returns a transaction ID for entire group operations and increases | ||
251 | + * the counter by the number given. | ||
252 | + * | ||
253 | + * @param increase the amount to increase the counter by | ||
254 | + * @return a transaction ID | ||
255 | + */ | ||
256 | + public static long getXidAndAdd(int increase) { | ||
257 | + return XID_COUNTER.getAndAdd(increase); | ||
258 | + } | ||
259 | + | ||
241 | private class InternalGroupProvider | 260 | private class InternalGroupProvider |
242 | implements OpenFlowSwitchListener, OpenFlowEventListener { | 261 | implements OpenFlowSwitchListener, OpenFlowEventListener { |
243 | 262 | ||
... | @@ -250,11 +269,28 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv | ... | @@ -250,11 +269,28 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv |
250 | case ERROR: | 269 | case ERROR: |
251 | OFErrorMsg errorMsg = (OFErrorMsg) msg; | 270 | OFErrorMsg errorMsg = (OFErrorMsg) msg; |
252 | if (errorMsg.getErrType() == OFErrorType.GROUP_MOD_FAILED) { | 271 | if (errorMsg.getErrType() == OFErrorType.GROUP_MOD_FAILED) { |
253 | - GroupOperation operation = | 272 | + int pendingGroupId = -1; |
254 | - pendingGroupOperations.get(errorMsg.getXid()); | 273 | + for (Map.Entry<Integer, Long> entry: pendingXidMaps.entrySet()) { |
255 | - if (operation != null) { | 274 | + if (entry.getValue() == errorMsg.getXid()) { |
256 | - providerService.groupOperationFailed(operation); | 275 | + pendingGroupId = entry.getKey(); |
257 | - log.warn("received Error message {} from {}", msg, dpid); | 276 | + break; |
277 | + } | ||
278 | + } | ||
279 | + if (pendingGroupId == -1) { | ||
280 | + log.warn("Error for unknown group operation: {}", | ||
281 | + errorMsg.getXid()); | ||
282 | + } else { | ||
283 | + GroupOperation operation = | ||
284 | + pendingGroupOperations.get(pendingGroupId); | ||
285 | + if (operation != null) { | ||
286 | + providerService.groupOperationFailed(operation); | ||
287 | + pendingGroupOperations.remove(pendingGroupId); | ||
288 | + pendingXidMaps.remove(pendingGroupId); | ||
289 | + log.warn("Received an group mod error {}", msg); | ||
290 | + } else { | ||
291 | + log.error("Cannot find pending group operation with group ID: {}", | ||
292 | + pendingGroupId); | ||
293 | + } | ||
258 | } | 294 | } |
259 | break; | 295 | break; |
260 | } | 296 | } | ... | ... |
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment