Srikanth Vavilapalli
Committed by Gerrit Code Review

ONOS-885: Group store interface definition and in-memory store implementation

Change-Id: I1125fbc23f1e58bcb8aaf5f67c02da610fa7ef25

ONOS-885: Group store interface definition and in-memory store implementation

Change-Id: Id3794bed63785e10ed86c0b5d90bf875d127224c
Showing 21 changed files with 1130 additions and 69 deletions
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.group;
17 +
18 +import static org.slf4j.LoggerFactory.getLogger;
19 +
20 +import org.onosproject.core.GroupId;
21 +import org.slf4j.Logger;
22 +
23 +/**
24 + * ONOS implementation of default group that is stored in the system.
25 + */
26 +public class DefaultGroup extends DefaultGroupDescription
27 + implements Group, StoredGroupEntry {
28 +
29 + private final Logger log = getLogger(getClass());
30 +
31 + private GroupState state;
32 + private long life;
33 + private long packets;
34 + private long bytes;
35 + private GroupId id;
36 +
37 + /**
38 + * Default group object constructor with the parameters.
39 + *
40 + * @param id group identifier
41 + * @param groupDesc group description parameters
42 + */
43 + public DefaultGroup(GroupId id, GroupDescription groupDesc) {
44 + super(groupDesc);
45 + this.id = id;
46 + this.state = GroupState.PENDING_ADD;
47 + this.life = 0;
48 + this.packets = 0;
49 + this.bytes = 0;
50 + }
51 +
52 + /**
53 + * Returns group identifier associated with a group object.
54 + *
55 + * @return GroupId Group Identifier
56 + */
57 + @Override
58 + public GroupId id() {
59 + return this.id;
60 + }
61 +
62 + /**
63 + * Returns current state of a group object.
64 + *
65 + * @return GroupState Group State
66 + */
67 + @Override
68 + public GroupState state() {
69 + return this.state;
70 + }
71 +
72 + /**
73 + * Returns the number of milliseconds this group has been alive.
74 + *
75 + * @return number of millis
76 + */
77 + @Override
78 + public long life() {
79 + return this.life;
80 + }
81 +
82 + /**
83 + * Returns the number of packets processed by this group.
84 + *
85 + * @return number of packets
86 + */
87 + @Override
88 + public long packets() {
89 + return this.packets;
90 + }
91 +
92 + /**
93 + * Returns the number of bytes processed by this group.
94 + *
95 + * @return number of bytes
96 + */
97 + @Override
98 + public long bytes() {
99 + return this.bytes;
100 + }
101 +
102 + /**
103 + * Sets the new state for this entry.
104 + *
105 + * @param newState new group entry state.
106 + */
107 + @Override
108 + public void setState(Group.GroupState newState) {
109 + this.state = newState;
110 + }
111 +
112 + /**
113 + * Sets how long this entry has been entered in the system.
114 + *
115 + * @param life epoch time
116 + */
117 + @Override
118 + public void setLife(long life) {
119 + this.life = life;
120 + }
121 +
122 + /**
123 + * Sets number of packets processed by this group entry.
124 + *
125 + * @param packets a long value
126 + */
127 + @Override
128 + public void setPackets(long packets) {
129 + this.packets = packets;
130 + }
131 +
132 + /**
133 + * Sets number of bytes processed by this group entry.
134 + *
135 + * @param bytes a long value
136 + */
137 + @Override
138 + public void setBytes(long bytes) {
139 + this.bytes = bytes;
140 + }
141 +
142 +}
...@@ -15,12 +15,12 @@ ...@@ -15,12 +15,12 @@
15 */ 15 */
16 package org.onosproject.net.group; 16 package org.onosproject.net.group;
17 17
18 -import static com.google.common.base.Preconditions.checkNotNull;
19 import static com.google.common.base.Preconditions.checkArgument; 18 import static com.google.common.base.Preconditions.checkArgument;
19 +import static com.google.common.base.Preconditions.checkNotNull;
20 20
21 +import org.onosproject.core.GroupId;
21 import org.onosproject.net.PortNumber; 22 import org.onosproject.net.PortNumber;
22 import org.onosproject.net.flow.TrafficTreatment; 23 import org.onosproject.net.flow.TrafficTreatment;
23 -import org.onosproject.core.GroupId;
24 24
25 /** 25 /**
26 * Group bucket implementation. A group bucket is collection of 26 * Group bucket implementation. A group bucket is collection of
...@@ -65,7 +65,6 @@ public final class DefaultGroupBucket implements GroupBucket { ...@@ -65,7 +65,6 @@ public final class DefaultGroupBucket implements GroupBucket {
65 * Creates indirect group bucket. 65 * Creates indirect group bucket.
66 * 66 *
67 * @param treatment traffic treatment associated with group bucket 67 * @param treatment traffic treatment associated with group bucket
68 - *
69 * @return indirect group bucket object 68 * @return indirect group bucket object
70 */ 69 */
71 public static GroupBucket createIndirectGroupBucket( 70 public static GroupBucket createIndirectGroupBucket(
...@@ -81,7 +80,6 @@ public final class DefaultGroupBucket implements GroupBucket { ...@@ -81,7 +80,6 @@ public final class DefaultGroupBucket implements GroupBucket {
81 * Creates select group bucket with weight as 1. 80 * Creates select group bucket with weight as 1.
82 * 81 *
83 * @param treatment traffic treatment associated with group bucket 82 * @param treatment traffic treatment associated with group bucket
84 - *
85 * @return select group bucket object 83 * @return select group bucket object
86 */ 84 */
87 public static GroupBucket createSelectGroupBucket( 85 public static GroupBucket createSelectGroupBucket(
...@@ -98,7 +96,6 @@ public final class DefaultGroupBucket implements GroupBucket { ...@@ -98,7 +96,6 @@ public final class DefaultGroupBucket implements GroupBucket {
98 * 96 *
99 * @param treatment traffic treatment associated with group bucket 97 * @param treatment traffic treatment associated with group bucket
100 * @param weight weight associated with group bucket 98 * @param weight weight associated with group bucket
101 - *
102 * @return select group bucket object 99 * @return select group bucket object
103 */ 100 */
104 public static GroupBucket createSelectGroupBucket( 101 public static GroupBucket createSelectGroupBucket(
...@@ -121,7 +118,6 @@ public final class DefaultGroupBucket implements GroupBucket { ...@@ -121,7 +118,6 @@ public final class DefaultGroupBucket implements GroupBucket {
121 * @param treatment traffic treatment associated with group bucket 118 * @param treatment traffic treatment associated with group bucket
122 * @param watchPort port that determines the liveness of group bucket 119 * @param watchPort port that determines the liveness of group bucket
123 * @param watchGroup group that determines the liveness of group bucket 120 * @param watchGroup group that determines the liveness of group bucket
124 - *
125 * @return failover group bucket object 121 * @return failover group bucket object
126 */ 122 */
127 public static GroupBucket createFailoverGroupBucket( 123 public static GroupBucket createFailoverGroupBucket(
...@@ -142,7 +138,7 @@ public final class DefaultGroupBucket implements GroupBucket { ...@@ -142,7 +138,7 @@ public final class DefaultGroupBucket implements GroupBucket {
142 } 138 }
143 139
144 /** 140 /**
145 - * Return list of Traffic instructions that are part of the bucket. 141 + * Returns list of Traffic instructions that are part of the bucket.
146 * 142 *
147 * @return TrafficTreatment Traffic instruction list 143 * @return TrafficTreatment Traffic instruction list
148 */ 144 */
...@@ -152,7 +148,7 @@ public final class DefaultGroupBucket implements GroupBucket { ...@@ -152,7 +148,7 @@ public final class DefaultGroupBucket implements GroupBucket {
152 } 148 }
153 149
154 /** 150 /**
155 - * Return weight of select group bucket. 151 + * Returns weight of select group bucket.
156 * 152 *
157 * @return short weight associated with a bucket 153 * @return short weight associated with a bucket
158 */ 154 */
...@@ -162,7 +158,7 @@ public final class DefaultGroupBucket implements GroupBucket { ...@@ -162,7 +158,7 @@ public final class DefaultGroupBucket implements GroupBucket {
162 } 158 }
163 159
164 /** 160 /**
165 - * Return port number used for liveness detection for a 161 + * Returns port number used for liveness detection for a
166 * failover bucket. 162 * failover bucket.
167 * 163 *
168 * @return PortNumber port number used for liveness detection 164 * @return PortNumber port number used for liveness detection
...@@ -173,7 +169,7 @@ public final class DefaultGroupBucket implements GroupBucket { ...@@ -173,7 +169,7 @@ public final class DefaultGroupBucket implements GroupBucket {
173 } 169 }
174 170
175 /** 171 /**
176 - * Return group identifier used for liveness detection for a 172 + * Returns group identifier used for liveness detection for a
177 * failover bucket. 173 * failover bucket.
178 * 174 *
179 * @return GroupId group identifier to be used for liveness detection 175 * @return GroupId group identifier to be used for liveness detection
......
...@@ -20,6 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -20,6 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
20 import org.onosproject.core.ApplicationId; 20 import org.onosproject.core.ApplicationId;
21 import org.onosproject.net.DeviceId; 21 import org.onosproject.net.DeviceId;
22 22
23 +/**
24 + * Default implementation of group description interface.
25 + */
23 public class DefaultGroupDescription implements GroupDescription { 26 public class DefaultGroupDescription implements GroupDescription {
24 private final GroupDescription.Type type; 27 private final GroupDescription.Type type;
25 private final GroupBuckets buckets; 28 private final GroupBuckets buckets;
...@@ -28,15 +31,15 @@ public class DefaultGroupDescription implements GroupDescription { ...@@ -28,15 +31,15 @@ public class DefaultGroupDescription implements GroupDescription {
28 private final DeviceId deviceId; 31 private final DeviceId deviceId;
29 32
30 /** 33 /**
34 + * Constructor to be used by north bound applications.
35 + * NOTE: The caller of this subsystem MUST ensure the appCookie
36 + * provided in this API is immutable
31 * 37 *
32 * @param deviceId device identifier 38 * @param deviceId device identifier
33 * @param type type of the group 39 * @param type type of the group
34 * @param buckets immutable list of group bucket 40 * @param buckets immutable list of group bucket
35 * @param appCookie immutable application cookie to be associated with the group 41 * @param appCookie immutable application cookie to be associated with the group
36 * @param appId application id 42 * @param appId application id
37 - *
38 - * NOTE: The caller of this subsystem MUST ensure the appCookie
39 - * provided in this API is immutable
40 */ 43 */
41 public DefaultGroupDescription(DeviceId deviceId, 44 public DefaultGroupDescription(DeviceId deviceId,
42 GroupDescription.Type type, 45 GroupDescription.Type type,
...@@ -51,7 +54,22 @@ public class DefaultGroupDescription implements GroupDescription { ...@@ -51,7 +54,22 @@ public class DefaultGroupDescription implements GroupDescription {
51 } 54 }
52 55
53 /** 56 /**
54 - * Return type of a group object. 57 + * Constructor to be used by group subsystem internal components.
58 + * Creates group description object from another object of same type.
59 + *
60 + * @param groupDesc group description object
61 + *
62 + */
63 + public DefaultGroupDescription(GroupDescription groupDesc) {
64 + this.type = checkNotNull(groupDesc.type());
65 + this.deviceId = checkNotNull(groupDesc.deviceId());
66 + this.buckets = checkNotNull(groupDesc.buckets());
67 + this.appCookie = checkNotNull(groupDesc.appCookie());
68 + this.appId = checkNotNull(groupDesc.appId());
69 + }
70 +
71 + /**
72 + * Returns type of a group object.
55 * 73 *
56 * @return GroupType group type 74 * @return GroupType group type
57 */ 75 */
...@@ -61,7 +79,7 @@ public class DefaultGroupDescription implements GroupDescription { ...@@ -61,7 +79,7 @@ public class DefaultGroupDescription implements GroupDescription {
61 } 79 }
62 80
63 /** 81 /**
64 - * Return device identifier on which this group object is created. 82 + * Returns device identifier on which this group object is created.
65 * 83 *
66 * @return DeviceId device identifier 84 * @return DeviceId device identifier
67 */ 85 */
...@@ -71,7 +89,7 @@ public class DefaultGroupDescription implements GroupDescription { ...@@ -71,7 +89,7 @@ public class DefaultGroupDescription implements GroupDescription {
71 } 89 }
72 90
73 /** 91 /**
74 - * Return application identifier that has created this group object. 92 + * Returns application identifier that has created this group object.
75 * 93 *
76 * @return ApplicationId application identifier 94 * @return ApplicationId application identifier
77 */ 95 */
...@@ -81,7 +99,7 @@ public class DefaultGroupDescription implements GroupDescription { ...@@ -81,7 +99,7 @@ public class DefaultGroupDescription implements GroupDescription {
81 } 99 }
82 100
83 /** 101 /**
84 - * Return application cookie associated with a group object. 102 + * Returns application cookie associated with a group object.
85 * 103 *
86 * @return GroupKey application cookie 104 * @return GroupKey application cookie
87 */ 105 */
...@@ -91,7 +109,7 @@ public class DefaultGroupDescription implements GroupDescription { ...@@ -91,7 +109,7 @@ public class DefaultGroupDescription implements GroupDescription {
91 } 109 }
92 110
93 /** 111 /**
94 - * Return group buckets of a group. 112 + * Returns group buckets of a group.
95 * 113 *
96 * @return GroupBuckets immutable list of group bucket 114 * @return GroupBuckets immutable list of group bucket
97 */ 115 */
......
...@@ -23,35 +23,43 @@ import org.onosproject.core.GroupId; ...@@ -23,35 +23,43 @@ import org.onosproject.core.GroupId;
23 public interface Group extends GroupDescription { 23 public interface Group extends GroupDescription {
24 /** 24 /**
25 * State of the group object in ONOS. 25 * State of the group object in ONOS.
26 - * PENDING_ADD: group create request is processed by ONOS and
27 - * not yet received the confirmation from data plane
28 - * ADDED: group is created in the data plane
29 - * PENDING_UPDATE: group update request is processed by ONOS and
30 - * not received the confirmation from data plane post which state
31 - * moves to ADDED state
32 - * PENDING_DELETE: group delete request is processed by ONOS and
33 - * not received the confirmation from data plane
34 */ 26 */
35 public enum GroupState { 27 public enum GroupState {
28 + /**
29 + * Group create request is processed by ONOS and not yet
30 + * received the confirmation from data plane.
31 + */
36 PENDING_ADD, 32 PENDING_ADD,
33 + /**
34 + * Group is created in the data plane.
35 + */
37 ADDED, 36 ADDED,
37 + /**
38 + * Group update request is processed by ONOS and not
39 + * received the confirmation from data plane post which
40 + * state moves to ADDED state.
41 + */
38 PENDING_UPDATE, 42 PENDING_UPDATE,
43 + /**
44 + * Group delete request is processed by ONOS and not
45 + * received the confirmation from data plane.
46 + */
39 PENDING_DELETE 47 PENDING_DELETE
40 } 48 }
41 49
42 /** 50 /**
43 - * Return group identifier associated with a group object. 51 + * Returns group identifier associated with a group object.
44 * 52 *
45 * @return GroupId Group Identifier 53 * @return GroupId Group Identifier
46 */ 54 */
47 - public GroupId id(); 55 + GroupId id();
48 56
49 /** 57 /**
50 - * Return current state of a group object. 58 + * Returns current state of a group object.
51 * 59 *
52 * @return GroupState Group State 60 * @return GroupState Group State
53 */ 61 */
54 - public GroupState state(); 62 + GroupState state();
55 63
56 /** 64 /**
57 * Returns the number of milliseconds this group has been alive. 65 * Returns the number of milliseconds this group has been alive.
......
...@@ -15,11 +15,12 @@ ...@@ -15,11 +15,12 @@
15 */ 15 */
16 package org.onosproject.net.group; 16 package org.onosproject.net.group;
17 17
18 +import org.onosproject.core.GroupId;
18 import org.onosproject.net.PortNumber; 19 import org.onosproject.net.PortNumber;
19 import org.onosproject.net.flow.TrafficTreatment; 20 import org.onosproject.net.flow.TrafficTreatment;
20 -import org.onosproject.core.GroupId;
21 21
22 -/* Group Bucket definition. A default group Bucket is collection of 22 +/**
23 + * Group Bucket definition. A default group Bucket is collection of
23 * Instructions that can be performed on a traffic flow. A failover 24 * Instructions that can be performed on a traffic flow. A failover
24 * group bucket is associated with a specific port or group that 25 * group bucket is associated with a specific port or group that
25 * controls its liveness. A select group bucket contains optional 26 * controls its liveness. A select group bucket contains optional
...@@ -27,28 +28,28 @@ import org.onosproject.core.GroupId; ...@@ -27,28 +28,28 @@ import org.onosproject.core.GroupId;
27 */ 28 */
28 public interface GroupBucket { 29 public interface GroupBucket {
29 /** 30 /**
30 - * Return group type of the bucket. 31 + * Returns group type of the bucket.
31 * 32 *
32 * @return GroupType group type 33 * @return GroupType group type
33 */ 34 */
34 public GroupDescription.Type type(); 35 public GroupDescription.Type type();
35 36
36 /** 37 /**
37 - * Return list of Traffic instructions that are part of the bucket. 38 + * Returns list of Traffic instructions that are part of the bucket.
38 * 39 *
39 * @return TrafficTreatment traffic instruction list 40 * @return TrafficTreatment traffic instruction list
40 */ 41 */
41 public TrafficTreatment treatment(); 42 public TrafficTreatment treatment();
42 43
43 /** 44 /**
44 - * Return weight of select group bucket. 45 + * Returns weight of select group bucket.
45 * 46 *
46 * @return short weight associated with a bucket 47 * @return short weight associated with a bucket
47 */ 48 */
48 public short weight(); 49 public short weight();
49 50
50 /** 51 /**
51 - * Return port number used for liveness detection for a 52 + * Returns port number used for liveness detection for a
52 * failover bucket. 53 * failover bucket.
53 * 54 *
54 * @return PortNumber port number used for liveness detection 55 * @return PortNumber port number used for liveness detection
...@@ -56,7 +57,7 @@ public interface GroupBucket { ...@@ -56,7 +57,7 @@ public interface GroupBucket {
56 public PortNumber watchPort(); 57 public PortNumber watchPort();
57 58
58 /** 59 /**
59 - * Return group identifier used for liveness detection for a 60 + * Returns group identifier used for liveness detection for a
60 * failover bucket. 61 * failover bucket.
61 * 62 *
62 * @return GroupId group identifier to be used for liveness detection 63 * @return GroupId group identifier to be used for liveness detection
......
...@@ -15,20 +15,21 @@ ...@@ -15,20 +15,21 @@
15 */ 15 */
16 package org.onosproject.net.group; 16 package org.onosproject.net.group;
17 17
18 -/* Generic group bucket entry representation that is stored in a 18 +/**
19 + * Generic group bucket entry representation that is stored in a
19 * group object. A group bucket entry provides additional info of 20 * group object. A group bucket entry provides additional info of
20 * group bucket like statistics...etc 21 * group bucket like statistics...etc
21 */ 22 */
22 public interface GroupBucketEntry extends GroupBucket { 23 public interface GroupBucketEntry extends GroupBucket {
23 /** 24 /**
24 - * Return Number of packets processed by bucket. 25 + * Returns Number of packets processed by bucket.
25 * 26 *
26 * @return long 27 * @return long
27 */ 28 */
28 public long packets(); 29 public long packets();
29 30
30 /** 31 /**
31 - * Return Number of bytes processed by bucket. 32 + * Returns Number of bytes processed by bucket.
32 * 33 *
33 * @return long 34 * @return long
34 */ 35 */
......
...@@ -19,9 +19,11 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -19,9 +19,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
19 19
20 import java.util.List; 20 import java.util.List;
21 21
22 -
23 import com.google.common.collect.ImmutableList; 22 import com.google.common.collect.ImmutableList;
24 23
24 +/**
25 + * Immutable collection of group bucket.
26 + */
25 public final class GroupBuckets { 27 public final class GroupBuckets {
26 private final List<GroupBucket> buckets; 28 private final List<GroupBucket> buckets;
27 29
...@@ -35,7 +37,7 @@ public final class GroupBuckets { ...@@ -35,7 +37,7 @@ public final class GroupBuckets {
35 } 37 }
36 38
37 /** 39 /**
38 - * Immutable list of group buckets. 40 + * Returns immutable list of group buckets.
39 * 41 *
40 * @return list of group bucket 42 * @return list of group bucket
41 */ 43 */
......
...@@ -47,35 +47,35 @@ public interface GroupDescription { ...@@ -47,35 +47,35 @@ public interface GroupDescription {
47 } 47 }
48 48
49 /** 49 /**
50 - * Return type of a group object. 50 + * Returns type of a group object.
51 * 51 *
52 * @return GroupType group type 52 * @return GroupType group type
53 */ 53 */
54 public Type type(); 54 public Type type();
55 55
56 /** 56 /**
57 - * Return device identifier on which this group object is created. 57 + * Returns device identifier on which this group object is created.
58 * 58 *
59 * @return DeviceId device identifier 59 * @return DeviceId device identifier
60 */ 60 */
61 public DeviceId deviceId(); 61 public DeviceId deviceId();
62 62
63 /** 63 /**
64 - * Return application identifier that has created this group object. 64 + * Returns application identifier that has created this group object.
65 * 65 *
66 * @return ApplicationId application identifier 66 * @return ApplicationId application identifier
67 */ 67 */
68 public ApplicationId appId(); 68 public ApplicationId appId();
69 69
70 /** 70 /**
71 - * Return application cookie associated with a group object. 71 + * Returns application cookie associated with a group object.
72 * 72 *
73 * @return GroupKey application cookie 73 * @return GroupKey application cookie
74 */ 74 */
75 public GroupKey appCookie(); 75 public GroupKey appCookie();
76 76
77 /** 77 /**
78 - * Return group buckets of a group. 78 + * Returns group buckets of a group.
79 * 79 *
80 * @return GroupBuckets immutable list of group bucket 80 * @return GroupBuckets immutable list of group bucket
81 */ 81 */
......
...@@ -18,7 +18,7 @@ package org.onosproject.net.group; ...@@ -18,7 +18,7 @@ package org.onosproject.net.group;
18 import org.onosproject.event.AbstractEvent; 18 import org.onosproject.event.AbstractEvent;
19 19
20 /** 20 /**
21 - * Describes flow rule event. 21 + * Describes group events.
22 */ 22 */
23 public class GroupEvent extends AbstractEvent<GroupEvent.Type, Group> { 23 public class GroupEvent extends AbstractEvent<GroupEvent.Type, Group> {
24 24
...@@ -48,6 +48,10 @@ public class GroupEvent extends AbstractEvent<GroupEvent.Type, Group> { ...@@ -48,6 +48,10 @@ public class GroupEvent extends AbstractEvent<GroupEvent.Type, Group> {
48 */ 48 */
49 GROUP_ADD_REQUESTED, 49 GROUP_ADD_REQUESTED,
50 /* 50 /*
51 + * Signifies that a request to update Group has been added to the store.
52 + */
53 + GROUP_UPDATE_REQUESTED,
54 + /*
51 * Signifies that a request to delete Group has been added to the store. 55 * Signifies that a request to delete Group has been added to the store.
52 */ 56 */
53 GROUP_REMOVE_REQUESTED, 57 GROUP_REMOVE_REQUESTED,
......
...@@ -15,8 +15,9 @@ ...@@ -15,8 +15,9 @@
15 */ 15 */
16 package org.onosproject.net.group; 16 package org.onosproject.net.group;
17 17
18 -/* Representation of generalized Key that would be used to store 18 +/**
19 - * groups in <Key, Value> store. Implementation of this interface 19 + * Representation of generalized Key that would be used to store
20 + * groups in &lt; Key, Value &gt; store. Implementation of this interface
20 * MUST override "equals()" and "hashcode()" methods. 21 * MUST override "equals()" and "hashcode()" methods.
21 */ 22 */
22 public interface GroupKey { 23 public interface GroupKey {
......
...@@ -19,6 +19,11 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -19,6 +19,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
19 19
20 import org.onosproject.core.GroupId; 20 import org.onosproject.core.GroupId;
21 21
22 +/**
23 + * Group operation definition to be used between core and provider
24 + * layers of group subsystem.
25 + *
26 + */
22 public final class GroupOperation { 27 public final class GroupOperation {
23 private final Type opType; 28 private final Type opType;
24 private final GroupId groupId; 29 private final GroupId groupId;
...@@ -64,7 +69,6 @@ public final class GroupOperation { ...@@ -64,7 +69,6 @@ public final class GroupOperation {
64 * @param groupId group Identifier 69 * @param groupId group Identifier
65 * @param groupType type of the group 70 * @param groupType type of the group
66 * @param buckets immutable list of group buckets to be part of group 71 * @param buckets immutable list of group buckets to be part of group
67 - *
68 * @return add group operation object 72 * @return add group operation object
69 */ 73 */
70 public static GroupOperation createAddGroupOperation(GroupId groupId, 74 public static GroupOperation createAddGroupOperation(GroupId groupId,
...@@ -80,7 +84,6 @@ public final class GroupOperation { ...@@ -80,7 +84,6 @@ public final class GroupOperation {
80 * @param groupId group Identifier 84 * @param groupId group Identifier
81 * @param groupType type of the group 85 * @param groupType type of the group
82 * @param buckets immutable list of group buckets to be part of group 86 * @param buckets immutable list of group buckets to be part of group
83 - *
84 * @return modify group operation object 87 * @return modify group operation object
85 */ 88 */
86 public static GroupOperation createModifyGroupOperation(GroupId groupId, 89 public static GroupOperation createModifyGroupOperation(GroupId groupId,
...@@ -96,7 +99,6 @@ public final class GroupOperation { ...@@ -96,7 +99,6 @@ public final class GroupOperation {
96 * 99 *
97 * @param groupId group Identifier 100 * @param groupId group Identifier
98 * @param groupType type of the group 101 * @param groupType type of the group
99 - *
100 * @return delete group operation object 102 * @return delete group operation object
101 */ 103 */
102 public static GroupOperation createDeleteGroupOperation(GroupId groupId, 104 public static GroupOperation createDeleteGroupOperation(GroupId groupId,
...@@ -106,7 +108,7 @@ public final class GroupOperation { ...@@ -106,7 +108,7 @@ public final class GroupOperation {
106 } 108 }
107 109
108 /** 110 /**
109 - * Return group operation type. 111 + * Returns group operation type.
110 * 112 *
111 * @return GroupOpType group operation type 113 * @return GroupOpType group operation type
112 */ 114 */
...@@ -115,7 +117,7 @@ public final class GroupOperation { ...@@ -115,7 +117,7 @@ public final class GroupOperation {
115 } 117 }
116 118
117 /** 119 /**
118 - * Return group identifier attribute of the operation. 120 + * Returns group identifier attribute of the operation.
119 * 121 *
120 * @return GroupId group identifier 122 * @return GroupId group identifier
121 */ 123 */
...@@ -124,7 +126,7 @@ public final class GroupOperation { ...@@ -124,7 +126,7 @@ public final class GroupOperation {
124 } 126 }
125 127
126 /** 128 /**
127 - * Return group type attribute of the operation. 129 + * Returns group type attribute of the operation.
128 * 130 *
129 * @return GroupType group type 131 * @return GroupType group type
130 */ 132 */
...@@ -133,7 +135,7 @@ public final class GroupOperation { ...@@ -133,7 +135,7 @@ public final class GroupOperation {
133 } 135 }
134 136
135 /** 137 /**
136 - * Return group buckets associated with the operation. 138 + * Returns group buckets associated with the operation.
137 * 139 *
138 * @return GroupBuckets group buckets 140 * @return GroupBuckets group buckets
139 */ 141 */
......
...@@ -19,9 +19,13 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -19,9 +19,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
19 19
20 import java.util.List; 20 import java.util.List;
21 21
22 -
23 import com.google.common.collect.ImmutableList; 22 import com.google.common.collect.ImmutableList;
24 23
24 +/**
25 + * Immutable collection of group operation to be used between
26 + * core and provider layers of group subsystem.
27 + *
28 + */
25 public final class GroupOperations { 29 public final class GroupOperations {
26 private final List<GroupOperation> operations; 30 private final List<GroupOperation> operations;
27 31
...@@ -35,7 +39,7 @@ public final class GroupOperations { ...@@ -35,7 +39,7 @@ public final class GroupOperations {
35 } 39 }
36 40
37 /** 41 /**
38 - * Immutable list of group operation. 42 + * Returns immutable list of group operation.
39 * 43 *
40 * @return list of group operation 44 * @return list of group operation
41 */ 45 */
......
...@@ -19,12 +19,12 @@ import org.onosproject.net.DeviceId; ...@@ -19,12 +19,12 @@ import org.onosproject.net.DeviceId;
19 import org.onosproject.net.provider.Provider; 19 import org.onosproject.net.provider.Provider;
20 20
21 /** 21 /**
22 - * Abstraction of a flow rule provider. 22 + * Abstraction of group provider.
23 */ 23 */
24 public interface GroupProvider extends Provider { 24 public interface GroupProvider extends Provider {
25 25
26 /** 26 /**
27 - * Perform a group operation in the specified device with the 27 + * Performs a batch of group operation in the specified device with the
28 * specified parameters. 28 * specified parameters.
29 * 29 *
30 * @param deviceId device identifier on which the batch of group 30 * @param deviceId device identifier on which the batch of group
......
...@@ -26,6 +26,11 @@ import org.onosproject.net.provider.ProviderService; ...@@ -26,6 +26,11 @@ import org.onosproject.net.provider.ProviderService;
26 */ 26 */
27 public interface GroupProviderService extends ProviderService<GroupProvider> { 27 public interface GroupProviderService extends ProviderService<GroupProvider> {
28 28
29 + /**
30 + * Notifies core if any failure from data plane during group operations.
31 + *
32 + * @param operation offended group operation
33 + */
29 void groupOperationFailed(GroupOperation operation); 34 void groupOperationFailed(GroupOperation operation);
30 35
31 /** 36 /**
......
...@@ -36,7 +36,7 @@ import org.onosproject.net.DeviceId; ...@@ -36,7 +36,7 @@ import org.onosproject.net.DeviceId;
36 public interface GroupService { 36 public interface GroupService {
37 37
38 /** 38 /**
39 - * Create a group in the specified device with the provided buckets. 39 + * Creates a group in the specified device with the provided buckets.
40 * This API provides an option for application to associate a cookie 40 * This API provides an option for application to associate a cookie
41 * while creating a group, so that applications can look-up the 41 * while creating a group, so that applications can look-up the
42 * groups based on the cookies. These Groups will be retained by 42 * groups based on the cookies. These Groups will be retained by
...@@ -55,7 +55,7 @@ public interface GroupService { ...@@ -55,7 +55,7 @@ public interface GroupService {
55 void addGroup(GroupDescription groupDesc); 55 void addGroup(GroupDescription groupDesc);
56 56
57 /** 57 /**
58 - * Return a group object associated to an application cookie. 58 + * Returns a group object associated to an application cookie.
59 * 59 *
60 * NOTE1: The presence of group object in the system does not 60 * NOTE1: The presence of group object in the system does not
61 * guarantee that the "group" is actually created in device. 61 * guarantee that the "group" is actually created in device.
...@@ -64,14 +64,13 @@ public interface GroupService { ...@@ -64,14 +64,13 @@ public interface GroupService {
64 * 64 *
65 * @param deviceId device identifier 65 * @param deviceId device identifier
66 * @param appCookie application cookie to be used for lookup 66 * @param appCookie application cookie to be used for lookup
67 - *
68 * @return group associated with the application cookie or 67 * @return group associated with the application cookie or
69 * NULL if Group is not found for the provided cookie 68 * NULL if Group is not found for the provided cookie
70 */ 69 */
71 Group getGroup(DeviceId deviceId, GroupKey appCookie); 70 Group getGroup(DeviceId deviceId, GroupKey appCookie);
72 71
73 /** 72 /**
74 - * Append buckets to existing group. The caller can optionally 73 + * Appends buckets to existing group. The caller can optionally
75 * associate a new cookie during this updation. GROUP_UPDATED or 74 * associate a new cookie during this updation. GROUP_UPDATED or
76 * GROUP_UPDATE_FAILED notifications would be provided along with 75 * GROUP_UPDATE_FAILED notifications would be provided along with
77 * cookie depending on the result of the operation on the device 76 * cookie depending on the result of the operation on the device
...@@ -89,7 +88,7 @@ public interface GroupService { ...@@ -89,7 +88,7 @@ public interface GroupService {
89 ApplicationId appId); 88 ApplicationId appId);
90 89
91 /** 90 /**
92 - * Remove buckets from existing group. The caller can optionally 91 + * Removes buckets from existing group. The caller can optionally
93 * associate a new cookie during this updation. GROUP_UPDATED or 92 * associate a new cookie during this updation. GROUP_UPDATED or
94 * GROUP_UPDATE_FAILED notifications would be provided along with 93 * GROUP_UPDATE_FAILED notifications would be provided along with
95 * cookie depending on the result of the operation on the device 94 * cookie depending on the result of the operation on the device
...@@ -107,7 +106,7 @@ public interface GroupService { ...@@ -107,7 +106,7 @@ public interface GroupService {
107 ApplicationId appId); 106 ApplicationId appId);
108 107
109 /** 108 /**
110 - * Delete a group associated to an application cookie. 109 + * Deletes a group associated to an application cookie.
111 * GROUP_DELETED or GROUP_DELETE_FAILED notifications would be 110 * GROUP_DELETED or GROUP_DELETE_FAILED notifications would be
112 * provided along with cookie depending on the result of the 111 * provided along with cookie depending on the result of the
113 * operation on the device 112 * operation on the device
...@@ -119,12 +118,11 @@ public interface GroupService { ...@@ -119,12 +118,11 @@ public interface GroupService {
119 void removeGroup(Device deviceId, GroupKey appCookie, ApplicationId appId); 118 void removeGroup(Device deviceId, GroupKey appCookie, ApplicationId appId);
120 119
121 /** 120 /**
122 - * Retrieve all groups created by an application in the specified device 121 + * Retrieves all groups created by an application in the specified device
123 * as seen by current controller instance. 122 * as seen by current controller instance.
124 * 123 *
125 * @param deviceId device identifier 124 * @param deviceId device identifier
126 * @param appId application id 125 * @param appId application id
127 - *
128 * @return collection of immutable group objects created by the application 126 * @return collection of immutable group objects created by the application
129 */ 127 */
130 Iterable<Group> getGroups(Device deviceId, ApplicationId appId); 128 Iterable<Group> getGroups(Device deviceId, ApplicationId appId);
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.group;
17 +
18 +import org.onosproject.net.DeviceId;
19 +import org.onosproject.store.Store;
20 +
21 +/**
22 + * Manages inventory of groups per device; not intended for direct use.
23 + */
24 +public interface GroupStore extends Store<GroupEvent, GroupStoreDelegate> {
25 +
26 + public enum UpdateType {
27 + /**
28 + * Modify existing group entry by adding provided information.
29 + */
30 + ADD,
31 + /**
32 + * Modify existing group by removing provided information from it.
33 + */
34 + REMOVE
35 + }
36 +
37 + /**
38 + * Returns the number of groups for the specified device in the store.
39 + *
40 + * @param deviceId the device ID
41 + * @return number of groups for the specified device
42 + */
43 + int getGroupCount(DeviceId deviceId);
44 +
45 + /**
46 + * Returns the groups associated with a device.
47 + *
48 + * @param deviceId the device ID
49 + * @return the group entries
50 + */
51 + Iterable<Group> getGroups(DeviceId deviceId);
52 +
53 + /**
54 + * Returns the stored group entry.
55 + *
56 + * @param deviceId the device ID
57 + * @param appCookie the group key
58 + * @return a group associated with the key
59 + */
60 + Group getGroup(DeviceId deviceId, GroupKey appCookie);
61 +
62 + /**
63 + * Stores a new group entry using the information from group description.
64 + *
65 + * @param groupDesc group description to be used to store group entry
66 + */
67 + void storeGroupDescription(GroupDescription groupDesc);
68 +
69 + /**
70 + * Updates the existing group entry with the information
71 + * from group description.
72 + *
73 + * @param deviceId the device ID
74 + * @param oldAppCookie the current group key
75 + * @param type update type
76 + * @param newGroupDesc group description with updates
77 + */
78 + void updateGroupDescription(DeviceId deviceId,
79 + GroupKey oldAppCookie,
80 + UpdateType type,
81 + GroupDescription newGroupDesc);
82 +
83 + /**
84 + * Triggers deleting the existing group entry.
85 + *
86 + * @param deviceId the device ID
87 + * @param appCookie the group key
88 + */
89 + void deleteGroupDescription(DeviceId deviceId,
90 + GroupKey appCookie);
91 +
92 + /**
93 + * Stores a new group entry, or updates an existing entry.
94 + *
95 + * @param group group entry
96 + */
97 + void addOrUpdateGroupEntry(Group group);
98 +
99 + /**
100 + * Removes the group entry from store.
101 + *
102 + * @param group group entry
103 + */
104 + void removeGroupEntry(Group group);
105 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.group;
17 +
18 +import org.onosproject.store.StoreDelegate;
19 +
20 +/**
21 + * Group store delegate abstraction.
22 + */
23 +public interface GroupStoreDelegate extends StoreDelegate<GroupEvent> {
24 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.group;
17 +
18 +/**
19 + * Interface that defines set methods for a group entry
20 + * that is stored in the system.
21 + */
22 +public interface StoredGroupEntry extends Group {
23 +
24 + /**
25 + * Sets the new state for this entry.
26 + *
27 + * @param newState new group entry state.
28 + */
29 + void setState(Group.GroupState newState);
30 +
31 + /**
32 + * Sets how long this entry has been entered in the system.
33 + *
34 + * @param life epoch time
35 + */
36 + void setLife(long life);
37 +
38 + /**
39 + * Sets number of packets processed by this group entry.
40 + *
41 + * @param packets a long value
42 + */
43 + void setPackets(long packets);
44 +
45 + /**
46 + * Sets number of bytes processed by this group entry.
47 + *
48 + * @param bytes a long value
49 + */
50 + void setBytes(long bytes);
51 +
52 +}
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +/**
17 + * Implementation of the group store.
18 + */
19 +package org.onosproject.store.group.impl;
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.store.trivial.impl;
17 +
18 +import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked;
19 +import static org.slf4j.LoggerFactory.getLogger;
20 +
21 +import java.util.ArrayList;
22 +import java.util.List;
23 +import java.util.concurrent.ConcurrentHashMap;
24 +import java.util.concurrent.ConcurrentMap;
25 +import java.util.concurrent.atomic.AtomicInteger;
26 +
27 +import org.apache.felix.scr.annotations.Activate;
28 +import org.apache.felix.scr.annotations.Component;
29 +import org.apache.felix.scr.annotations.Deactivate;
30 +import org.apache.felix.scr.annotations.Service;
31 +import org.onlab.util.NewConcurrentHashMap;
32 +import org.onosproject.core.DefaultGroupId;
33 +import org.onosproject.core.GroupId;
34 +import org.onosproject.net.DeviceId;
35 +import org.onosproject.net.group.DefaultGroup;
36 +import org.onosproject.net.group.DefaultGroupDescription;
37 +import org.onosproject.net.group.Group;
38 +import org.onosproject.net.group.Group.GroupState;
39 +import org.onosproject.net.group.GroupBucket;
40 +import org.onosproject.net.group.GroupBuckets;
41 +import org.onosproject.net.group.GroupDescription;
42 +import org.onosproject.net.group.GroupEvent;
43 +import org.onosproject.net.group.GroupEvent.Type;
44 +import org.onosproject.net.group.GroupKey;
45 +import org.onosproject.net.group.GroupStore;
46 +import org.onosproject.net.group.GroupStoreDelegate;
47 +import org.onosproject.net.group.StoredGroupEntry;
48 +import org.onosproject.store.AbstractStore;
49 +import org.slf4j.Logger;
50 +
51 +import com.google.common.base.Function;
52 +import com.google.common.collect.FluentIterable;
53 +
54 +/**
55 + * Manages inventory of group entries using trivial in-memory implementation.
56 + */
57 +@Component(immediate = true)
58 +@Service
59 +public class SimpleGroupStore
60 + extends AbstractStore<GroupEvent, GroupStoreDelegate>
61 + implements GroupStore {
62 +
63 + private final Logger log = getLogger(getClass());
64 +
65 + // inner Map is per device group table
66 + private final ConcurrentMap<DeviceId, ConcurrentMap<GroupKey, StoredGroupEntry>>
67 + groupEntriesByKey = new ConcurrentHashMap<>();
68 + private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, StoredGroupEntry>>
69 + groupEntriesById = new ConcurrentHashMap<>();
70 +
71 + private final AtomicInteger groupIdGen = new AtomicInteger();
72 +
73 + @Activate
74 + public void activate() {
75 + log.info("Started");
76 + }
77 +
78 + @Deactivate
79 + public void deactivate() {
80 + groupEntriesByKey.clear();
81 + groupEntriesById.clear();
82 + log.info("Stopped");
83 + }
84 +
85 + private static NewConcurrentHashMap<GroupKey, StoredGroupEntry> lazyEmptyGroupKeyTable() {
86 + return NewConcurrentHashMap.<GroupKey, StoredGroupEntry>ifNeeded();
87 + }
88 +
89 + private static NewConcurrentHashMap<GroupId, StoredGroupEntry> lazyEmptyGroupIdTable() {
90 + return NewConcurrentHashMap.<GroupId, StoredGroupEntry>ifNeeded();
91 + }
92 +
93 + /**
94 + * Returns the group key table for specified device.
95 + *
96 + * @param deviceId identifier of the device
97 + * @return Map representing group key table of given device.
98 + */
99 + private ConcurrentMap<GroupKey, StoredGroupEntry> getGroupKeyTable(DeviceId deviceId) {
100 + return createIfAbsentUnchecked(groupEntriesByKey,
101 + deviceId, lazyEmptyGroupKeyTable());
102 + }
103 +
104 + /**
105 + * Returns the group id table for specified device.
106 + *
107 + * @param deviceId identifier of the device
108 + * @return Map representing group key table of given device.
109 + */
110 + private ConcurrentMap<GroupId, StoredGroupEntry> getGroupIdTable(DeviceId deviceId) {
111 + return createIfAbsentUnchecked(groupEntriesById,
112 + deviceId, lazyEmptyGroupIdTable());
113 + }
114 +
115 + /**
116 + * Returns the number of groups for the specified device in the store.
117 + *
118 + * @return number of groups for the specified device
119 + */
120 + @Override
121 + public int getGroupCount(DeviceId deviceId) {
122 + return (groupEntriesByKey.get(deviceId) != null) ?
123 + groupEntriesByKey.get(deviceId).size() : 0;
124 + }
125 +
126 + /**
127 + * Returns the groups associated with a device.
128 + *
129 + * @param deviceId the device ID
130 + *
131 + * @return the group entries
132 + */
133 + @Override
134 + public Iterable<Group> getGroups(DeviceId deviceId) {
135 + // flatten and make iterator unmodifiable
136 + if (groupEntriesByKey.get(deviceId) != null) {
137 + return FluentIterable.from(groupEntriesByKey.get(deviceId).values())
138 + .transform(
139 + new Function<StoredGroupEntry, Group>() {
140 +
141 + @Override
142 + public Group apply(
143 + StoredGroupEntry input) {
144 + return input;
145 + }
146 + });
147 + } else {
148 + return null;
149 + }
150 + }
151 +
152 + /**
153 + * Returns the stored group entry.
154 + *
155 + * @param deviceId the device ID
156 + * @param appCookie the group key
157 + *
158 + * @return a group associated with the key
159 + */
160 + @Override
161 + public Group getGroup(DeviceId deviceId, GroupKey appCookie) {
162 + return (groupEntriesByKey.get(deviceId) != null) ?
163 + groupEntriesByKey.get(deviceId).get(appCookie) :
164 + null;
165 + }
166 +
167 + /**
168 + * Stores a new group entry using the information from group description.
169 + *
170 + * @param groupDesc group description to be used to create group entry
171 + */
172 + @Override
173 + public void storeGroupDescription(GroupDescription groupDesc) {
174 + /* Check if a group is existing with the same key */
175 + if (getGroup(groupDesc.deviceId(), groupDesc.appCookie()) != null) {
176 + return;
177 + }
178 +
179 + /* Get a new group identifier */
180 + GroupId id = new DefaultGroupId(groupIdGen.incrementAndGet());
181 + /* Create a group entry object */
182 + StoredGroupEntry group = new DefaultGroup(id, groupDesc);
183 + /* Insert the newly created group entry into concurrent key and id maps */
184 + ConcurrentMap<GroupKey, StoredGroupEntry> keyTable =
185 + getGroupKeyTable(groupDesc.deviceId());
186 + keyTable.put(groupDesc.appCookie(), group);
187 + ConcurrentMap<GroupId, StoredGroupEntry> idTable =
188 + getGroupIdTable(groupDesc.deviceId());
189 + idTable.put(id, group);
190 + notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED,
191 + group));
192 + }
193 +
194 + /**
195 + * Updates the existing group entry with the information
196 + * from group description.
197 + *
198 + * @param deviceId the device ID
199 + * @param oldAppCookie the current group key
200 + * @param type update type
201 + * @param newGroupDesc group description with updates
202 + */
203 + @Override
204 + public void updateGroupDescription(DeviceId deviceId,
205 + GroupKey oldAppCookie,
206 + UpdateType type,
207 + GroupDescription newGroupDesc) {
208 + /* Check if a group is existing with the provided key */
209 + Group oldGroup = getGroup(deviceId, oldAppCookie);
210 + if (oldGroup == null) {
211 + return;
212 + }
213 +
214 + List<GroupBucket> newBucketList = getUpdatedBucketList(oldGroup,
215 + type,
216 + newGroupDesc.buckets());
217 + if (newBucketList != null) {
218 + /* Create a new group object from the old group */
219 + GroupBuckets updatedBuckets = new GroupBuckets(newBucketList);
220 + GroupDescription updatedGroupDesc = new DefaultGroupDescription(
221 + oldGroup.deviceId(),
222 + oldGroup.type(),
223 + updatedBuckets,
224 + newGroupDesc.appCookie(),
225 + oldGroup.appId());
226 + StoredGroupEntry newGroup = new DefaultGroup(oldGroup.id(),
227 + updatedGroupDesc);
228 + newGroup.setState(GroupState.PENDING_UPDATE);
229 + newGroup.setLife(oldGroup.life());
230 + newGroup.setPackets(oldGroup.packets());
231 + newGroup.setBytes(oldGroup.bytes());
232 + /* Remove the old entry from maps and add new entry
233 + * using new key
234 + */
235 + ConcurrentMap<GroupKey, StoredGroupEntry> keyTable =
236 + getGroupKeyTable(oldGroup.deviceId());
237 + ConcurrentMap<GroupId, StoredGroupEntry> idTable =
238 + getGroupIdTable(oldGroup.deviceId());
239 + keyTable.remove(oldGroup.appCookie());
240 + idTable.remove(oldGroup.id());
241 + keyTable.put(newGroup.appCookie(), newGroup);
242 + idTable.put(newGroup.id(), newGroup);
243 + notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, newGroup));
244 + }
245 + }
246 +
247 + private List<GroupBucket> getUpdatedBucketList(Group oldGroup,
248 + UpdateType type,
249 + GroupBuckets buckets) {
250 + GroupBuckets oldBuckets = oldGroup.buckets();
251 + List<GroupBucket> newBucketList = new ArrayList<GroupBucket>(
252 + oldBuckets.buckets());
253 + boolean groupDescUpdated = false;
254 +
255 + if (type == UpdateType.ADD) {
256 + /* Check if the any of the new buckets are part of the
257 + * old bucket list
258 + */
259 + for (GroupBucket addBucket:buckets.buckets()) {
260 + if (!newBucketList.contains(addBucket)) {
261 + newBucketList.add(addBucket);
262 + groupDescUpdated = true;
263 + }
264 + }
265 + } else if (type == UpdateType.REMOVE) {
266 + /* Check if the to be removed buckets are part of the
267 + * old bucket list
268 + */
269 + for (GroupBucket removeBucket:buckets.buckets()) {
270 + if (newBucketList.contains(removeBucket)) {
271 + newBucketList.remove(removeBucket);
272 + groupDescUpdated = true;
273 + }
274 + }
275 + }
276 +
277 + if (groupDescUpdated) {
278 + return newBucketList;
279 + } else {
280 + return null;
281 + }
282 + }
283 +
284 + /**
285 + * Triggers deleting the existing group entry.
286 + *
287 + * @param deviceId the device ID
288 + * @param appCookie the group key
289 + */
290 + @Override
291 + public void deleteGroupDescription(DeviceId deviceId,
292 + GroupKey appCookie) {
293 + /* Check if a group is existing with the provided key */
294 + StoredGroupEntry existing = (groupEntriesByKey.get(deviceId) != null) ?
295 + groupEntriesByKey.get(deviceId).get(appCookie) :
296 + null;
297 + if (existing == null) {
298 + return;
299 + }
300 +
301 + synchronized (existing) {
302 + existing.setState(GroupState.PENDING_DELETE);
303 + }
304 + notifyDelegate(new GroupEvent(Type.GROUP_REMOVE_REQUESTED, existing));
305 + }
306 +
307 + /**
308 + * Stores a new group entry, or updates an existing entry.
309 + *
310 + * @param group group entry
311 + */
312 + @Override
313 + public void addOrUpdateGroupEntry(Group group) {
314 + // check if this new entry is an update to an existing entry
315 + StoredGroupEntry existing = (groupEntriesById.get(
316 + group.deviceId()) != null) ?
317 + groupEntriesById.get(group.deviceId()).get(group.id()) :
318 + null;
319 + GroupEvent event = null;
320 +
321 + if (existing != null) {
322 + synchronized (existing) {
323 + existing.setLife(group.life());
324 + existing.setPackets(group.packets());
325 + existing.setBytes(group.bytes());
326 + if (existing.state() == GroupState.PENDING_ADD) {
327 + existing.setState(GroupState.ADDED);
328 + event = new GroupEvent(Type.GROUP_ADDED, existing);
329 + } else {
330 + if (existing.state() == GroupState.PENDING_UPDATE) {
331 + existing.setState(GroupState.PENDING_UPDATE);
332 + }
333 + event = new GroupEvent(Type.GROUP_UPDATED, existing);
334 + }
335 + }
336 + }
337 +
338 + if (event != null) {
339 + notifyDelegate(event);
340 + }
341 + }
342 +
343 + /**
344 + * Removes the group entry from store.
345 + *
346 + * @param group group entry
347 + */
348 + @Override
349 + public void removeGroupEntry(Group group) {
350 + StoredGroupEntry existing = (groupEntriesById.get(
351 + group.deviceId()) != null) ?
352 + groupEntriesById.get(group.deviceId()).get(group.id()) :
353 + null;
354 +
355 + if (existing != null) {
356 + ConcurrentMap<GroupKey, StoredGroupEntry> keyTable =
357 + getGroupKeyTable(existing.deviceId());
358 + ConcurrentMap<GroupId, StoredGroupEntry> idTable =
359 + getGroupIdTable(existing.deviceId());
360 + idTable.remove(existing.id());
361 + keyTable.remove(existing.appCookie());
362 + notifyDelegate(new GroupEvent(Type.GROUP_REMOVED, existing));
363 + }
364 + }
365 +}
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.store.trivial.impl;
17 +
18 +import static org.junit.Assert.assertEquals;
19 +import static org.onosproject.net.DeviceId.deviceId;
20 +
21 +import java.util.ArrayList;
22 +import java.util.List;
23 +
24 +import org.junit.After;
25 +import org.junit.Before;
26 +import org.junit.Test;
27 +import org.onlab.packet.MacAddress;
28 +import org.onosproject.core.ApplicationId;
29 +import org.onosproject.core.DefaultApplicationId;
30 +import org.onosproject.core.GroupId;
31 +import org.onosproject.net.DeviceId;
32 +import org.onosproject.net.PortNumber;
33 +import org.onosproject.net.flow.DefaultTrafficTreatment;
34 +import org.onosproject.net.flow.TrafficTreatment;
35 +import org.onosproject.net.group.DefaultGroupBucket;
36 +import org.onosproject.net.group.DefaultGroupDescription;
37 +import org.onosproject.net.group.Group;
38 +import org.onosproject.net.group.GroupBucket;
39 +import org.onosproject.net.group.GroupBuckets;
40 +import org.onosproject.net.group.GroupDescription;
41 +import org.onosproject.net.group.GroupEvent;
42 +import org.onosproject.net.group.GroupKey;
43 +import org.onosproject.net.group.GroupStoreDelegate;
44 +import org.onosproject.net.group.GroupStore.UpdateType;
45 +
46 +/**
47 + * Test of the simple DeviceStore implementation.
48 + */
49 +public class SimpleGroupStoreTest {
50 +
51 + private SimpleGroupStore simpleGroupStore;
52 +
53 + public static final DeviceId D1 = deviceId("of:1");
54 +
55 + @Before
56 + public void setUp() throws Exception {
57 + simpleGroupStore = new SimpleGroupStore();
58 + simpleGroupStore.activate();
59 + }
60 +
61 + @After
62 + public void tearDown() throws Exception {
63 + simpleGroupStore.deactivate();
64 + }
65 +
66 + public class TestGroupKey implements GroupKey {
67 + private String groupId;
68 +
69 + public TestGroupKey(String id) {
70 + this.groupId = id;
71 + }
72 +
73 + public String id() {
74 + return this.groupId;
75 + }
76 +
77 + @Override
78 + public int hashCode() {
79 + return groupId.hashCode();
80 + }
81 +
82 + @Override
83 + public boolean equals(Object obj) {
84 + if (obj instanceof TestGroupKey) {
85 + return this.groupId.equals(((TestGroupKey) obj).id());
86 + }
87 + return false;
88 + }
89 + }
90 +
91 + private class InternalGroupStoreDelegate
92 + implements GroupStoreDelegate {
93 + private GroupId createdGroupId = null;
94 + private GroupKey createdGroupKey;
95 + private GroupBuckets createdBuckets;
96 + private GroupEvent.Type expectedEvent;
97 +
98 + public InternalGroupStoreDelegate(GroupKey key,
99 + GroupBuckets buckets,
100 + GroupEvent.Type expectedEvent) {
101 + this.createdBuckets = buckets;
102 + this.createdGroupKey = key;
103 + this.expectedEvent = expectedEvent;
104 + }
105 + @Override
106 + public void notify(GroupEvent event) {
107 + assertEquals(expectedEvent, event.type());
108 + assertEquals(Group.Type.SELECT, event.subject().type());
109 + assertEquals(D1, event.subject().deviceId());
110 + assertEquals(createdGroupKey, event.subject().appCookie());
111 + assertEquals(createdBuckets.buckets(), event.subject().buckets().buckets());
112 + if (expectedEvent == GroupEvent.Type.GROUP_ADD_REQUESTED) {
113 + createdGroupId = event.subject().id();
114 + assertEquals(Group.GroupState.PENDING_ADD,
115 + event.subject().state());
116 + } else if (expectedEvent == GroupEvent.Type.GROUP_ADDED) {
117 + createdGroupId = event.subject().id();
118 + assertEquals(Group.GroupState.ADDED,
119 + event.subject().state());
120 + } else if (expectedEvent == GroupEvent.Type.GROUP_UPDATE_REQUESTED) {
121 + assertEquals(Group.GroupState.PENDING_UPDATE,
122 + event.subject().state());
123 + } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVE_REQUESTED) {
124 + assertEquals(Group.GroupState.PENDING_DELETE,
125 + event.subject().state());
126 + } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVED) {
127 + createdGroupId = event.subject().id();
128 + assertEquals(Group.GroupState.PENDING_DELETE,
129 + event.subject().state());
130 + }
131 + }
132 +
133 + public void verifyGroupId(GroupId id) {
134 + assertEquals(createdGroupId, id);
135 + }
136 + }
137 +
138 + @Test
139 + public void testGroupStoreOperations() {
140 + ApplicationId appId =
141 + new DefaultApplicationId(2, "org.groupstore.test");
142 + TestGroupKey key = new TestGroupKey("group1");
143 + PortNumber[] ports = {PortNumber.portNumber(31),
144 + PortNumber.portNumber(32)};
145 + List<PortNumber> outPorts = new ArrayList<PortNumber>();
146 + outPorts.add(ports[0]);
147 + outPorts.add(ports[1]);
148 +
149 + List<GroupBucket> buckets = new ArrayList<GroupBucket>();
150 + for (PortNumber portNumber: outPorts) {
151 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
152 + tBuilder.setOutput(portNumber)
153 + .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
154 + .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
155 + .pushMpls()
156 + .setMpls(106);
157 + buckets.add(DefaultGroupBucket.createSelectGroupBucket(
158 + tBuilder.build()));
159 + }
160 + GroupBuckets groupBuckets = new GroupBuckets(buckets);
161 + GroupDescription groupDesc = new DefaultGroupDescription(
162 + D1,
163 + Group.Type.SELECT,
164 + groupBuckets,
165 + key,
166 + appId);
167 + InternalGroupStoreDelegate checkStoreGroupDelegate =
168 + new InternalGroupStoreDelegate(key,
169 + groupBuckets,
170 + GroupEvent.Type.GROUP_ADD_REQUESTED);
171 + simpleGroupStore.setDelegate(checkStoreGroupDelegate);
172 + /* Testing storeGroup operation */
173 + simpleGroupStore.storeGroupDescription(groupDesc);
174 +
175 + /* Testing getGroupCount operation */
176 + assertEquals(1, simpleGroupStore.getGroupCount(D1));
177 +
178 + /* Testing getGroup operation */
179 + Group createdGroup = simpleGroupStore.getGroup(D1, key);
180 + checkStoreGroupDelegate.verifyGroupId(createdGroup.id());
181 +
182 + /* Testing getGroups operation */
183 + Iterable<Group> createdGroups = simpleGroupStore.getGroups(D1);
184 + int groupCount = 0;
185 + for (Group group:createdGroups) {
186 + checkStoreGroupDelegate.verifyGroupId(group.id());
187 + groupCount++;
188 + }
189 + assertEquals(1, groupCount);
190 + simpleGroupStore.unsetDelegate(checkStoreGroupDelegate);
191 +
192 + /* Testing addOrUpdateGroupEntry operation from southbound */
193 + InternalGroupStoreDelegate addGroupEntryDelegate =
194 + new InternalGroupStoreDelegate(key,
195 + groupBuckets,
196 + GroupEvent.Type.GROUP_ADDED);
197 + simpleGroupStore.setDelegate(addGroupEntryDelegate);
198 + simpleGroupStore.addOrUpdateGroupEntry(createdGroup);
199 + simpleGroupStore.unsetDelegate(addGroupEntryDelegate);
200 +
201 + /* Testing updateGroupDescription for ADD operation from northbound */
202 + TestGroupKey addKey = new TestGroupKey("group1AddBuckets");
203 + PortNumber[] newNeighborPorts = {PortNumber.portNumber(41),
204 + PortNumber.portNumber(42)};
205 + List<PortNumber> newOutPorts = new ArrayList<PortNumber>();
206 + newOutPorts.add(newNeighborPorts[0]);
207 + newOutPorts.add(newNeighborPorts[1]);
208 +
209 + List<GroupBucket> toAddBuckets = new ArrayList<GroupBucket>();
210 + for (PortNumber portNumber: newOutPorts) {
211 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
212 + tBuilder.setOutput(portNumber)
213 + .setEthDst(MacAddress.valueOf("00:00:00:00:00:03"))
214 + .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
215 + .pushMpls()
216 + .setMpls(106);
217 + toAddBuckets.add(DefaultGroupBucket.createSelectGroupBucket(
218 + tBuilder.build()));
219 + }
220 + GroupBuckets toAddGroupBuckets = new GroupBuckets(toAddBuckets);
221 + buckets.addAll(toAddBuckets);
222 + GroupBuckets updatedGroupBuckets = new GroupBuckets(buckets);
223 + InternalGroupStoreDelegate updateGroupDescDelegate =
224 + new InternalGroupStoreDelegate(addKey,
225 + updatedGroupBuckets,
226 + GroupEvent.Type.GROUP_UPDATE_REQUESTED);
227 + simpleGroupStore.setDelegate(updateGroupDescDelegate);
228 + GroupDescription newGroupDesc = new DefaultGroupDescription(
229 + D1,
230 + Group.Type.SELECT,
231 + toAddGroupBuckets,
232 + addKey,
233 + appId);
234 + simpleGroupStore.updateGroupDescription(D1,
235 + key,
236 + UpdateType.ADD,
237 + newGroupDesc);
238 + simpleGroupStore.unsetDelegate(updateGroupDescDelegate);
239 +
240 + /* Testing updateGroupDescription for REMOVE operation from northbound */
241 + TestGroupKey removeKey = new TestGroupKey("group1RemoveBuckets");
242 + List<GroupBucket> toRemoveBuckets = new ArrayList<GroupBucket>();
243 + toRemoveBuckets.add(updatedGroupBuckets.buckets().get(0));
244 + toRemoveBuckets.add(updatedGroupBuckets.buckets().get(1));
245 + GroupBuckets toRemoveGroupBuckets = new GroupBuckets(toRemoveBuckets);
246 + List<GroupBucket> remainingBuckets = new ArrayList<GroupBucket>();
247 + remainingBuckets.add(updatedGroupBuckets.buckets().get(2));
248 + remainingBuckets.add(updatedGroupBuckets.buckets().get(3));
249 + GroupBuckets remainingGroupBuckets = new GroupBuckets(remainingBuckets);
250 + InternalGroupStoreDelegate removeGroupDescDelegate =
251 + new InternalGroupStoreDelegate(removeKey,
252 + remainingGroupBuckets,
253 + GroupEvent.Type.GROUP_UPDATE_REQUESTED);
254 + simpleGroupStore.setDelegate(removeGroupDescDelegate);
255 + GroupDescription removeGroupDesc = new DefaultGroupDescription(
256 + D1,
257 + Group.Type.SELECT,
258 + toRemoveGroupBuckets,
259 + removeKey,
260 + appId);
261 + simpleGroupStore.updateGroupDescription(D1,
262 + addKey,
263 + UpdateType.REMOVE,
264 + removeGroupDesc);
265 + simpleGroupStore.unsetDelegate(removeGroupDescDelegate);
266 +
267 + /* Testing getGroup operation */
268 + Group existingGroup = simpleGroupStore.getGroup(D1, removeKey);
269 + checkStoreGroupDelegate.verifyGroupId(existingGroup.id());
270 +
271 + /* Testing addOrUpdateGroupEntry operation from southbound */
272 + InternalGroupStoreDelegate updateGroupEntryDelegate =
273 + new InternalGroupStoreDelegate(removeKey,
274 + remainingGroupBuckets,
275 + GroupEvent.Type.GROUP_UPDATED);
276 + simpleGroupStore.setDelegate(updateGroupEntryDelegate);
277 + simpleGroupStore.addOrUpdateGroupEntry(existingGroup);
278 + simpleGroupStore.unsetDelegate(updateGroupEntryDelegate);
279 +
280 + /* Testing deleteGroupDescription operation from northbound */
281 + InternalGroupStoreDelegate deleteGroupDescDelegate =
282 + new InternalGroupStoreDelegate(removeKey,
283 + remainingGroupBuckets,
284 + GroupEvent.Type.GROUP_REMOVE_REQUESTED);
285 + simpleGroupStore.setDelegate(deleteGroupDescDelegate);
286 + simpleGroupStore.deleteGroupDescription(D1, removeKey);
287 + simpleGroupStore.unsetDelegate(deleteGroupDescDelegate);
288 +
289 + /* Testing removeGroupEntry operation from southbound */
290 + InternalGroupStoreDelegate removeGroupEntryDelegate =
291 + new InternalGroupStoreDelegate(removeKey,
292 + remainingGroupBuckets,
293 + GroupEvent.Type.GROUP_REMOVED);
294 + simpleGroupStore.setDelegate(removeGroupEntryDelegate);
295 + simpleGroupStore.removeGroupEntry(existingGroup);
296 +
297 + /* Testing getGroup operation */
298 + existingGroup = simpleGroupStore.getGroup(D1, removeKey);
299 + assertEquals(null, existingGroup);
300 + Iterable<Group> existingGroups = simpleGroupStore.getGroups(D1);
301 + groupCount = 0;
302 + for (Group tmp:existingGroups) {
303 + /* To avoid warning */
304 + assertEquals(null, tmp);
305 + groupCount++;
306 + }
307 + assertEquals(0, groupCount);
308 + assertEquals(0, simpleGroupStore.getGroupCount(D1));
309 +
310 + simpleGroupStore.unsetDelegate(removeGroupEntryDelegate);
311 +
312 + }
313 +}
314 +