blob: e115127dcd58d4385b0aab3aefa002fae42ed82c [file] [log] [blame]
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -07001package net.onrc.onos.core.topology;
2
3import static com.google.common.base.Preconditions.checkNotNull;
4
Yuta HIGUCHI4f328842014-08-28 17:23:09 -07005import java.util.ArrayList;
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -07006import java.util.Collection;
7import java.util.Collections;
8import java.util.HashMap;
9import java.util.LinkedList;
10import java.util.List;
11import java.util.Map;
12import java.util.Map.Entry;
13import java.util.SortedSet;
14import java.util.TreeSet;
15
16import javax.annotation.concurrent.Immutable;
17import javax.annotation.concurrent.NotThreadSafe;
18
19import net.floodlightcontroller.core.IFloodlightProviderService.Role;
20import net.floodlightcontroller.util.MACAddress;
21import net.onrc.onos.core.util.Dpid;
22import net.onrc.onos.core.util.LinkTuple;
23import net.onrc.onos.core.util.OnosInstanceId;
24import net.onrc.onos.core.util.PortNumber;
25import net.onrc.onos.core.util.SwitchPort;
26
27import org.slf4j.Logger;
28import org.slf4j.LoggerFactory;
29
30import com.google.common.collect.HashMultimap;
31import com.google.common.collect.ImmutableMultimap;
32import com.google.common.collect.Multimap;
33
34/**
35 * Immutable Topology snapshot.
36 */
37@Immutable
38public final class ImmutableTopologySnapshot
39 implements ImmutableTopology, ImmutableInternalTopology {
40
41 private static final Logger log = LoggerFactory
42 .getLogger(ImmutableTopologySnapshot.class);
43
44 /**
45 * Empty Topology.
46 */
47 public static final ImmutableTopologySnapshot EMPTY = new ImmutableTopologySnapshot();
48
49 // interface adaptor
50 private final BaseTopologyAdaptor adaptor;
51
52
53 // Mastership info
54 // Dpid -> [ (InstanceID, Role) ]
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -070055 private final Map<Dpid, SortedSet<MastershipData>> mastership;
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -070056
57 // DPID -> Switch
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -070058 private final Map<Dpid, SwitchData> switches;
59 private final Map<Dpid, Map<PortNumber, PortData>> ports;
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -070060
61 // Index from Port to Host
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -070062 private final Multimap<SwitchPort, HostData> hosts;
63 private final Map<MACAddress, HostData> mac2Host;
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -070064
65 // SwitchPort -> (type -> Link)
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -070066 private final Map<SwitchPort, Map<String, LinkData>> outgoingLinks;
67 private final Map<SwitchPort, Map<String, LinkData>> incomingLinks;
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -070068
69
70 // TODO Slice out Topology Builder interface.
71 // May need to change put*, remove* return values.
72 /**
73 * Immutable Topology Builder.
74 */
75 @NotThreadSafe
76 public static final class Builder {
77
78 private final ImmutableTopologySnapshot current;
79
80 /**
81 * Builder to start from empty topology.
82 */
83 private Builder() {
84 this.current = new ImmutableTopologySnapshot(EMPTY);
85 }
86
87 /**
88 * Builder to start building from existing topology.
89 *
90 * @param original topology to start building from
91 */
92 private Builder(final ImmutableTopologySnapshot original) {
93 // original must be internally mutable instance
94 this.current = original;
95 }
96
97
98 /**
99 * Gets the current InternalTopology being built.
100 *
101 * @return InternalTopology
102 */
103 BaseInternalTopology getCurrentInternal() {
104 return this.current;
105 }
106
107 /**
108 * Gets the current Topology being built.
109 *
110 * @return Topology
111 */
112 BaseTopology getCurrent() {
113 return this.current;
114 }
115
116 /**
117 * Builds the {@link ImmutableTopologySnapshot}.
118 *
119 * @return ImmutableTopologySnapshot
120 */
121 public ImmutableTopologySnapshot build() {
122 return new ImmutableTopologySnapshot(this);
123 }
124
125 // TODO Define error conditions for topology mutation
126 // - Element was already gone:
127 // Treat as error or silently ignore?
128 // - Removing element, where child element still exist:
129 // Treat as error or silently remove?
130
131 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700132 * Puts a SwitchData.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700133 *
134 * @param sw Switch to add. (Will be frozen if not already)
135 * @return Builder
136 */
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700137 public Builder putSwitch(SwitchData sw) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700138 checkNotNull(sw);
139
140 current.switches.put(sw.getDpid(), sw.freeze());
141 if (current.ports.get(sw.getDpid()) == null) {
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700142 current.ports.put(sw.getDpid(), new HashMap<PortNumber, PortData>());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700143 }
144 return this;
145 }
146
147 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700148 * Removes a SwitchData from this snapshot.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700149 * <p>
150 * Will also remove ports, if it has not been removed already.
151 *
152 * @param dpid Switch DPID
153 * @return Builder
154 */
155 public Builder removeSwitch(Dpid dpid) {
156 checkNotNull(dpid);
157
158 current.switches.remove(dpid);
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700159 Map<PortNumber, PortData> removedPorts = current.ports.remove(dpid);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700160 if (removedPorts != null && !removedPorts.isEmpty()) {
161 log.warn("Some ports were removed as side-effect of #removeSwitch({})", dpid);
162 }
163 return this;
164 }
165
166 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700167 * Puts a PortData.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700168 *
169 * @param port Port to add. (Will be frozen if not already)
170 * @return Builder
171 */
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700172 public Builder putPort(PortData port) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700173 checkNotNull(port);
174
175 // TODO check parent port and throw TopologyMutationFailed
176
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700177 Map<PortNumber, PortData> portMap = current.ports.get(port.getDpid());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700178 if (portMap == null) {
179 // shouldn't happen but just to be sure
180 portMap = new HashMap<>();
181 current.ports.put(port.getDpid(), portMap);
182 }
183 portMap.put(port.getPortNumber(), port.freeze());
184 return this;
185 }
186
187 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700188 * Removes a PortData from this snapshot.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700189 *
190 * @param port SwitchPort to remove
191 * @return Builder
192 */
193 public Builder removePort(SwitchPort port) {
194 checkNotNull(port);
195
196 removePort(port.getDpid(), port.getPortNumber());
197 return this;
198 }
199
200 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700201 * Removes a PortData from this snapshot.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700202 * <p>
203 * Will also remove ports, if it has not been removed already.
204 *
205 * @param dpid Switch DPID
206 * @param number PortNumber
207 * @return Builder
208 */
209 public Builder removePort(Dpid dpid, PortNumber number) {
210 checkNotNull(dpid);
211 checkNotNull(number);
212
213 // TODO sanity check:
214 // - Links should be removed
215 // - Host attachment point should be updated.
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700216 Map<PortNumber, PortData> portMap = current.ports.get(dpid);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700217 if (portMap != null) {
218 portMap.remove(number);
219 }
220 return this;
221 }
222
223 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700224 * Puts a LinkData.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700225 *
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700226 * @param link LinkData
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700227 * @return Builder
228 */
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700229 public Builder putLink(LinkData link) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700230 checkNotNull(link);
231
232 // TODO check ports and throw TopologyMutationFailed
233
234 // TODO remove host or ignore?
235
236 // TODO Add sanity check?
237 // - There cannot be 2 links in same direction between a port pair.
238 putLinkMap(current.outgoingLinks, link.getSrc(), link);
239 putLinkMap(current.incomingLinks, link.getDst(), link);
240 return this;
241 }
242
243 /**
244 * Helper method to update outgoingLinks, incomingLinks.
245 *
246 * @param linkMap outgoingLinks or incomingLinks to update
247 * @param port {@code linkMap} key to update
248 * @param link Link to add
249 */
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700250 private void putLinkMap(Map<SwitchPort, Map<String, LinkData>> linkMap,
251 SwitchPort port, LinkData link) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700252
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700253 Map<String, LinkData> linksOnPort = linkMap.get(port);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700254 if (linksOnPort == null) {
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700255 linksOnPort = new HashMap<String, LinkData>();
Yuta HIGUCHI4f328842014-08-28 17:23:09 -0700256 linkMap.put(port, linksOnPort);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700257 }
258 linksOnPort.put(link.getType(), link);
259 }
260
261 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700262 * Removes a LinkData from this snapshot.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700263 *
264 * @param link Link to remove
265 * @param type type of link to remove
266 * @return Builder
267 */
268 public Builder removeLink(LinkTuple link, String type) {
269 checkNotNull(link);
270
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700271 Map<String, LinkData> portLinks
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700272 = current.outgoingLinks.get(link.getSrc());
273 if (portLinks != null) {
274 // no conditional update here
275 portLinks.remove(type);
276 }
277 portLinks
278 = current.incomingLinks.get(link.getDst());
279 if (portLinks != null) {
280 // no conditional update here
281 portLinks.remove(type);
282 }
283 return this;
284 }
285
286 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700287 * Removes a LinkData from this snapshot.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700288 *
289 * @param link Link to remove
290 * @return Builder
291 */
292 public Builder removeLink(LinkTuple link) {
293 checkNotNull(link);
294
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700295 Map<String, LinkData> links = current.outgoingLinks.get(link.getSrc());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700296 if (links == null) {
297 // nothing to do
298 return this;
299 }
300
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700301 for (LinkData linkData : links.values()) {
302 removeLink(linkData.getLinkTuple(), linkData.getType());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700303 }
304 return this;
305 }
306
307 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700308 * Puts a HostData.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700309 * <p>
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700310 * Removes attachment points for previous HostData and update
311 * them with new HostData
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700312 *
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700313 * @param host HostData
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700314 * @return Builder
315 */
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700316 public Builder putHost(HostData host) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700317 checkNotNull(host);
318
319 // TODO check Link does not exist on port and throw TopologyMutationFailed
320
321 // Host cannot be simply put() to replace instance
322 // since we need to track attachment point update.
323 // remove -> put to replace all attachment points, etc. for now.
324
325 // remove old attachment points
326 removeHost(host.getMac());
327
328 // add new attachment points
329 for (SwitchPort port : host.getAttachmentPoints()) {
330 current.hosts.put(port, host);
331 }
332 current.mac2Host.put(host.getMac(), host);
333 return this;
334 }
335
336 /**
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700337 * Removes a HostData from this snapshot.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700338 *
339 * @param mac MACAddress of the Host to remove
340 * @return Builder
341 */
342 public Builder removeHost(MACAddress mac) {
343 checkNotNull(mac);
344
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700345 HostData host = current.mac2Host.remove(mac);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700346 if (host != null) {
347 for (SwitchPort port : host.getAttachmentPoints()) {
348 current.hosts.remove(port, host);
349 }
350 }
351 return this;
352 }
353
354 /**
355 * Puts a mastership change event.
356 *
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700357 * @param master MastershipData
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700358 * @return Builder
359 */
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700360 public Builder putSwitchMastershipData(MastershipData master) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700361 checkNotNull(master);
362
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700363 SortedSet<MastershipData> candidates
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700364 = current.mastership.get(master.getDpid());
365 if (candidates == null) {
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700366 // SortedSet, customized so that MASTER MastershipData appear
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700367 // earlier during iteration.
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700368 candidates = new TreeSet<>(new MastershipData.MasterFirstComparator());
Yuta HIGUCHI4f328842014-08-28 17:23:09 -0700369 current.mastership.put(master.getDpid(), candidates);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700370 }
371
372 // always replace
373 candidates.remove(master);
374 candidates.add(master);
375 return this;
376 }
377
378 /**
379 * Removes a mastership change event.
380 * <p>
381 * Note: Only Dpid and OnosInstanceId will be used to identify the
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700382 * {@link MastershipData} to remove.
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700383 *
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700384 * @param master {@link MastershipData} to remove. (Role is ignored)
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700385 * @return Builder
386 */
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700387 public Builder removeSwitchMastershipData(MastershipData master) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700388 checkNotNull(master);
389
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700390 SortedSet<MastershipData> candidates
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700391 = current.mastership.get(master.getDpid());
392 if (candidates == null) {
393 // nothing to do
394 return this;
395 }
396 candidates.remove(master);
397
398 return this;
399 }
400 }
401
402 /**
403 * Create an empty Topology.
404 */
405 private ImmutableTopologySnapshot() {
406 mastership = Collections.emptyMap();
407 switches = Collections.emptyMap();
408 ports = Collections.emptyMap();
409 hosts = ImmutableMultimap.of();
410 mac2Host = Collections.emptyMap();
411 outgoingLinks = Collections.emptyMap();
412 incomingLinks = Collections.emptyMap();
413 this.adaptor = new BaseTopologyAdaptor(this);
414 }
415
416 /**
417 * Constructor to create instance from Builder.
418 *
419 * @param builder Builder
420 */
421 private ImmutableTopologySnapshot(final Builder builder) {
422
423 // TODO Change to move semantics to avoid shallow copying or
424 // Shallow copies should be created using
425 // Immutable variant or wrapped by Unmodifiable.
426 //
427 // If we switched to Immutable* Collections,
428 // wrapping by Collections.unmodifiableCollection() can be removed.
429
430 // shallow copy Set in Map
431 this.mastership = new HashMap<>(builder.current.mastership.size());
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700432 for (Entry<Dpid, SortedSet<MastershipData>> e
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700433 : builder.current.mastership.entrySet()) {
434 this.mastership.put(e.getKey(), new TreeSet<>(e.getValue()));
435 }
436
437 this.switches = new HashMap<>(builder.current.switches);
438
439 // shallow copy Map in Map
440 this.ports = new HashMap<>(builder.current.ports.size());
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700441 for (Entry<Dpid, Map<PortNumber, PortData>> entry
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700442 : builder.current.ports.entrySet()) {
443 this.ports.put(entry.getKey(), new HashMap<>(entry.getValue()));
444 }
445
446 this.hosts =
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700447 HashMultimap.<SwitchPort, HostData>create(builder.current.hosts);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700448 this.mac2Host = new HashMap<>(builder.current.mac2Host);
449
450 // shallow copy Map in Map
451 this.outgoingLinks = new HashMap<>(builder.current.outgoingLinks.size());
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700452 for (Entry<SwitchPort, Map<String, LinkData>> entry
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700453 : builder.current.outgoingLinks.entrySet()) {
454 this.outgoingLinks.put(entry.getKey(), new HashMap<>(entry.getValue()));
455 }
456
457 // shallow copy Map in Map
458 this.incomingLinks = new HashMap<>(builder.current.incomingLinks.size());
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700459 for (Entry<SwitchPort, Map<String, LinkData>> entry
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700460 : builder.current.incomingLinks.entrySet()) {
461 this.incomingLinks.put(entry.getKey(), new HashMap<>(entry.getValue()));
462 }
463
464 this.adaptor = new BaseTopologyAdaptor(this);
465 }
466
467 /**
468 * Create internally mutable shallow copy of given instance.
469 * <p>
470 * Note: only expected to be used by Builder.
471 *
472 * @param original instance to copy from
473 */
474 private ImmutableTopologySnapshot(ImmutableTopologySnapshot original) {
475
476 // shallow copy Set in Map
477 this.mastership = new HashMap<>(original.mastership.size());
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700478 for (Entry<Dpid, SortedSet<MastershipData>> e
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700479 : original.mastership.entrySet()) {
480 this.mastership.put(e.getKey(), new TreeSet<>(e.getValue()));
481 }
482
483 this.switches = new HashMap<>(original.switches);
484
485 // shallow copy Map in Map
486 this.ports = new HashMap<>(original.ports.size());
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700487 for (Entry<Dpid, Map<PortNumber, PortData>> entry
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700488 : original.ports.entrySet()) {
489 this.ports.put(entry.getKey(), new HashMap<>(entry.getValue()));
490 }
491
492 this.hosts =
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700493 HashMultimap.<SwitchPort, HostData>create(original.hosts);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700494 this.mac2Host = new HashMap<>(original.mac2Host);
495
496 // shallow copy Map in Map
497 this.outgoingLinks = new HashMap<>(original.outgoingLinks.size());
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700498 for (Entry<SwitchPort, Map<String, LinkData>> entry
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700499 : original.outgoingLinks.entrySet()) {
500 this.outgoingLinks.put(entry.getKey(), new HashMap<>(entry.getValue()));
501 }
502
503 // shallow copy Map in Map
504 this.incomingLinks = new HashMap<>(original.incomingLinks.size());
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700505 for (Entry<SwitchPort, Map<String, LinkData>> entry
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700506 : original.incomingLinks.entrySet()) {
507 this.incomingLinks.put(entry.getKey(), new HashMap<>(entry.getValue()));
508 }
509
510 this.adaptor = new BaseTopologyAdaptor(this);
511 }
512
513
514 /**
515 * Gets the builder starting from empty topology.
516 *
517 * @return Builder
518 */
519 public static Builder initialBuilder() {
520 return new Builder();
521 }
522
523 /**
524 * Gets the builder starting from this topology.
525 *
526 * @return Builder
527 */
528 public Builder builder() {
529 return new Builder(new ImmutableTopologySnapshot(this));
530 }
531
532 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700533 public SwitchData getSwitchData(final Dpid dpid) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700534 return this.switches.get(dpid);
535 }
536
537 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700538 public Collection<SwitchData> getAllSwitchDataEntries() {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700539 return Collections.unmodifiableCollection(switches.values());
540 }
541
542 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700543 public PortData getPortData(final SwitchPort port) {
544 return getPortData(port.getDpid(), port.getPortNumber());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700545 }
546
547 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700548 public PortData getPortData(final Dpid dpid, PortNumber portNumber) {
549 Map<PortNumber, PortData> portMap = this.ports.get(dpid);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700550 if (portMap != null) {
551 return portMap.get(portNumber);
552 }
553 return null;
554 }
555
556 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700557 public Collection<PortData> getPortDataEntries(final Dpid dpid) {
558 Map<PortNumber, PortData> portList = ports.get(dpid);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700559 if (portList == null) {
560 return Collections.emptyList();
561 }
562 return Collections.unmodifiableCollection(portList.values());
563 }
564
565 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700566 public Collection<PortData> getAllPortDataEntries() {
567 List<PortData> dataEntries = new LinkedList<>();
568 for (Map<PortNumber, PortData> cm : ports.values()) {
569 dataEntries.addAll(cm.values());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700570 }
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700571 return Collections.unmodifiableCollection(dataEntries);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700572 }
573
574 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700575 public LinkData getLinkData(final LinkTuple linkId) {
576 Map<String, LinkData> links = this.outgoingLinks.get(linkId.getSrc());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700577 if (links == null) {
578 return null;
579 }
580
Yuta HIGUCHI98eaab52014-08-29 23:10:14 -0700581 // Should we look for Packet link first?
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700582 // => Not needed unless invariant is broken.
583
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700584 for (LinkData link : links.values()) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700585 if (link.getDst().equals(linkId.getDst())) {
586 return link;
587 }
588 }
589 return null;
590 }
591
592 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700593 public LinkData getLinkData(final LinkTuple linkId, final String type) {
594 Map<String, LinkData> links = this.outgoingLinks.get(linkId.getSrc());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700595 if (links == null) {
596 return null;
597 }
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700598 LinkData link = links.get(type);
Yuta HIGUCHI4f328842014-08-28 17:23:09 -0700599 if (link.getDst().equals(linkId.getDst())) {
600 return link;
601 }
602 return null;
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700603 }
604
605 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700606 public Collection<LinkData> getLinkDataEntriesFrom(SwitchPort srcPort) {
607 Map<String, LinkData> links = this.outgoingLinks.get(srcPort);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700608 if (links == null) {
609 return Collections.emptyList();
610 }
611
612 return Collections.unmodifiableCollection(links.values());
613 }
614
615 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700616 public Collection<LinkData> getLinkDataEntriesTo(SwitchPort dstPort) {
617 Map<String, LinkData> links = this.incomingLinks.get(dstPort);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700618 if (links == null) {
619 return Collections.emptyList();
620 }
621
622 return Collections.unmodifiableCollection(links.values());
623 }
624
625 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700626 public Collection<LinkData> getLinkDataEntries(final LinkTuple linkId) {
627 Map<String, LinkData> links = this.outgoingLinks.get(linkId.getSrc());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700628 if (links == null) {
629 return Collections.emptyList();
630 }
631
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700632 List<LinkData> linkDataEntries = new ArrayList<>();
633 for (LinkData ld : links.values()) {
634 if (ld.getDst().equals(linkId.getDst())) {
635 linkDataEntries.add(ld);
Yuta HIGUCHI4f328842014-08-28 17:23:09 -0700636 }
637 }
638
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700639 // unless invariant is broken, this should contain at most 1 element.
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700640 return linkDataEntries;
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700641 }
642
643 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700644 public Collection<LinkData> getAllLinkDataEntries() {
645 List<LinkData> dataEntries = new LinkedList<>();
646 for (Map<String, LinkData> cm : outgoingLinks.values()) {
647 dataEntries.addAll(cm.values());
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700648 }
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700649 return Collections.unmodifiableCollection(dataEntries);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700650 }
651
652 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700653 public HostData getHostData(final MACAddress mac) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700654 return this.mac2Host.get(mac);
655 }
656
657 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700658 public Collection<HostData> getHostDataEntries(SwitchPort port) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700659 return Collections.unmodifiableCollection(this.hosts.get(port));
660 }
661
662 @Override
Yuta HIGUCHI93d35ea2014-08-31 23:26:13 -0700663 public Collection<HostData> getAllHostDataEntries() {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700664 return Collections.unmodifiableCollection(mac2Host.values());
665 }
666
667 /**
668 * Gets the master instance ID for a switch.
669 *
670 * @param dpid switch dpid
671 * @return master instance ID or null if there is no master
672 */
Yuta HIGUCHI4f328842014-08-28 17:23:09 -0700673 @Override
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700674 public OnosInstanceId getSwitchMaster(Dpid dpid) {
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700675 final SortedSet<MastershipData> candidates = mastership.get(dpid);
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700676 if (candidates == null) {
677 return null;
678 }
Yuta HIGUCHId8fd2f52014-09-01 23:19:45 -0700679 for (MastershipData candidate : candidates) {
Yuta HIGUCHIeb3733a2014-08-26 21:38:16 -0700680 if (candidate.getRole() == Role.MASTER) {
681 return candidate.getOnosInstanceId();
682 }
683 }
684 return null;
685 }
686
687
688 // TODO find better way to delegate following to interface adaptor
689
690 @Override
691 public Switch getSwitch(Dpid dpid) {
692 return adaptor.getSwitch(dpid);
693 }
694
695 @Override
696 public Iterable<Switch> getSwitches() {
697 return adaptor.getSwitches();
698 }
699
700 @Override
701 public Port getPort(Dpid dpid, PortNumber number) {
702 return adaptor.getPort(dpid, number);
703 }
704
705 @Override
706 public Port getPort(SwitchPort port) {
707 return adaptor.getPort(port);
708 }
709
710 @Override
711 public Collection<Port> getPorts(Dpid dpid) {
712 return adaptor.getPorts(dpid);
713 }
714
715 @Override
716 public Link getOutgoingLink(Dpid dpid, PortNumber number) {
717 return adaptor.getOutgoingLink(dpid, number);
718 }
719
720 @Override
721 public Link getOutgoingLink(SwitchPort port) {
722 return adaptor.getOutgoingLink(port);
723 }
724
725 @Override
726 public Link getOutgoingLink(Dpid dpid, PortNumber number, String type) {
727 return adaptor.getOutgoingLink(dpid, number, type);
728 }
729
730 @Override
731 public Link getOutgoingLink(SwitchPort port, String type) {
732 return adaptor.getOutgoingLink(port, type);
733 }
734
735 @Override
736 public Collection<Link> getOutgoingLinks(SwitchPort port) {
737 return adaptor.getOutgoingLinks(port);
738 }
739
740 @Override
741 public Link getIncomingLink(Dpid dpid, PortNumber number) {
742 return adaptor.getIncomingLink(dpid, number);
743 }
744
745 @Override
746 public Link getIncomingLink(SwitchPort port) {
747 return adaptor.getIncomingLink(port);
748 }
749
750 @Override
751 public Link getIncomingLink(Dpid dpid, PortNumber number, String type) {
752 return adaptor.getIncomingLink(dpid, number, type);
753 }
754
755 @Override
756 public Link getIncomingLink(SwitchPort port, String type) {
757 return adaptor.getIncomingLink(port, type);
758 }
759
760 @Override
761 public Collection<Link> getIncomingLinks(SwitchPort port) {
762 return adaptor.getIncomingLinks(port);
763 }
764
765 @Override
766 public Link getLink(Dpid srcDpid, PortNumber srcNumber,
767 Dpid dstDpid, PortNumber dstNumber) {
768
769 return adaptor.getLink(srcDpid, srcNumber, dstDpid, dstNumber);
770 }
771
772 @Override
773 public Link getLink(Dpid srcDpid, PortNumber srcNumber,
774 Dpid dstDpid, PortNumber dstNumber,
775 String type) {
776
777 return adaptor.getLink(srcDpid, srcNumber, dstDpid, dstNumber, type);
778 }
779
780 @Override
781 public Iterable<Link> getLinks() {
782 return adaptor.getLinks();
783 }
784
785 @Override
786 public Host getHostByMac(MACAddress address) {
787 return adaptor.getHostByMac(address);
788 }
789
790 @Override
791 public Iterable<Host> getHosts() {
792 return adaptor.getHosts();
793 }
794
795 @Override
796 public Collection<Host> getHosts(SwitchPort port) {
797 return adaptor.getHosts(port);
798 }
799}