Madan Jampani

Added GossipLinkStore with basic replication for link state.

1 +package org.onlab.onos.store.link.impl;
2 +
3 +import org.onlab.onos.store.cluster.messaging.MessageSubject;
4 +
5 +/**
6 + * MessageSubjects used by GossipLinkStore peer-peer communication.
7 + */
8 +public final class GossipLinkStoreMessageSubjects {
9 +
10 + private GossipLinkStoreMessageSubjects() {}
11 +
12 + public static final MessageSubject LINK_UPDATE = new MessageSubject("peer-link-update");
13 + public static final MessageSubject LINK_REMOVED = new MessageSubject("peer-link-removed");
14 +}
1 +package org.onlab.onos.store.link.impl;
2 +
3 +import com.google.common.base.MoreObjects;
4 +
5 +import org.onlab.onos.net.link.LinkDescription;
6 +import org.onlab.onos.net.provider.ProviderId;
7 +import org.onlab.onos.store.common.impl.Timestamped;
8 +
9 +/**
10 + * Information published by GossipDeviceStore to notify peers of a device
11 + * change event.
12 + */
13 +public class InternalLinkEvent {
14 +
15 + private final ProviderId providerId;
16 + private final Timestamped<LinkDescription> linkDescription;
17 +
18 + protected InternalLinkEvent(
19 + ProviderId providerId,
20 + Timestamped<LinkDescription> linkDescription) {
21 + this.providerId = providerId;
22 + this.linkDescription = linkDescription;
23 + }
24 +
25 + public ProviderId providerId() {
26 + return providerId;
27 + }
28 +
29 + public Timestamped<LinkDescription> linkDescription() {
30 + return linkDescription;
31 + }
32 +
33 + @Override
34 + public String toString() {
35 + return MoreObjects.toStringHelper(getClass())
36 + .add("providerId", providerId)
37 + .add("linkDescription", linkDescription)
38 + .toString();
39 + }
40 +
41 + // for serializer
42 + protected InternalLinkEvent() {
43 + this.providerId = null;
44 + this.linkDescription = null;
45 + }
46 +}
1 +package org.onlab.onos.store.link.impl;
2 +
3 +import org.onlab.onos.net.LinkKey;
4 +import org.onlab.onos.store.Timestamp;
5 +
6 +import com.google.common.base.MoreObjects;
7 +
8 +/**
9 + * Information published by GossipLinkStore to notify peers of a link
10 + * being removed.
11 + */
12 +public class InternalLinkRemovedEvent {
13 +
14 + private final LinkKey linkKey;
15 + private final Timestamp timestamp;
16 +
17 + /**
18 + * Creates a InternalLinkRemovedEvent.
19 + * @param linkKey identifier of the removed link.
20 + * @param timestamp timestamp of when the link was removed.
21 + */
22 + public InternalLinkRemovedEvent(LinkKey linkKey, Timestamp timestamp) {
23 + this.linkKey = linkKey;
24 + this.timestamp = timestamp;
25 + }
26 +
27 + public LinkKey linkKey() {
28 + return linkKey;
29 + }
30 +
31 + public Timestamp timestamp() {
32 + return timestamp;
33 + }
34 +
35 + @Override
36 + public String toString() {
37 + return MoreObjects.toStringHelper(getClass())
38 + .add("linkKey", linkKey)
39 + .add("timestamp", timestamp)
40 + .toString();
41 + }
42 +
43 + // for serializer
44 + @SuppressWarnings("unused")
45 + private InternalLinkRemovedEvent() {
46 + linkKey = null;
47 + timestamp = null;
48 + }
49 +}
...\ No newline at end of file ...\ No newline at end of file
1 -package org.onlab.onos.store.link.impl;
2 -
3 -import static org.onlab.onos.net.Link.Type.DIRECT;
4 -import static org.onlab.onos.net.Link.Type.INDIRECT;
5 -import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED;
6 -import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
7 -import static org.onlab.onos.net.link.LinkEvent.Type.LINK_UPDATED;
8 -import static org.slf4j.LoggerFactory.getLogger;
9 -
10 -import java.util.HashSet;
11 -import java.util.Set;
12 -import java.util.concurrent.ConcurrentHashMap;
13 -import java.util.concurrent.ConcurrentMap;
14 -
15 -import org.apache.felix.scr.annotations.Activate;
16 -import org.apache.felix.scr.annotations.Component;
17 -import org.apache.felix.scr.annotations.Deactivate;
18 -import org.apache.felix.scr.annotations.Reference;
19 -import org.apache.felix.scr.annotations.ReferenceCardinality;
20 -import org.apache.felix.scr.annotations.Service;
21 -import org.onlab.onos.net.ConnectPoint;
22 -import org.onlab.onos.net.DefaultLink;
23 -import org.onlab.onos.net.DeviceId;
24 -import org.onlab.onos.net.Link;
25 -import org.onlab.onos.net.LinkKey;
26 -import org.onlab.onos.net.link.LinkDescription;
27 -import org.onlab.onos.net.link.LinkEvent;
28 -import org.onlab.onos.net.link.LinkStore;
29 -import org.onlab.onos.net.link.LinkStoreDelegate;
30 -import org.onlab.onos.net.provider.ProviderId;
31 -import org.onlab.onos.store.AbstractStore;
32 -import org.onlab.onos.store.ClockService;
33 -import org.onlab.onos.store.Timestamp;
34 -import org.slf4j.Logger;
35 -
36 -import com.google.common.collect.HashMultimap;
37 -import com.google.common.collect.ImmutableSet;
38 -import com.google.common.collect.Multimap;
39 -import com.google.common.collect.ImmutableSet.Builder;
40 -
41 -import static com.google.common.base.Preconditions.checkArgument;
42 -import static com.google.common.base.Preconditions.checkState;
43 -
44 -//TODO: Add support for multiple provider and annotations
45 -/**
46 - * Manages inventory of infrastructure links using a protocol that takes into consideration
47 - * the order in which events occur.
48 - */
49 -// FIXME: This does not yet implement the full protocol.
50 -// The full protocol requires the sender of LLDP message to include the
51 -// version information of src device/port and the receiver to
52 -// take that into account when figuring out if a more recent src
53 -// device/port down event renders the link discovery obsolete.
54 -@Component(immediate = true)
55 -@Service
56 -public class OnosDistributedLinkStore
57 - extends AbstractStore<LinkEvent, LinkStoreDelegate>
58 - implements LinkStore {
59 -
60 - private final Logger log = getLogger(getClass());
61 -
62 - // Link inventory
63 - private ConcurrentMap<LinkKey, VersionedValue<Link>> links;
64 -
65 - public static final String LINK_NOT_FOUND = "Link between %s and %s not found";
66 -
67 - // TODO synchronize?
68 - // Egress and ingress link sets
69 - private final Multimap<DeviceId, VersionedValue<Link>> srcLinks = HashMultimap.create();
70 - private final Multimap<DeviceId, VersionedValue<Link>> dstLinks = HashMultimap.create();
71 -
72 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 - protected ClockService clockService;
74 -
75 - @Activate
76 - public void activate() {
77 -
78 - links = new ConcurrentHashMap<>();
79 -
80 - log.info("Started");
81 - }
82 -
83 - @Deactivate
84 - public void deactivate() {
85 - log.info("Stopped");
86 - }
87 -
88 - @Override
89 - public int getLinkCount() {
90 - return links.size();
91 - }
92 -
93 - @Override
94 - public Iterable<Link> getLinks() {
95 - Builder<Link> builder = ImmutableSet.builder();
96 - synchronized (this) {
97 - for (VersionedValue<Link> link : links.values()) {
98 - builder.add(link.entity());
99 - }
100 - return builder.build();
101 - }
102 - }
103 -
104 - @Override
105 - public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
106 - Set<VersionedValue<Link>> egressLinks = ImmutableSet.copyOf(srcLinks.get(deviceId));
107 - Set<Link> rawEgressLinks = new HashSet<>();
108 - for (VersionedValue<Link> link : egressLinks) {
109 - rawEgressLinks.add(link.entity());
110 - }
111 - return rawEgressLinks;
112 - }
113 -
114 - @Override
115 - public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
116 - Set<VersionedValue<Link>> ingressLinks = ImmutableSet.copyOf(dstLinks.get(deviceId));
117 - Set<Link> rawIngressLinks = new HashSet<>();
118 - for (VersionedValue<Link> link : ingressLinks) {
119 - rawIngressLinks.add(link.entity());
120 - }
121 - return rawIngressLinks;
122 - }
123 -
124 - @Override
125 - public Link getLink(ConnectPoint src, ConnectPoint dst) {
126 - VersionedValue<Link> link = links.get(new LinkKey(src, dst));
127 - checkArgument(link != null, "LINK_NOT_FOUND", src, dst);
128 - return link.entity();
129 - }
130 -
131 - @Override
132 - public Set<Link> getEgressLinks(ConnectPoint src) {
133 - Set<Link> egressLinks = new HashSet<>();
134 - for (VersionedValue<Link> link : srcLinks.get(src.deviceId())) {
135 - if (link.entity().src().equals(src)) {
136 - egressLinks.add(link.entity());
137 - }
138 - }
139 - return egressLinks;
140 - }
141 -
142 - @Override
143 - public Set<Link> getIngressLinks(ConnectPoint dst) {
144 - Set<Link> ingressLinks = new HashSet<>();
145 - for (VersionedValue<Link> link : dstLinks.get(dst.deviceId())) {
146 - if (link.entity().dst().equals(dst)) {
147 - ingressLinks.add(link.entity());
148 - }
149 - }
150 - return ingressLinks;
151 - }
152 -
153 - @Override
154 - public LinkEvent createOrUpdateLink(ProviderId providerId,
155 - LinkDescription linkDescription) {
156 -
157 - final DeviceId destinationDeviceId = linkDescription.dst().deviceId();
158 - final Timestamp newTimestamp = clockService.getTimestamp(destinationDeviceId);
159 -
160 - LinkKey key = new LinkKey(linkDescription.src(), linkDescription.dst());
161 - VersionedValue<Link> link = links.get(key);
162 - if (link == null) {
163 - return createLink(providerId, key, linkDescription, newTimestamp);
164 - }
165 -
166 - checkState(newTimestamp.compareTo(link.timestamp()) > 0,
167 - "Existing Link has a timestamp in the future!");
168 -
169 - return updateLink(providerId, link, key, linkDescription, newTimestamp);
170 - }
171 -
172 - // Creates and stores the link and returns the appropriate event.
173 - private LinkEvent createLink(ProviderId providerId, LinkKey key,
174 - LinkDescription linkDescription, Timestamp timestamp) {
175 - VersionedValue<Link> link = new VersionedValue<Link>(new DefaultLink(providerId, key.src(), key.dst(),
176 - linkDescription.type()), true, timestamp);
177 - synchronized (this) {
178 - links.put(key, link);
179 - addNewLink(link, timestamp);
180 - }
181 - // FIXME: notify peers.
182 - return new LinkEvent(LINK_ADDED, link.entity());
183 - }
184 -
185 - // update Egress and ingress link sets
186 - private void addNewLink(VersionedValue<Link> link, Timestamp timestamp) {
187 - Link rawLink = link.entity();
188 - synchronized (this) {
189 - srcLinks.put(rawLink.src().deviceId(), link);
190 - dstLinks.put(rawLink.dst().deviceId(), link);
191 - }
192 - }
193 -
194 - // Updates, if necessary the specified link and returns the appropriate event.
195 - private LinkEvent updateLink(ProviderId providerId, VersionedValue<Link> existingLink,
196 - LinkKey key, LinkDescription linkDescription, Timestamp timestamp) {
197 - // FIXME confirm Link update condition is OK
198 - if (existingLink.entity().type() == INDIRECT && linkDescription.type() == DIRECT) {
199 - synchronized (this) {
200 -
201 - VersionedValue<Link> updatedLink = new VersionedValue<Link>(
202 - new DefaultLink(providerId, existingLink.entity().src(), existingLink.entity().dst(),
203 - linkDescription.type()), true, timestamp);
204 - links.replace(key, existingLink, updatedLink);
205 -
206 - replaceLink(existingLink, updatedLink);
207 - // FIXME: notify peers.
208 - return new LinkEvent(LINK_UPDATED, updatedLink.entity());
209 - }
210 - }
211 - return null;
212 - }
213 -
214 - // update Egress and ingress link sets
215 - private void replaceLink(VersionedValue<Link> current, VersionedValue<Link> updated) {
216 - synchronized (this) {
217 - srcLinks.remove(current.entity().src().deviceId(), current);
218 - dstLinks.remove(current.entity().dst().deviceId(), current);
219 -
220 - srcLinks.put(current.entity().src().deviceId(), updated);
221 - dstLinks.put(current.entity().dst().deviceId(), updated);
222 - }
223 - }
224 -
225 - @Override
226 - public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
227 - synchronized (this) {
228 - LinkKey key = new LinkKey(src, dst);
229 - VersionedValue<Link> link = links.remove(key);
230 - if (link != null) {
231 - removeLink(link);
232 - // notify peers
233 - return new LinkEvent(LINK_REMOVED, link.entity());
234 - }
235 - return null;
236 - }
237 - }
238 -
239 - // update Egress and ingress link sets
240 - private void removeLink(VersionedValue<Link> link) {
241 - synchronized (this) {
242 - srcLinks.remove(link.entity().src().deviceId(), link);
243 - dstLinks.remove(link.entity().dst().deviceId(), link);
244 - }
245 - }
246 -}
...@@ -24,6 +24,7 @@ import org.onlab.onos.net.Port; ...@@ -24,6 +24,7 @@ import org.onlab.onos.net.Port;
24 import org.onlab.onos.net.PortNumber; 24 import org.onlab.onos.net.PortNumber;
25 import org.onlab.onos.net.device.DefaultDeviceDescription; 25 import org.onlab.onos.net.device.DefaultDeviceDescription;
26 import org.onlab.onos.net.device.DefaultPortDescription; 26 import org.onlab.onos.net.device.DefaultPortDescription;
27 +import org.onlab.onos.net.link.DefaultLinkDescription;
27 import org.onlab.onos.net.provider.ProviderId; 28 import org.onlab.onos.net.provider.ProviderId;
28 import org.onlab.onos.store.Timestamp; 29 import org.onlab.onos.store.Timestamp;
29 import org.onlab.packet.IpAddress; 30 import org.onlab.packet.IpAddress;
...@@ -58,6 +59,7 @@ public final class KryoPoolUtil { ...@@ -58,6 +59,7 @@ public final class KryoPoolUtil {
58 DefaultControllerNode.class, 59 DefaultControllerNode.class,
59 DefaultDevice.class, 60 DefaultDevice.class,
60 DefaultDeviceDescription.class, 61 DefaultDeviceDescription.class,
62 + DefaultLinkDescription.class,
61 MastershipRole.class, 63 MastershipRole.class,
62 Port.class, 64 Port.class,
63 DefaultPortDescription.class, 65 DefaultPortDescription.class,
......