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