blob: 72ec98ca4137305fa21953f41474193b6f0b83a8 [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 */
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;
tom5bcc9462014-09-19 10:11:31 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Service;
Jonathan Hart46080b62015-08-31 11:10:21 +020025import org.onlab.packet.IpAddress;
26import org.onlab.packet.MacAddress;
27import org.onlab.packet.VlanId;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.net.Annotations;
29import org.onosproject.net.ConnectPoint;
30import org.onosproject.net.DefaultAnnotations;
31import org.onosproject.net.DefaultHost;
32import org.onosproject.net.DeviceId;
33import org.onosproject.net.Host;
34import org.onosproject.net.HostId;
35import org.onosproject.net.HostLocation;
36import org.onosproject.net.host.HostDescription;
37import org.onosproject.net.host.HostEvent;
38import org.onosproject.net.host.HostStore;
39import org.onosproject.net.host.HostStoreDelegate;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.provider.ProviderId;
41import org.onosproject.store.AbstractStore;
Jonathan Hartac60c082014-09-23 08:55:17 -070042import org.slf4j.Logger;
tom7869ad92014-09-09 14:32:08 -070043
Jonathan Hart46080b62015-08-31 11:10:21 +020044import java.util.HashSet;
45import java.util.Map;
46import java.util.Set;
47import java.util.concurrent.ConcurrentHashMap;
48
49import static org.onosproject.net.DefaultAnnotations.merge;
50import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
51import static org.onosproject.net.host.HostEvent.Type.HOST_MOVED;
52import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED;
53import static org.onosproject.net.host.HostEvent.Type.HOST_UPDATED;
54import static org.slf4j.LoggerFactory.getLogger;
Ayaka Koshibee5652752014-09-10 23:27:34 -070055
Yuta HIGUCHIa2639152014-10-14 15:08:10 -070056// TODO: multi-provider, annotation not supported.
tom7869ad92014-09-09 14:32:08 -070057/**
58 * Manages inventory of end-station hosts using trivial in-memory
59 * implementation.
60 */
tom5bcc9462014-09-19 10:11:31 -070061@Component(immediate = true)
62@Service
tomf80c9722014-09-24 14:49:18 -070063public class SimpleHostStore
64 extends AbstractStore<HostEvent, HostStoreDelegate>
65 implements HostStore {
tom7869ad92014-09-09 14:32:08 -070066
tom5bcc9462014-09-19 10:11:31 -070067 private final Logger log = getLogger(getClass());
68
69 // Host inventory
tom093340b2014-10-10 00:15:36 -070070 private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
tom7869ad92014-09-09 14:32:08 -070071
tom5bcc9462014-09-19 10:11:31 -070072 // Hosts tracked by their location
Ayaka Koshibee5652752014-09-10 23:27:34 -070073 private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
tome615ee42014-09-11 10:52:10 -070074
tom5bcc9462014-09-19 10:11:31 -070075 @Activate
76 public void activate() {
77 log.info("Started");
78 }
79
80 @Deactivate
81 public void deactivate() {
82 log.info("Stopped");
83 }
84
85 @Override
86 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
Brian O'Connorf107bd72015-09-21 15:31:03 -070087 HostDescription hostDescription,
88 boolean replaceIps) {
89 //TODO We need a way to detect conflicting changes and abort update.
tom093340b2014-10-10 00:15:36 -070090 StoredHost host = hosts.get(hostId);
Ayaka Koshibee5652752014-09-10 23:27:34 -070091 if (host == null) {
92 return createHost(providerId, hostId, hostDescription);
93 }
Brian O'Connorf107bd72015-09-21 15:31:03 -070094 return updateHost(providerId, host, hostDescription, replaceIps);
Ayaka Koshibee5652752014-09-10 23:27:34 -070095 }
96
97 // creates a new host and sends HOST_ADDED
98 private HostEvent createHost(ProviderId providerId, HostId hostId,
toma56d5fe2014-09-17 11:05:47 -070099 HostDescription descr) {
tom093340b2014-10-10 00:15:36 -0700100 StoredHost newhost = new StoredHost(providerId, hostId,
101 descr.hwAddress(),
102 descr.vlan(),
103 descr.location(),
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800104 ImmutableSet.copyOf(descr.ipAddress()),
105 descr.annotations());
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700106 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700107 hosts.put(hostId, newhost);
108 locations.put(descr.location(), newhost);
109 }
110 return new HostEvent(HOST_ADDED, newhost);
111 }
112
113 // checks for type of update to host, sends appropriate event
tom093340b2014-10-10 00:15:36 -0700114 private HostEvent updateHost(ProviderId providerId, StoredHost host,
Brian O'Connorf107bd72015-09-21 15:31:03 -0700115 HostDescription descr, boolean replaceIps) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700116 HostEvent event;
toma56d5fe2014-09-17 11:05:47 -0700117 if (!host.location().equals(descr.location())) {
tom093340b2014-10-10 00:15:36 -0700118 host.setLocation(descr.location());
119 return new HostEvent(HOST_MOVED, host);
120 }
toma56d5fe2014-09-17 11:05:47 -0700121
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800122 if (host.ipAddresses().containsAll(descr.ipAddress()) &&
123 descr.annotations().keys().isEmpty()) {
Ayaka Koshibe1a100982014-09-13 19:32:19 -0700124 return null;
Ayaka Koshibee5652752014-09-10 23:27:34 -0700125 }
tom093340b2014-10-10 00:15:36 -0700126
Brian O'Connorf107bd72015-09-21 15:31:03 -0700127 final Set<IpAddress> addresses;
128 if (replaceIps) {
129 addresses = ImmutableSet.copyOf(descr.ipAddress());
130 } else {
131 addresses = new HashSet<>(host.ipAddresses());
132 addresses.addAll(descr.ipAddress());
133 }
134
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800135 Annotations annotations = merge((DefaultAnnotations) host.annotations(),
136 descr.annotations());
tom093340b2014-10-10 00:15:36 -0700137 StoredHost updated = new StoredHost(providerId, host.id(),
138 host.mac(), host.vlan(),
Thomas Vachuskae4cebaf2014-11-15 18:49:34 -0800139 descr.location(), addresses,
140 annotations);
tom093340b2014-10-10 00:15:36 -0700141 event = new HostEvent(HOST_UPDATED, updated);
Ayaka Koshibee5652752014-09-10 23:27:34 -0700142 synchronized (this) {
143 hosts.put(host.id(), updated);
144 locations.remove(host.location(), host);
145 locations.put(updated.location(), updated);
146 }
147 return event;
tom7869ad92014-09-09 14:32:08 -0700148 }
149
tom5bcc9462014-09-19 10:11:31 -0700150 @Override
151 public HostEvent removeHost(HostId hostId) {
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700152 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700153 Host host = hosts.remove(hostId);
154 if (host != null) {
155 locations.remove((host.location()), host);
156 return new HostEvent(HOST_REMOVED, host);
157 }
158 return null;
159 }
tom7869ad92014-09-09 14:32:08 -0700160 }
161
tom5bcc9462014-09-19 10:11:31 -0700162 @Override
samanwita palc40e5ed2015-09-24 11:01:51 -0700163 public HostEvent removeIp(HostId hostId, IpAddress ipAddress) {
164 return null;
165 }
166
167 @Override
tom5bcc9462014-09-19 10:11:31 -0700168 public int getHostCount() {
tom7869ad92014-09-09 14:32:08 -0700169 return hosts.size();
170 }
171
tom5bcc9462014-09-19 10:11:31 -0700172 @Override
173 public Iterable<Host> getHosts() {
tom093340b2014-10-10 00:15:36 -0700174 return ImmutableSet.<Host>copyOf(hosts.values());
tom7869ad92014-09-09 14:32:08 -0700175 }
176
tom5bcc9462014-09-19 10:11:31 -0700177 @Override
178 public Host getHost(HostId hostId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700179 return hosts.get(hostId);
tom7869ad92014-09-09 14:32:08 -0700180 }
181
tom5bcc9462014-09-19 10:11:31 -0700182 @Override
183 public Set<Host> getHosts(VlanId vlanId) {
toma56d5fe2014-09-17 11:05:47 -0700184 Set<Host> vlanset = new HashSet<>();
Ayaka Koshibee5652752014-09-10 23:27:34 -0700185 for (Host h : hosts.values()) {
Ayaka Koshibe04a1a4e2014-09-11 14:31:29 -0700186 if (h.vlan().equals(vlanId)) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700187 vlanset.add(h);
188 }
189 }
190 return vlanset;
tom7869ad92014-09-09 14:32:08 -0700191 }
192
tom5bcc9462014-09-19 10:11:31 -0700193 @Override
194 public Set<Host> getHosts(MacAddress mac) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700195 Set<Host> macset = new HashSet<>();
196 for (Host h : hosts.values()) {
197 if (h.mac().equals(mac)) {
198 macset.add(h);
199 }
200 }
201 return macset;
tom7869ad92014-09-09 14:32:08 -0700202 }
203
tom5bcc9462014-09-19 10:11:31 -0700204 @Override
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700205 public Set<Host> getHosts(IpAddress ip) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700206 Set<Host> ipset = new HashSet<>();
207 for (Host h : hosts.values()) {
208 if (h.ipAddresses().contains(ip)) {
209 ipset.add(h);
210 }
211 }
212 return ipset;
tom7869ad92014-09-09 14:32:08 -0700213 }
214
tom5bcc9462014-09-19 10:11:31 -0700215 @Override
216 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700217 return ImmutableSet.copyOf(locations.get(connectPoint));
tom7869ad92014-09-09 14:32:08 -0700218 }
219
tom5bcc9462014-09-19 10:11:31 -0700220 @Override
tom7869ad92014-09-09 14:32:08 -0700221 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700222 Set<Host> hostset = new HashSet<>();
223 for (ConnectPoint p : locations.keySet()) {
224 if (p.deviceId().equals(deviceId)) {
225 hostset.addAll(locations.get(p));
226 }
227 }
228 return hostset;
tom7869ad92014-09-09 14:32:08 -0700229 }
230
tom093340b2014-10-10 00:15:36 -0700231 // Auxiliary extension to allow location to mutate.
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700232 private static final class StoredHost extends DefaultHost {
tom093340b2014-10-10 00:15:36 -0700233 private HostLocation location;
234
235 /**
236 * Creates an end-station host using the supplied information.
237 *
238 * @param providerId provider identity
239 * @param id host identifier
240 * @param mac host MAC address
241 * @param vlan host VLAN identifier
242 * @param location host location
243 * @param ips host IP addresses
244 * @param annotations optional key/value annotations
245 */
246 public StoredHost(ProviderId providerId, HostId id,
247 MacAddress mac, VlanId vlan, HostLocation location,
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700248 Set<IpAddress> ips, Annotations... annotations) {
tom093340b2014-10-10 00:15:36 -0700249 super(providerId, id, mac, vlan, location, ips, annotations);
250 this.location = location;
251 }
252
253 void setLocation(HostLocation location) {
254 this.location = location;
255 }
256
257 @Override
258 public HostLocation location() {
259 return location;
260 }
261 }
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700262}