blob: 94a3f0514d8f6a793a512bd00d1f309dededc6f3 [file] [log] [blame]
tom202175a2014-09-19 19:00:11 -07001package org.onlab.onos.net.trivial.impl;
tom7869ad92014-09-09 14:32:08 -07002
alshabib51622f72014-09-11 11:22:33 -07003import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
4import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
5import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED;
6import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED;
tom5bcc9462014-09-19 10:11:31 -07007import static org.slf4j.LoggerFactory.getLogger;
alshabib51622f72014-09-11 11:22:33 -07008
9import java.util.Collections;
10import java.util.HashSet;
11import java.util.Map;
12import java.util.Set;
13import java.util.concurrent.ConcurrentHashMap;
tom7869ad92014-09-09 14:32:08 -070014
tom5bcc9462014-09-19 10:11:31 -070015import org.apache.felix.scr.annotations.Activate;
16import org.apache.felix.scr.annotations.Component;
17import org.apache.felix.scr.annotations.Deactivate;
18import org.apache.felix.scr.annotations.Service;
tom7869ad92014-09-09 14:32:08 -070019import org.onlab.onos.net.ConnectPoint;
Ayaka Koshibee5652752014-09-10 23:27:34 -070020import org.onlab.onos.net.DefaultHost;
tom7869ad92014-09-09 14:32:08 -070021import org.onlab.onos.net.DeviceId;
22import org.onlab.onos.net.Host;
23import org.onlab.onos.net.HostId;
24import org.onlab.onos.net.host.HostDescription;
25import org.onlab.onos.net.host.HostEvent;
tom5bcc9462014-09-19 10:11:31 -070026import org.onlab.onos.net.host.HostStore;
tomf80c9722014-09-24 14:49:18 -070027import org.onlab.onos.net.host.HostStoreDelegate;
Jonathan Hartac60c082014-09-23 08:55:17 -070028import org.onlab.onos.net.host.PortAddresses;
tom7869ad92014-09-09 14:32:08 -070029import org.onlab.onos.net.provider.ProviderId;
tomf80c9722014-09-24 14:49:18 -070030import org.onlab.onos.store.AbstractStore;
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -070031import org.onlab.packet.IpPrefix;
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070032import org.onlab.packet.MacAddress;
33import org.onlab.packet.VlanId;
Jonathan Hartac60c082014-09-23 08:55:17 -070034import org.slf4j.Logger;
tom7869ad92014-09-09 14:32:08 -070035
Ayaka Koshibee5652752014-09-10 23:27:34 -070036import com.google.common.collect.HashMultimap;
37import com.google.common.collect.ImmutableSet;
38import com.google.common.collect.Multimap;
Jonathan Hartc884f1b2014-09-24 11:53:33 -070039import com.google.common.collect.Sets;
Ayaka Koshibee5652752014-09-10 23:27:34 -070040
tom7869ad92014-09-09 14:32:08 -070041/**
42 * Manages inventory of end-station hosts using trivial in-memory
43 * implementation.
44 */
tom5bcc9462014-09-19 10:11:31 -070045@Component(immediate = true)
46@Service
tomf80c9722014-09-24 14:49:18 -070047public class SimpleHostStore
48 extends AbstractStore<HostEvent, HostStoreDelegate>
49 implements HostStore {
tom7869ad92014-09-09 14:32:08 -070050
tom5bcc9462014-09-19 10:11:31 -070051 private final Logger log = getLogger(getClass());
52
53 // Host inventory
tom7869ad92014-09-09 14:32:08 -070054 private final Map<HostId, Host> hosts = new ConcurrentHashMap<>();
55
tom5bcc9462014-09-19 10:11:31 -070056 // Hosts tracked by their location
Ayaka Koshibee5652752014-09-10 23:27:34 -070057 private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
tome615ee42014-09-11 10:52:10 -070058
Jonathan Hart43c182c2014-09-23 11:13:42 -070059 private final Map<ConnectPoint, PortAddresses> portAddresses =
60 new ConcurrentHashMap<>();
61
tom5bcc9462014-09-19 10:11:31 -070062 @Activate
63 public void activate() {
64 log.info("Started");
65 }
66
67 @Deactivate
68 public void deactivate() {
69 log.info("Stopped");
70 }
71
72 @Override
73 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
74 HostDescription hostDescription) {
Ayaka Koshibee5652752014-09-10 23:27:34 -070075 Host host = hosts.get(hostId);
76 if (host == null) {
77 return createHost(providerId, hostId, hostDescription);
78 }
79 return updateHost(providerId, host, hostDescription);
80 }
81
82 // creates a new host and sends HOST_ADDED
83 private HostEvent createHost(ProviderId providerId, HostId hostId,
toma56d5fe2014-09-17 11:05:47 -070084 HostDescription descr) {
Ayaka Koshibee5652752014-09-10 23:27:34 -070085 DefaultHost newhost = new DefaultHost(providerId, hostId,
toma56d5fe2014-09-17 11:05:47 -070086 descr.hwAddress(),
87 descr.vlan(),
88 descr.location(),
89 descr.ipAddresses());
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -070090 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -070091 hosts.put(hostId, newhost);
92 locations.put(descr.location(), newhost);
93 }
94 return new HostEvent(HOST_ADDED, newhost);
95 }
96
97 // checks for type of update to host, sends appropriate event
98 private HostEvent updateHost(ProviderId providerId, Host host,
toma56d5fe2014-09-17 11:05:47 -070099 HostDescription descr) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700100 DefaultHost updated;
101 HostEvent event;
toma56d5fe2014-09-17 11:05:47 -0700102 if (!host.location().equals(descr.location())) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700103 updated = new DefaultHost(providerId, host.id(),
toma56d5fe2014-09-17 11:05:47 -0700104 host.mac(),
105 host.vlan(),
106 descr.location(),
107 host.ipAddresses());
Ayaka Koshibee5652752014-09-10 23:27:34 -0700108 event = new HostEvent(HOST_MOVED, updated);
toma56d5fe2014-09-17 11:05:47 -0700109
Ayaka Koshibe1a100982014-09-13 19:32:19 -0700110 } else if (!(host.ipAddresses().equals(descr.ipAddresses()))) {
111 updated = new DefaultHost(providerId, host.id(),
toma56d5fe2014-09-17 11:05:47 -0700112 host.mac(),
113 host.vlan(),
114 descr.location(),
115 descr.ipAddresses());
Ayaka Koshibe1a100982014-09-13 19:32:19 -0700116 event = new HostEvent(HOST_UPDATED, updated);
117 } else {
118 return null;
Ayaka Koshibee5652752014-09-10 23:27:34 -0700119 }
120 synchronized (this) {
121 hosts.put(host.id(), updated);
122 locations.remove(host.location(), host);
123 locations.put(updated.location(), updated);
124 }
125 return event;
tom7869ad92014-09-09 14:32:08 -0700126 }
127
tom5bcc9462014-09-19 10:11:31 -0700128 @Override
129 public HostEvent removeHost(HostId hostId) {
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700130 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700131 Host host = hosts.remove(hostId);
132 if (host != null) {
133 locations.remove((host.location()), host);
134 return new HostEvent(HOST_REMOVED, host);
135 }
136 return null;
137 }
tom7869ad92014-09-09 14:32:08 -0700138 }
139
tom5bcc9462014-09-19 10:11:31 -0700140 @Override
141 public int getHostCount() {
tom7869ad92014-09-09 14:32:08 -0700142 return hosts.size();
143 }
144
tom5bcc9462014-09-19 10:11:31 -0700145 @Override
146 public Iterable<Host> getHosts() {
toma56d5fe2014-09-17 11:05:47 -0700147 return Collections.unmodifiableSet(new HashSet<>(hosts.values()));
tom7869ad92014-09-09 14:32:08 -0700148 }
149
tom5bcc9462014-09-19 10:11:31 -0700150 @Override
151 public Host getHost(HostId hostId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700152 return hosts.get(hostId);
tom7869ad92014-09-09 14:32:08 -0700153 }
154
tom5bcc9462014-09-19 10:11:31 -0700155 @Override
156 public Set<Host> getHosts(VlanId vlanId) {
toma56d5fe2014-09-17 11:05:47 -0700157 Set<Host> vlanset = new HashSet<>();
Ayaka Koshibee5652752014-09-10 23:27:34 -0700158 for (Host h : hosts.values()) {
Ayaka Koshibe04a1a4e2014-09-11 14:31:29 -0700159 if (h.vlan().equals(vlanId)) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700160 vlanset.add(h);
161 }
162 }
163 return vlanset;
tom7869ad92014-09-09 14:32:08 -0700164 }
165
tom5bcc9462014-09-19 10:11:31 -0700166 @Override
167 public Set<Host> getHosts(MacAddress mac) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700168 Set<Host> macset = new HashSet<>();
169 for (Host h : hosts.values()) {
170 if (h.mac().equals(mac)) {
171 macset.add(h);
172 }
173 }
174 return macset;
tom7869ad92014-09-09 14:32:08 -0700175 }
176
tom5bcc9462014-09-19 10:11:31 -0700177 @Override
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700178 public Set<Host> getHosts(IpPrefix ip) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700179 Set<Host> ipset = new HashSet<>();
180 for (Host h : hosts.values()) {
181 if (h.ipAddresses().contains(ip)) {
182 ipset.add(h);
183 }
184 }
185 return ipset;
tom7869ad92014-09-09 14:32:08 -0700186 }
187
tom5bcc9462014-09-19 10:11:31 -0700188 @Override
189 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700190 return ImmutableSet.copyOf(locations.get(connectPoint));
tom7869ad92014-09-09 14:32:08 -0700191 }
192
tom5bcc9462014-09-19 10:11:31 -0700193 @Override
tom7869ad92014-09-09 14:32:08 -0700194 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700195 Set<Host> hostset = new HashSet<>();
196 for (ConnectPoint p : locations.keySet()) {
197 if (p.deviceId().equals(deviceId)) {
198 hostset.addAll(locations.get(p));
199 }
200 }
201 return hostset;
tom7869ad92014-09-09 14:32:08 -0700202 }
203
Jonathan Hartac60c082014-09-23 08:55:17 -0700204 @Override
205 public void updateAddressBindings(PortAddresses addresses) {
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700206 synchronized (portAddresses) {
207 PortAddresses existing = portAddresses.get(addresses.connectPoint());
208 if (existing == null) {
209 portAddresses.put(addresses.connectPoint(), addresses);
210 } else {
211 Set<IpPrefix> union = Sets.union(existing.ips(), addresses.ips())
212 .immutableCopy();
213
214 MacAddress newMac = (addresses.mac() == null) ? existing.mac()
215 : addresses.mac();
216
217 PortAddresses newAddresses =
218 new PortAddresses(addresses.connectPoint(), union, newMac);
219
220 portAddresses.put(newAddresses.connectPoint(), newAddresses);
221 }
222 }
Jonathan Hartac60c082014-09-23 08:55:17 -0700223 }
224
225 @Override
Jonathan Hart09585c62014-09-23 16:58:04 -0700226 public void removeAddressBindings(PortAddresses addresses) {
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700227 synchronized (portAddresses) {
228 PortAddresses existing = portAddresses.get(addresses.connectPoint());
229 if (existing != null) {
230 Set<IpPrefix> difference =
231 Sets.difference(existing.ips(), addresses.ips()).immutableCopy();
Jonathan Hart09585c62014-09-23 16:58:04 -0700232
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700233 // If they removed the existing mac, set the new mac to null.
234 // Otherwise, keep the existing mac.
235 MacAddress newMac = existing.mac();
236 if (addresses.mac() != null && addresses.mac().equals(existing.mac())) {
237 newMac = null;
238 }
239
240 PortAddresses newAddresses =
241 new PortAddresses(addresses.connectPoint(), difference, newMac);
242
243 portAddresses.put(newAddresses.connectPoint(), newAddresses);
244 }
245 }
Jonathan Hart09585c62014-09-23 16:58:04 -0700246 }
247
248 @Override
249 public void clearAddressBindings(ConnectPoint connectPoint) {
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700250 synchronized (portAddresses) {
251 portAddresses.remove(connectPoint);
252 }
Jonathan Hartac60c082014-09-23 08:55:17 -0700253 }
254
255 @Override
256 public Set<PortAddresses> getAddressBindings() {
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700257 synchronized (portAddresses) {
258 return new HashSet<>(portAddresses.values());
259 }
Jonathan Hartac60c082014-09-23 08:55:17 -0700260 }
261
262 @Override
263 public PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint) {
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700264 PortAddresses addresses;
265
266 synchronized (portAddresses) {
267 addresses = portAddresses.get(connectPoint);
268 }
269
270 if (addresses == null) {
271 addresses = new PortAddresses(connectPoint, null, null);
272 }
273
274 return addresses;
Jonathan Hartac60c082014-09-23 08:55:17 -0700275 }
276
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700277}