blob: 923e68e1c9b672ef55b5bd37ed627a38f582101a [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
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 */
Thomas Vachuskac97aa612015-06-23 16:00:18 -070016package org.onosproject.store.trivial;
tom7869ad92014-09-09 14:32:08 -070017
Jonathan Hart46080b62015-08-31 11:10:21 +020018import com.google.common.collect.HashMultimap;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Multimap;
Jonathan Hart46080b62015-08-31 11:10:21 +020021import org.onlab.packet.IpAddress;
22import org.onlab.packet.MacAddress;
23import org.onlab.packet.VlanId;
Brian O'Connorabafb502014-12-02 22:26:20 -080024import org.onosproject.net.Annotations;
25import org.onosproject.net.ConnectPoint;
26import org.onosproject.net.DefaultAnnotations;
27import org.onosproject.net.DefaultHost;
28import org.onosproject.net.DeviceId;
29import org.onosproject.net.Host;
30import org.onosproject.net.HostId;
31import org.onosproject.net.HostLocation;
32import org.onosproject.net.host.HostDescription;
33import org.onosproject.net.host.HostEvent;
34import org.onosproject.net.host.HostStore;
35import org.onosproject.net.host.HostStoreDelegate;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.provider.ProviderId;
37import org.onosproject.store.AbstractStore;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070038import org.osgi.service.component.annotations.Activate;
39import org.osgi.service.component.annotations.Component;
40import org.osgi.service.component.annotations.Deactivate;
Jonathan Hartac60c082014-09-23 08:55:17 -070041import org.slf4j.Logger;
tom7869ad92014-09-09 14:32:08 -070042
Jonathan Hart46080b62015-08-31 11:10:21 +020043import java.util.HashSet;
44import java.util.Map;
45import java.util.Set;
46import java.util.concurrent.ConcurrentHashMap;
47
48import static org.onosproject.net.DefaultAnnotations.merge;
49import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
50import static org.onosproject.net.host.HostEvent.Type.HOST_MOVED;
51import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED;
52import static org.onosproject.net.host.HostEvent.Type.HOST_UPDATED;
53import static org.slf4j.LoggerFactory.getLogger;
Ayaka Koshibee5652752014-09-10 23:27:34 -070054
Yuta HIGUCHIa2639152014-10-14 15:08:10 -070055// TODO: multi-provider, annotation not supported.
tom7869ad92014-09-09 14:32:08 -070056/**
57 * Manages inventory of end-station hosts using trivial in-memory
58 * implementation.
59 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070060@Component(immediate = true, service = HostStore.class)
tomf80c9722014-09-24 14:49:18 -070061public class SimpleHostStore
62 extends AbstractStore<HostEvent, HostStoreDelegate>
63 implements HostStore {
tom7869ad92014-09-09 14:32:08 -070064
tom5bcc9462014-09-19 10:11:31 -070065 private final Logger log = getLogger(getClass());
66
67 // Host inventory
tom093340b2014-10-10 00:15:36 -070068 private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
tom7869ad92014-09-09 14:32:08 -070069
tom5bcc9462014-09-19 10:11:31 -070070 // Hosts tracked by their location
Ayaka Koshibee5652752014-09-10 23:27:34 -070071 private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
tome615ee42014-09-11 10:52:10 -070072
tom5bcc9462014-09-19 10:11:31 -070073 @Activate
74 public void activate() {
75 log.info("Started");
76 }
77
78 @Deactivate
79 public void deactivate() {
80 log.info("Stopped");
81 }
82
83 @Override
84 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
Brian O'Connorf107bd72015-09-21 15:31:03 -070085 HostDescription hostDescription,
86 boolean replaceIps) {
87 //TODO We need a way to detect conflicting changes and abort update.
tom093340b2014-10-10 00:15:36 -070088 StoredHost host = hosts.get(hostId);
Charles Chan009c3082015-11-10 14:18:04 -080089 HostEvent hostEvent;
Ayaka Koshibee5652752014-09-10 23:27:34 -070090 if (host == null) {
Charles Chan009c3082015-11-10 14:18:04 -080091 hostEvent = createHost(providerId, hostId, hostDescription);
92 } else {
93 hostEvent = updateHost(providerId, host, hostDescription, replaceIps);
Ayaka Koshibee5652752014-09-10 23:27:34 -070094 }
Charles Chan009c3082015-11-10 14:18:04 -080095 notifyDelegate(hostEvent);
96 return hostEvent;
Ayaka Koshibee5652752014-09-10 23:27:34 -070097 }
98
99 // creates a new host and sends HOST_ADDED
100 private HostEvent createHost(ProviderId providerId, HostId hostId,
toma56d5fe2014-09-17 11:05:47 -0700101 HostDescription descr) {
tom093340b2014-10-10 00:15:36 -0700102 StoredHost newhost = new StoredHost(providerId, hostId,
103 descr.hwAddress(),
104 descr.vlan(),
105 descr.location(),
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800106 ImmutableSet.copyOf(descr.ipAddress()),
Charles Chand0c147a2017-09-14 14:00:10 -0700107 descr.configured(),
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800108 descr.annotations());
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700109 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700110 hosts.put(hostId, newhost);
111 locations.put(descr.location(), newhost);
112 }
113 return new HostEvent(HOST_ADDED, newhost);
114 }
115
116 // checks for type of update to host, sends appropriate event
tom093340b2014-10-10 00:15:36 -0700117 private HostEvent updateHost(ProviderId providerId, StoredHost host,
Brian O'Connorf107bd72015-09-21 15:31:03 -0700118 HostDescription descr, boolean replaceIps) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700119 HostEvent event;
toma56d5fe2014-09-17 11:05:47 -0700120 if (!host.location().equals(descr.location())) {
tom093340b2014-10-10 00:15:36 -0700121 host.setLocation(descr.location());
122 return new HostEvent(HOST_MOVED, host);
123 }
toma56d5fe2014-09-17 11:05:47 -0700124
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800125 if (host.ipAddresses().containsAll(descr.ipAddress()) &&
126 descr.annotations().keys().isEmpty()) {
Ayaka Koshibe1a100982014-09-13 19:32:19 -0700127 return null;
Ayaka Koshibee5652752014-09-10 23:27:34 -0700128 }
tom093340b2014-10-10 00:15:36 -0700129
Brian O'Connorf107bd72015-09-21 15:31:03 -0700130 final Set<IpAddress> addresses;
131 if (replaceIps) {
132 addresses = ImmutableSet.copyOf(descr.ipAddress());
133 } else {
134 addresses = new HashSet<>(host.ipAddresses());
135 addresses.addAll(descr.ipAddress());
136 }
137
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800138 Annotations annotations = merge((DefaultAnnotations) host.annotations(),
139 descr.annotations());
tom093340b2014-10-10 00:15:36 -0700140 StoredHost updated = new StoredHost(providerId, host.id(),
141 host.mac(), host.vlan(),
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800142 descr.location(), addresses,
Charles Chand0c147a2017-09-14 14:00:10 -0700143 descr.configured(),
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800144 annotations);
tom093340b2014-10-10 00:15:36 -0700145 event = new HostEvent(HOST_UPDATED, updated);
Ayaka Koshibee5652752014-09-10 23:27:34 -0700146 synchronized (this) {
147 hosts.put(host.id(), updated);
148 locations.remove(host.location(), host);
149 locations.put(updated.location(), updated);
150 }
151 return event;
tom7869ad92014-09-09 14:32:08 -0700152 }
153
tom5bcc9462014-09-19 10:11:31 -0700154 @Override
155 public HostEvent removeHost(HostId hostId) {
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700156 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700157 Host host = hosts.remove(hostId);
158 if (host != null) {
159 locations.remove((host.location()), host);
Charles Chan009c3082015-11-10 14:18:04 -0800160 HostEvent hostEvent = new HostEvent(HOST_REMOVED, host);
161 notifyDelegate(hostEvent);
162 return hostEvent;
Ayaka Koshibee5652752014-09-10 23:27:34 -0700163 }
164 return null;
165 }
tom7869ad92014-09-09 14:32:08 -0700166 }
167
tom5bcc9462014-09-19 10:11:31 -0700168 @Override
samanwita palc40e5ed2015-09-24 11:01:51 -0700169 public HostEvent removeIp(HostId hostId, IpAddress ipAddress) {
Charles Chan888e20a2017-05-01 15:44:23 -0700170 // TODO implement this
samanwita palc40e5ed2015-09-24 11:01:51 -0700171 return null;
172 }
173
174 @Override
Charles Chan47933752017-11-30 15:37:50 -0800175 public void appendLocation(HostId hostId, HostLocation location) {
176 hosts.get(hostId).locations().add(location);
177 }
178
179 @Override
Charles Chan888e20a2017-05-01 15:44:23 -0700180 public void removeLocation(HostId hostId, HostLocation location) {
181 hosts.get(hostId).locations().remove(location);
182 }
183
184 @Override
tom5bcc9462014-09-19 10:11:31 -0700185 public int getHostCount() {
tom7869ad92014-09-09 14:32:08 -0700186 return hosts.size();
187 }
188
tom5bcc9462014-09-19 10:11:31 -0700189 @Override
190 public Iterable<Host> getHosts() {
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700191 return ImmutableSet.copyOf(hosts.values());
tom7869ad92014-09-09 14:32:08 -0700192 }
193
tom5bcc9462014-09-19 10:11:31 -0700194 @Override
195 public Host getHost(HostId hostId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700196 return hosts.get(hostId);
tom7869ad92014-09-09 14:32:08 -0700197 }
198
tom5bcc9462014-09-19 10:11:31 -0700199 @Override
200 public Set<Host> getHosts(VlanId vlanId) {
toma56d5fe2014-09-17 11:05:47 -0700201 Set<Host> vlanset = new HashSet<>();
Ayaka Koshibee5652752014-09-10 23:27:34 -0700202 for (Host h : hosts.values()) {
Ayaka Koshibe04a1a4e2014-09-11 14:31:29 -0700203 if (h.vlan().equals(vlanId)) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700204 vlanset.add(h);
205 }
206 }
207 return vlanset;
tom7869ad92014-09-09 14:32:08 -0700208 }
209
tom5bcc9462014-09-19 10:11:31 -0700210 @Override
211 public Set<Host> getHosts(MacAddress mac) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700212 Set<Host> macset = new HashSet<>();
213 for (Host h : hosts.values()) {
214 if (h.mac().equals(mac)) {
215 macset.add(h);
216 }
217 }
218 return macset;
tom7869ad92014-09-09 14:32:08 -0700219 }
220
tom5bcc9462014-09-19 10:11:31 -0700221 @Override
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700222 public Set<Host> getHosts(IpAddress ip) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700223 Set<Host> ipset = new HashSet<>();
224 for (Host h : hosts.values()) {
225 if (h.ipAddresses().contains(ip)) {
226 ipset.add(h);
227 }
228 }
229 return ipset;
tom7869ad92014-09-09 14:32:08 -0700230 }
231
tom5bcc9462014-09-19 10:11:31 -0700232 @Override
233 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700234 return ImmutableSet.copyOf(locations.get(connectPoint));
tom7869ad92014-09-09 14:32:08 -0700235 }
236
tom5bcc9462014-09-19 10:11:31 -0700237 @Override
tom7869ad92014-09-09 14:32:08 -0700238 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700239 Set<Host> hostset = new HashSet<>();
240 for (ConnectPoint p : locations.keySet()) {
241 if (p.deviceId().equals(deviceId)) {
242 hostset.addAll(locations.get(p));
243 }
244 }
245 return hostset;
tom7869ad92014-09-09 14:32:08 -0700246 }
247
tom093340b2014-10-10 00:15:36 -0700248 // Auxiliary extension to allow location to mutate.
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700249 private static final class StoredHost extends DefaultHost {
tom093340b2014-10-10 00:15:36 -0700250 private HostLocation location;
251
252 /**
253 * Creates an end-station host using the supplied information.
254 *
255 * @param providerId provider identity
256 * @param id host identifier
257 * @param mac host MAC address
258 * @param vlan host VLAN identifier
259 * @param location host location
260 * @param ips host IP addresses
261 * @param annotations optional key/value annotations
262 */
263 public StoredHost(ProviderId providerId, HostId id,
264 MacAddress mac, VlanId vlan, HostLocation location,
Charles Chand0c147a2017-09-14 14:00:10 -0700265 Set<IpAddress> ips, boolean configured, Annotations... annotations) {
266 super(providerId, id, mac, vlan, location, ips, configured, annotations);
tom093340b2014-10-10 00:15:36 -0700267 this.location = location;
268 }
269
270 void setLocation(HostLocation location) {
271 this.location = location;
272 }
273
274 @Override
275 public HostLocation location() {
276 return location;
277 }
278 }
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700279}