blob: ba1cafbbd6e4e3411701d65d65e319806e128a6e [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
tomea961ff2014-10-01 12:45:15 -070016package org.onlab.onos.store.trivial.impl;
tom7869ad92014-09-09 14:32:08 -070017
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -080018import static org.onlab.onos.net.DefaultAnnotations.merge;
Jonathan Harta887ba82014-11-03 15:20:52 -080019import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
20import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
21import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED;
22import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED;
23import static org.slf4j.LoggerFactory.getLogger;
24
25import java.util.Collections;
26import java.util.HashSet;
27import java.util.Map;
28import java.util.Set;
29import java.util.concurrent.ConcurrentHashMap;
30
tom5bcc9462014-09-19 10:11:31 -070031import org.apache.felix.scr.annotations.Activate;
32import org.apache.felix.scr.annotations.Component;
33import org.apache.felix.scr.annotations.Deactivate;
34import org.apache.felix.scr.annotations.Service;
tom093340b2014-10-10 00:15:36 -070035import org.onlab.onos.net.Annotations;
tom7869ad92014-09-09 14:32:08 -070036import org.onlab.onos.net.ConnectPoint;
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -080037import org.onlab.onos.net.DefaultAnnotations;
Ayaka Koshibee5652752014-09-10 23:27:34 -070038import org.onlab.onos.net.DefaultHost;
tom7869ad92014-09-09 14:32:08 -070039import org.onlab.onos.net.DeviceId;
40import org.onlab.onos.net.Host;
41import org.onlab.onos.net.HostId;
tom093340b2014-10-10 00:15:36 -070042import org.onlab.onos.net.HostLocation;
tom7869ad92014-09-09 14:32:08 -070043import org.onlab.onos.net.host.HostDescription;
44import org.onlab.onos.net.host.HostEvent;
tom5bcc9462014-09-19 10:11:31 -070045import org.onlab.onos.net.host.HostStore;
tomf80c9722014-09-24 14:49:18 -070046import org.onlab.onos.net.host.HostStoreDelegate;
Jonathan Hartac60c082014-09-23 08:55:17 -070047import org.onlab.onos.net.host.PortAddresses;
tom7869ad92014-09-09 14:32:08 -070048import org.onlab.onos.net.provider.ProviderId;
tomf80c9722014-09-24 14:49:18 -070049import org.onlab.onos.store.AbstractStore;
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -070050import org.onlab.packet.IpAddress;
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070051import org.onlab.packet.MacAddress;
52import org.onlab.packet.VlanId;
Jonathan Hartac60c082014-09-23 08:55:17 -070053import org.slf4j.Logger;
tom7869ad92014-09-09 14:32:08 -070054
Jonathan Harta887ba82014-11-03 15:20:52 -080055import com.google.common.collect.HashMultimap;
56import com.google.common.collect.ImmutableSet;
57import com.google.common.collect.Multimap;
58import com.google.common.collect.Multimaps;
59import com.google.common.collect.SetMultimap;
Ayaka Koshibee5652752014-09-10 23:27:34 -070060
Yuta HIGUCHIa2639152014-10-14 15:08:10 -070061// TODO: multi-provider, annotation not supported.
tom7869ad92014-09-09 14:32:08 -070062/**
63 * Manages inventory of end-station hosts using trivial in-memory
64 * implementation.
65 */
tom5bcc9462014-09-19 10:11:31 -070066@Component(immediate = true)
67@Service
tomf80c9722014-09-24 14:49:18 -070068public class SimpleHostStore
69 extends AbstractStore<HostEvent, HostStoreDelegate>
70 implements HostStore {
tom7869ad92014-09-09 14:32:08 -070071
tom5bcc9462014-09-19 10:11:31 -070072 private final Logger log = getLogger(getClass());
73
74 // Host inventory
tom093340b2014-10-10 00:15:36 -070075 private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
tom7869ad92014-09-09 14:32:08 -070076
tom5bcc9462014-09-19 10:11:31 -070077 // Hosts tracked by their location
Ayaka Koshibee5652752014-09-10 23:27:34 -070078 private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
tome615ee42014-09-11 10:52:10 -070079
Jonathan Harta887ba82014-11-03 15:20:52 -080080 private final SetMultimap<ConnectPoint, PortAddresses> portAddresses =
81 Multimaps.synchronizedSetMultimap(
82 HashMultimap.<ConnectPoint, PortAddresses>create());
Jonathan Hart43c182c2014-09-23 11:13:42 -070083
tom5bcc9462014-09-19 10:11:31 -070084 @Activate
85 public void activate() {
86 log.info("Started");
87 }
88
89 @Deactivate
90 public void deactivate() {
91 log.info("Stopped");
92 }
93
94 @Override
95 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
96 HostDescription hostDescription) {
tom093340b2014-10-10 00:15:36 -070097 StoredHost host = hosts.get(hostId);
Ayaka Koshibee5652752014-09-10 23:27:34 -070098 if (host == null) {
99 return createHost(providerId, hostId, hostDescription);
100 }
101 return updateHost(providerId, host, hostDescription);
102 }
103
104 // creates a new host and sends HOST_ADDED
105 private HostEvent createHost(ProviderId providerId, HostId hostId,
toma56d5fe2014-09-17 11:05:47 -0700106 HostDescription descr) {
tom093340b2014-10-10 00:15:36 -0700107 StoredHost newhost = new StoredHost(providerId, hostId,
108 descr.hwAddress(),
109 descr.vlan(),
110 descr.location(),
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800111 ImmutableSet.copyOf(descr.ipAddress()),
112 descr.annotations());
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700113 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700114 hosts.put(hostId, newhost);
115 locations.put(descr.location(), newhost);
116 }
117 return new HostEvent(HOST_ADDED, newhost);
118 }
119
120 // checks for type of update to host, sends appropriate event
tom093340b2014-10-10 00:15:36 -0700121 private HostEvent updateHost(ProviderId providerId, StoredHost host,
toma56d5fe2014-09-17 11:05:47 -0700122 HostDescription descr) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700123 HostEvent event;
toma56d5fe2014-09-17 11:05:47 -0700124 if (!host.location().equals(descr.location())) {
tom093340b2014-10-10 00:15:36 -0700125 host.setLocation(descr.location());
126 return new HostEvent(HOST_MOVED, host);
127 }
toma56d5fe2014-09-17 11:05:47 -0700128
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800129 if (host.ipAddresses().containsAll(descr.ipAddress()) &&
130 descr.annotations().keys().isEmpty()) {
Ayaka Koshibe1a100982014-09-13 19:32:19 -0700131 return null;
Ayaka Koshibee5652752014-09-10 23:27:34 -0700132 }
tom093340b2014-10-10 00:15:36 -0700133
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700134 Set<IpAddress> addresses = new HashSet<>(host.ipAddresses());
Yuta HIGUCHI5fa3dc02014-10-15 17:08:13 -0700135 addresses.addAll(descr.ipAddress());
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800136 Annotations annotations = merge((DefaultAnnotations) host.annotations(),
137 descr.annotations());
tom093340b2014-10-10 00:15:36 -0700138 StoredHost updated = new StoredHost(providerId, host.id(),
139 host.mac(), host.vlan(),
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800140 descr.location(), addresses,
141 annotations);
tom093340b2014-10-10 00:15:36 -0700142 event = new HostEvent(HOST_UPDATED, updated);
Ayaka Koshibee5652752014-09-10 23:27:34 -0700143 synchronized (this) {
144 hosts.put(host.id(), updated);
145 locations.remove(host.location(), host);
146 locations.put(updated.location(), updated);
147 }
148 return event;
tom7869ad92014-09-09 14:32:08 -0700149 }
150
tom5bcc9462014-09-19 10:11:31 -0700151 @Override
152 public HostEvent removeHost(HostId hostId) {
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700153 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700154 Host host = hosts.remove(hostId);
155 if (host != null) {
156 locations.remove((host.location()), host);
157 return new HostEvent(HOST_REMOVED, host);
158 }
159 return null;
160 }
tom7869ad92014-09-09 14:32:08 -0700161 }
162
tom5bcc9462014-09-19 10:11:31 -0700163 @Override
164 public int getHostCount() {
tom7869ad92014-09-09 14:32:08 -0700165 return hosts.size();
166 }
167
tom5bcc9462014-09-19 10:11:31 -0700168 @Override
169 public Iterable<Host> getHosts() {
tom093340b2014-10-10 00:15:36 -0700170 return ImmutableSet.<Host>copyOf(hosts.values());
tom7869ad92014-09-09 14:32:08 -0700171 }
172
tom5bcc9462014-09-19 10:11:31 -0700173 @Override
174 public Host getHost(HostId hostId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700175 return hosts.get(hostId);
tom7869ad92014-09-09 14:32:08 -0700176 }
177
tom5bcc9462014-09-19 10:11:31 -0700178 @Override
179 public Set<Host> getHosts(VlanId vlanId) {
toma56d5fe2014-09-17 11:05:47 -0700180 Set<Host> vlanset = new HashSet<>();
Ayaka Koshibee5652752014-09-10 23:27:34 -0700181 for (Host h : hosts.values()) {
Ayaka Koshibe04a1a4e2014-09-11 14:31:29 -0700182 if (h.vlan().equals(vlanId)) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700183 vlanset.add(h);
184 }
185 }
186 return vlanset;
tom7869ad92014-09-09 14:32:08 -0700187 }
188
tom5bcc9462014-09-19 10:11:31 -0700189 @Override
190 public Set<Host> getHosts(MacAddress mac) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700191 Set<Host> macset = new HashSet<>();
192 for (Host h : hosts.values()) {
193 if (h.mac().equals(mac)) {
194 macset.add(h);
195 }
196 }
197 return macset;
tom7869ad92014-09-09 14:32:08 -0700198 }
199
tom5bcc9462014-09-19 10:11:31 -0700200 @Override
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700201 public Set<Host> getHosts(IpAddress ip) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700202 Set<Host> ipset = new HashSet<>();
203 for (Host h : hosts.values()) {
204 if (h.ipAddresses().contains(ip)) {
205 ipset.add(h);
206 }
207 }
208 return ipset;
tom7869ad92014-09-09 14:32:08 -0700209 }
210
tom5bcc9462014-09-19 10:11:31 -0700211 @Override
212 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700213 return ImmutableSet.copyOf(locations.get(connectPoint));
tom7869ad92014-09-09 14:32:08 -0700214 }
215
tom5bcc9462014-09-19 10:11:31 -0700216 @Override
tom7869ad92014-09-09 14:32:08 -0700217 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700218 Set<Host> hostset = new HashSet<>();
219 for (ConnectPoint p : locations.keySet()) {
220 if (p.deviceId().equals(deviceId)) {
221 hostset.addAll(locations.get(p));
222 }
223 }
224 return hostset;
tom7869ad92014-09-09 14:32:08 -0700225 }
226
Jonathan Hartac60c082014-09-23 08:55:17 -0700227 @Override
228 public void updateAddressBindings(PortAddresses addresses) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800229 portAddresses.put(addresses.connectPoint(), addresses);
Jonathan Hartac60c082014-09-23 08:55:17 -0700230 }
231
232 @Override
Jonathan Hart09585c62014-09-23 16:58:04 -0700233 public void removeAddressBindings(PortAddresses addresses) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800234 portAddresses.remove(addresses.connectPoint(), addresses);
Jonathan Hart09585c62014-09-23 16:58:04 -0700235 }
236
237 @Override
238 public void clearAddressBindings(ConnectPoint connectPoint) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800239 portAddresses.removeAll(connectPoint);
Jonathan Hartac60c082014-09-23 08:55:17 -0700240 }
241
242 @Override
243 public Set<PortAddresses> getAddressBindings() {
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700244 synchronized (portAddresses) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800245 return ImmutableSet.copyOf(portAddresses.values());
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700246 }
Jonathan Hartac60c082014-09-23 08:55:17 -0700247 }
248
249 @Override
Jonathan Harta887ba82014-11-03 15:20:52 -0800250 public Set<PortAddresses> getAddressBindingsForPort(ConnectPoint connectPoint) {
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700251 synchronized (portAddresses) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800252 Set<PortAddresses> addresses = portAddresses.get(connectPoint);
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700253
Jonathan Harta887ba82014-11-03 15:20:52 -0800254 if (addresses == null) {
255 return Collections.emptySet();
256 } else {
257 return ImmutableSet.copyOf(addresses);
258 }
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700259 }
Jonathan Hartac60c082014-09-23 08:55:17 -0700260 }
261
tom093340b2014-10-10 00:15:36 -0700262 // Auxiliary extension to allow location to mutate.
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700263 private static final class StoredHost extends DefaultHost {
tom093340b2014-10-10 00:15:36 -0700264 private HostLocation location;
265
266 /**
267 * Creates an end-station host using the supplied information.
268 *
269 * @param providerId provider identity
270 * @param id host identifier
271 * @param mac host MAC address
272 * @param vlan host VLAN identifier
273 * @param location host location
274 * @param ips host IP addresses
275 * @param annotations optional key/value annotations
276 */
277 public StoredHost(ProviderId providerId, HostId id,
278 MacAddress mac, VlanId vlan, HostLocation location,
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700279 Set<IpAddress> ips, Annotations... annotations) {
tom093340b2014-10-10 00:15:36 -0700280 super(providerId, id, mac, vlan, location, ips, annotations);
281 this.location = location;
282 }
283
284 void setLocation(HostLocation location) {
285 this.location = location;
286 }
287
288 @Override
289 public HostLocation location() {
290 return location;
291 }
292 }
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700293}