sangho
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
...@@ -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 }
......