blob: d10c3a46ebb31b0ef19fea962a7e08ec1a456cfd [file] [log] [blame]
tom4c6606f2014-09-07 11:11:21 -07001package org.onlab.onos.net.trivial.impl;
2
tomeadbb462014-09-07 16:10:19 -07003import com.google.common.collect.HashMultimap;
4import com.google.common.collect.ImmutableSet;
5import com.google.common.collect.Multimap;
6import org.onlab.onos.net.ConnectPoint;
7import org.onlab.onos.net.DefaultLink;
8import org.onlab.onos.net.DeviceId;
9import org.onlab.onos.net.Link;
10import org.onlab.onos.net.link.LinkDescription;
11import org.onlab.onos.net.link.LinkEvent;
12import org.onlab.onos.net.provider.ProviderId;
13
14import java.util.Collections;
15import java.util.HashSet;
16import java.util.Map;
17import java.util.Objects;
18import java.util.Set;
19import java.util.concurrent.ConcurrentHashMap;
20
tomd176fc42014-09-08 00:12:30 -070021import static org.onlab.onos.net.Link.Type.DIRECT;
22import static org.onlab.onos.net.Link.Type.INDIRECT;
23import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED;
24import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
25import static org.onlab.onos.net.link.LinkEvent.Type.LINK_UPDATED;
26
tom4c6606f2014-09-07 11:11:21 -070027/**
28 * Manages inventory of infrastructure links using trivial in-memory link
29 * implementation.
30 */
tomeadbb462014-09-07 16:10:19 -070031class SimpleLinkStore {
32
33 // Link inventory
34 private final Map<LinkKey, DefaultLink> links = new ConcurrentHashMap<>();
35
36 // Egress and ingress link sets
37 private final Multimap<DeviceId, Link> srcLinks = HashMultimap.create();
38 private final Multimap<DeviceId, Link> dstLinks = HashMultimap.create();
39
40 private static final Set<Link> EMPTY = ImmutableSet.copyOf(new Link[]{});
41
42 /**
43 * Returns the number of links in the store.
44 *
45 * @return number of links
46 */
47 int getLinkCount() {
48 return links.size();
49 }
50
51 /**
52 * Returns an iterable collection of all links in the inventory.
53 *
54 * @return collection of all links
55 */
56 Iterable<Link> getLinks() {
57 return Collections.unmodifiableSet(new HashSet<Link>(links.values()));
58 }
59
60 /**
61 * Returns all links egressing from the specified device.
62 *
63 * @param deviceId device identifier
64 * @return set of device links
65 */
66 Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
67 return ImmutableSet.copyOf(srcLinks.get(deviceId));
68 }
69
70 /**
71 * Returns all links ingressing from the specified device.
72 *
73 * @param deviceId device identifier
74 * @return set of device links
75 */
76 Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
77 return ImmutableSet.copyOf(dstLinks.get(deviceId));
78 }
79
80 /**
tomd176fc42014-09-08 00:12:30 -070081 * Returns the link between the two end-points.
82 *
83 * @param src source connection point
84 * @param dst destination connection point
85 * @return link or null if one not found between the end-points
86 */
87 Link getLink(ConnectPoint src, ConnectPoint dst) {
88 return links.get(new LinkKey(src, dst));
89 }
90
91 /**
tomeadbb462014-09-07 16:10:19 -070092 * Returns all links egressing from the specified connection point.
93 *
94 * @param src source connection point
95 * @return set of connection point links
96 */
97 Set<Link> getEgressLinks(ConnectPoint src) {
98 Set<Link> egress = new HashSet<>();
99 for (Link link : srcLinks.get(src.deviceId())) {
100 if (link.src().equals(src)) {
101 egress.add(link);
102 }
103 }
104 return egress;
105 }
106
107 /**
108 * Returns all links ingressing to the specified connection point.
109 *
110 * @param dst destination connection point
111 * @return set of connection point links
112 */
113 Set<Link> getIngressLinks(ConnectPoint dst) {
114 Set<Link> ingress = new HashSet<>();
115 for (Link link : dstLinks.get(dst.deviceId())) {
tomd176fc42014-09-08 00:12:30 -0700116 if (link.dst().equals(dst)) {
tomeadbb462014-09-07 16:10:19 -0700117 ingress.add(link);
118 }
119 }
120 return ingress;
121 }
122
tomeadbb462014-09-07 16:10:19 -0700123 /**
124 * Creates a new link, or updates an existing one, based on the given
125 * information.
126 *
127 * @param providerId provider identity
128 * @param linkDescription link description
129 * @return create or update link event, or null if no change resulted
130 */
131 public LinkEvent createOrUpdateLink(ProviderId providerId,
132 LinkDescription linkDescription) {
133 LinkKey key = new LinkKey(linkDescription.src(), linkDescription.dst());
134 DefaultLink link = links.get(key);
135 if (link == null) {
136 return createLink(providerId, key, linkDescription);
137 }
tomd176fc42014-09-08 00:12:30 -0700138 return updateLink(providerId, link, key, linkDescription);
tomeadbb462014-09-07 16:10:19 -0700139 }
140
141 // Creates and stores the link and returns the appropriate event.
142 private LinkEvent createLink(ProviderId providerId, LinkKey key,
143 LinkDescription linkDescription) {
144 DefaultLink link = new DefaultLink(providerId, key.src, key.dst,
145 linkDescription.type());
146 synchronized (this) {
147 links.put(key, link);
148 srcLinks.put(link.src().deviceId(), link);
149 dstLinks.put(link.dst().deviceId(), link);
150 }
tomd176fc42014-09-08 00:12:30 -0700151 return new LinkEvent(LINK_ADDED, link);
tomeadbb462014-09-07 16:10:19 -0700152 }
153
154 // Updates, if necessary the specified link and returns the appropriate event.
tomd176fc42014-09-08 00:12:30 -0700155 private LinkEvent updateLink(ProviderId providerId, DefaultLink link,
156 LinkKey key, LinkDescription linkDescription) {
157 if (link.type() == INDIRECT && linkDescription.type() == DIRECT) {
158 synchronized (this) {
159 srcLinks.remove(link.src().deviceId(), link);
160 dstLinks.remove(link.dst().deviceId(), link);
161
162 DefaultLink updated =
163 new DefaultLink(providerId, link.src(), link.dst(),
164 linkDescription.type());
165 links.put(key, updated);
166 srcLinks.put(link.src().deviceId(), updated);
167 dstLinks.put(link.dst().deviceId(), updated);
168 return new LinkEvent(LINK_UPDATED, updated);
169 }
170 }
tomeadbb462014-09-07 16:10:19 -0700171 return null;
172 }
173
174 /**
175 * Removes the link based on the specified information.
176 *
177 * @param src link source
178 * @param dst link destination
179 * @return remove link event, or null if no change resulted
180 */
181 LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
182 synchronized (this) {
183 Link link = links.remove(new LinkKey(src, dst));
tomd176fc42014-09-08 00:12:30 -0700184 if (link != null) {
185 srcLinks.remove(link.src().deviceId(), link);
186 dstLinks.remove(link.dst().deviceId(), link);
187 return new LinkEvent(LINK_REMOVED, link);
188 }
189 return null;
tomeadbb462014-09-07 16:10:19 -0700190 }
191 }
192
193 // Auxiliary key to track links.
194 private class LinkKey {
195 final ConnectPoint src;
196 final ConnectPoint dst;
197
198 LinkKey(ConnectPoint src, ConnectPoint dst) {
199 this.src = src;
200 this.dst = dst;
201 }
202
203 @Override
204 public int hashCode() {
205 return Objects.hash(src, dst);
206 }
207
208 @Override
209 public boolean equals(Object obj) {
210 if (obj instanceof LinkKey) {
211 final LinkKey other = (LinkKey) obj;
212 return Objects.equals(this.src, other.src) &&
213 Objects.equals(this.dst, other.dst);
214 }
215 return false;
216 }
217 }
tom4c6606f2014-09-07 11:11:21 -0700218}