blob: 5ce3729de7305759a092b14aacf7e35879026874 [file] [log] [blame]
Jonathan Hart472062d2014-04-03 10:56:48 -07001package net.onrc.onos.core.topology;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -08002
Yuta HIGUCHIfa742842014-07-03 22:35:13 -07003import java.util.Collection;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -08004import java.util.Collections;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -08005import java.util.concurrent.ConcurrentHashMap;
6import java.util.concurrent.ConcurrentMap;
Jonathan Hart26f291b2014-02-18 16:57:24 -08007import java.util.concurrent.locks.Lock;
8import java.util.concurrent.locks.ReadWriteLock;
9import java.util.concurrent.locks.ReentrantReadWriteLock;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080010
11import net.floodlightcontroller.util.MACAddress;
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -070012import net.onrc.onos.core.util.Dpid;
13import net.onrc.onos.core.util.PortNumber;
Jonathan Hart25bd53e2014-04-30 23:44:09 -070014import net.onrc.onos.core.util.SwitchPort;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080015
16import org.slf4j.Logger;
17import org.slf4j.LoggerFactory;
18
Yuta HIGUCHIfa742842014-07-03 22:35:13 -070019import com.google.common.collect.HashMultimap;
20import com.google.common.collect.Multimap;
21import com.google.common.collect.Multimaps;
22
Jonathan Harte37e4e22014-05-13 19:12:02 -070023public class TopologyImpl implements Topology {
Ray Milkey269ffb92014-04-03 14:43:30 -070024 @SuppressWarnings("unused")
Jonathan Harte37e4e22014-05-13 19:12:02 -070025 private static final Logger log = LoggerFactory.getLogger(TopologyImpl.class);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080026
Ray Milkey269ffb92014-04-03 14:43:30 -070027 // DPID -> Switch
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -070028 private final ConcurrentMap<Dpid, Switch> switches;
Yuta HIGUCHIfa742842014-07-03 22:35:13 -070029 // XXX may need to be careful when shallow copying.
30 private final ConcurrentMap<Dpid, ConcurrentMap<PortNumber, Port>> ports;
31
32 // Index from Port to Device
33 private final Multimap<SwitchPort, Device> devices;
Jonathan Hart25bd53e2014-04-30 23:44:09 -070034 private final ConcurrentMap<MACAddress, Device> mac2Device;
35
36 private final ConcurrentMap<SwitchPort, Link> outgoingLinks;
37 private final ConcurrentMap<SwitchPort, Link> incomingLinks;
Yuta HIGUCHI5d2d8d42014-02-20 22:22:53 -080038
Ray Milkey269ffb92014-04-03 14:43:30 -070039 private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
40 private Lock readLock = readWriteLock.readLock();
41 // TODO use the write lock after refactor
42 private Lock writeLock = readWriteLock.writeLock();
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080043
Jonathan Harte37e4e22014-05-13 19:12:02 -070044 public TopologyImpl() {
Ray Milkey269ffb92014-04-03 14:43:30 -070045 // TODO: Does these object need to be stored in Concurrent Collection?
46 switches = new ConcurrentHashMap<>();
Yuta HIGUCHIfa742842014-07-03 22:35:13 -070047 ports = new ConcurrentHashMap<>();
48 devices = Multimaps.synchronizedMultimap(
49 HashMultimap.<SwitchPort, Device>create());
Ray Milkey269ffb92014-04-03 14:43:30 -070050 mac2Device = new ConcurrentHashMap<>();
Jonathan Hart25bd53e2014-04-30 23:44:09 -070051 outgoingLinks = new ConcurrentHashMap<>();
52 incomingLinks = new ConcurrentHashMap<>();
Ray Milkey269ffb92014-04-03 14:43:30 -070053 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080054
Ray Milkey269ffb92014-04-03 14:43:30 -070055 @Override
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -070056 public Switch getSwitch(Dpid dpid) {
Ray Milkey269ffb92014-04-03 14:43:30 -070057 // TODO Check if it is safe to directly return this Object.
58 return switches.get(dpid);
59 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080060
Yuta HIGUCHIfa742842014-07-03 22:35:13 -070061 // Only add switch.
Ray Milkey269ffb92014-04-03 14:43:30 -070062 protected void putSwitch(Switch sw) {
63 switches.put(sw.getDpid(), sw);
Yuta HIGUCHIfa742842014-07-03 22:35:13 -070064 ports.putIfAbsent(sw.getDpid(), new ConcurrentHashMap<PortNumber, Port>());
Ray Milkey269ffb92014-04-03 14:43:30 -070065 }
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080066
Yuta HIGUCHIfa742842014-07-03 22:35:13 -070067 // TODO remove me when ready
Ray Milkey269ffb92014-04-03 14:43:30 -070068 protected void removeSwitch(Long dpid) {
Yuta HIGUCHIfa742842014-07-03 22:35:13 -070069 removeSwitch(new Dpid(dpid));
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -070070 }
71
Yuta HIGUCHIfa742842014-07-03 22:35:13 -070072 // XXX Will remove ports in snapshot as side-effect.
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -070073 protected void removeSwitch(Dpid dpid) {
Ray Milkey269ffb92014-04-03 14:43:30 -070074 switches.remove(dpid);
Yuta HIGUCHIfa742842014-07-03 22:35:13 -070075 ports.remove(dpid);
76 }
77
78 // This method is expected to be serialized by writeLock.
79 protected void putPort(Port port) {
80 ConcurrentMap<PortNumber, Port> portMap = ports.get(port.getDpid());
81 if (portMap == null) {
82 portMap = new ConcurrentHashMap<>();
83 ConcurrentMap<PortNumber, Port> existing =
84 ports.putIfAbsent(port.getDpid(), portMap);
85 if (existing != null) {
86 // port map was added concurrently, using theirs
87 portMap = existing;
88 }
89 }
90 portMap.put(port.getNumber(), port);
91 }
92
93 protected void removePort(Port port) {
94 ConcurrentMap<PortNumber, Port> portMap = ports.get(port.getDpid());
95 if (portMap != null) {
96 portMap.remove(port.getNumber());
97 }
Ray Milkey269ffb92014-04-03 14:43:30 -070098 }
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080099
Ray Milkey269ffb92014-04-03 14:43:30 -0700100 @Override
101 public Iterable<Switch> getSwitches() {
102 // TODO Check if it is safe to directly return this Object.
103 return Collections.unmodifiableCollection(switches.values());
104 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800105
Ray Milkey269ffb92014-04-03 14:43:30 -0700106 @Override
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700107 public Port getPort(Dpid dpid, PortNumber number) {
Yuta HIGUCHIfa742842014-07-03 22:35:13 -0700108 ConcurrentMap<PortNumber, Port> portMap = ports.get(dpid);
109 if (portMap != null) {
110 return portMap.get(number);
Ray Milkey269ffb92014-04-03 14:43:30 -0700111 }
112 return null;
113 }
Pavlin Radoslavov06df22a2014-02-18 19:16:27 -0800114
Ray Milkey269ffb92014-04-03 14:43:30 -0700115 @Override
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700116 public Port getPort(SwitchPort port) {
117 return getPort(port.dpid(), port.port());
Jonathan Hart25bd53e2014-04-30 23:44:09 -0700118 }
119
120 @Override
Yuta HIGUCHIfa742842014-07-03 22:35:13 -0700121 public Collection<Port> getPorts(Dpid dpid) {
122 ConcurrentMap<PortNumber, Port> portMap = ports.get(dpid);
123 if (portMap == null) {
124 return Collections.emptyList();
125 }
126 return Collections.unmodifiableCollection(portMap.values());
127 }
128
129 @Override
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700130 public Link getOutgoingLink(Dpid dpid, PortNumber number) {
131 return outgoingLinks.get(new SwitchPort(dpid, number));
Ray Milkey269ffb92014-04-03 14:43:30 -0700132 }
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800133
Ray Milkey269ffb92014-04-03 14:43:30 -0700134 @Override
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700135 public Link getOutgoingLink(SwitchPort port) {
136 return outgoingLinks.get(port);
137 }
138
139 @Override
140 public Link getIncomingLink(Dpid dpid, PortNumber number) {
141 return incomingLinks.get(new SwitchPort(dpid, number));
142 }
143
144 @Override
145 public Link getIncomingLink(SwitchPort port) {
146 return incomingLinks.get(port);
147 }
148
149 @Override
150 public Link getLink(Dpid srcDpid, PortNumber srcNumber,
151 Dpid dstDpid, PortNumber dstNumber) {
152
Jonathan Hart25bd53e2014-04-30 23:44:09 -0700153 Link link = getOutgoingLink(srcDpid, srcNumber);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700154 if (link == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700155 return null;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700156 }
157 if (!link.getDstSwitch().getDpid().equals(dstDpid)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700158 return null;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700159 }
160 if (!link.getDstPort().getNumber().equals(dstNumber)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700161 return null;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700162 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700163 return link;
164 }
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800165
Ray Milkey269ffb92014-04-03 14:43:30 -0700166 @Override
167 public Iterable<Link> getLinks() {
Jonathan Hart25bd53e2014-04-30 23:44:09 -0700168 return Collections.unmodifiableCollection(outgoingLinks.values());
169 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800170
Jonathan Hart25bd53e2014-04-30 23:44:09 -0700171 protected void putLink(Link link) {
172 outgoingLinks.put(link.getSrcPort().asSwitchPort(), link);
173 incomingLinks.put(link.getDstPort().asSwitchPort(), link);
174 }
175
176 protected void removeLink(Link link) {
177 outgoingLinks.remove(link.getSrcPort().asSwitchPort(), link);
178 incomingLinks.remove(link.getDstPort().asSwitchPort(), link);
Ray Milkey269ffb92014-04-03 14:43:30 -0700179 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800180
Ray Milkey269ffb92014-04-03 14:43:30 -0700181 @Override
Ray Milkey269ffb92014-04-03 14:43:30 -0700182 public Device getDeviceByMac(MACAddress address) {
183 return mac2Device.get(address);
184 }
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -0800185
TeruU65bc5ff2014-04-23 22:22:32 -0700186 @Override
187 public Iterable<Device> getDevices() {
188 return Collections.unmodifiableCollection(mac2Device.values());
189 }
190
Yuta HIGUCHIfa742842014-07-03 22:35:13 -0700191 @Override
192 public Collection<Device> getDevices(SwitchPort port) {
193 return Collections.unmodifiableCollection(devices.get(port));
194 }
195
196 // This method is expected to be serialized by writeLock.
197 // XXX new or updated device
Ray Milkey269ffb92014-04-03 14:43:30 -0700198 protected void putDevice(Device device) {
Yuta HIGUCHIfa742842014-07-03 22:35:13 -0700199 // assuming Device is immutable
200 Device oldDevice = mac2Device.get(device.getMacAddress());
201 if (oldDevice != null) {
202 // remove old attachment point
203 removeDevice(oldDevice);
204 }
205 // add new attachment points
206 for (Port port : device.getAttachmentPoints()) {
207 // TODO Won't need remove() if we define Device equality to reflect
208 // all of it's fields.
209 devices.remove(port.asSwitchPort(), device);
210 devices.put(port.asSwitchPort(), device);
211 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700212 mac2Device.put(device.getMacAddress(), device);
Ray Milkey269ffb92014-04-03 14:43:30 -0700213 }
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -0800214
Ray Milkey269ffb92014-04-03 14:43:30 -0700215 protected void removeDevice(Device device) {
Yuta HIGUCHIfa742842014-07-03 22:35:13 -0700216 for (Port port : device.getAttachmentPoints()) {
217 devices.remove(port.asSwitchPort(), device);
218 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700219 mac2Device.remove(device.getMacAddress());
Ray Milkey269ffb92014-04-03 14:43:30 -0700220 }
Jonathan Hart26f291b2014-02-18 16:57:24 -0800221
Ray Milkey269ffb92014-04-03 14:43:30 -0700222 @Override
223 public void acquireReadLock() {
224 readLock.lock();
225 }
Jonathan Hart26f291b2014-02-18 16:57:24 -0800226
Ray Milkey269ffb92014-04-03 14:43:30 -0700227 @Override
228 public void releaseReadLock() {
229 readLock.unlock();
230 }
Pavlin Radoslavov8ffb8bf2014-02-20 15:34:26 -0800231
Ray Milkey269ffb92014-04-03 14:43:30 -0700232 protected void acquireWriteLock() {
233 writeLock.lock();
234 }
Pavlin Radoslavov8ffb8bf2014-02-20 15:34:26 -0800235
Ray Milkey269ffb92014-04-03 14:43:30 -0700236 protected void releaseWriteLock() {
237 writeLock.unlock();
238 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800239}