blob: 2f8fbd2cd60fd4d57ef2ffe1c63ab7ef2d6645e4 [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
Jonathan Harta887ba82014-11-03 15:20:52 -080018import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
19import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
20import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED;
21import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED;
22import static org.slf4j.LoggerFactory.getLogger;
23
24import java.util.Collections;
25import java.util.HashSet;
26import java.util.Map;
27import java.util.Set;
28import java.util.concurrent.ConcurrentHashMap;
29
tom5bcc9462014-09-19 10:11:31 -070030import org.apache.felix.scr.annotations.Activate;
31import org.apache.felix.scr.annotations.Component;
32import org.apache.felix.scr.annotations.Deactivate;
33import org.apache.felix.scr.annotations.Service;
tom093340b2014-10-10 00:15:36 -070034import org.onlab.onos.net.Annotations;
tom7869ad92014-09-09 14:32:08 -070035import org.onlab.onos.net.ConnectPoint;
Ayaka Koshibee5652752014-09-10 23:27:34 -070036import org.onlab.onos.net.DefaultHost;
tom7869ad92014-09-09 14:32:08 -070037import org.onlab.onos.net.DeviceId;
38import org.onlab.onos.net.Host;
39import org.onlab.onos.net.HostId;
tom093340b2014-10-10 00:15:36 -070040import org.onlab.onos.net.HostLocation;
tom7869ad92014-09-09 14:32:08 -070041import org.onlab.onos.net.host.HostDescription;
42import org.onlab.onos.net.host.HostEvent;
tom5bcc9462014-09-19 10:11:31 -070043import org.onlab.onos.net.host.HostStore;
tomf80c9722014-09-24 14:49:18 -070044import org.onlab.onos.net.host.HostStoreDelegate;
Jonathan Hartac60c082014-09-23 08:55:17 -070045import org.onlab.onos.net.host.PortAddresses;
tom7869ad92014-09-09 14:32:08 -070046import org.onlab.onos.net.provider.ProviderId;
tomf80c9722014-09-24 14:49:18 -070047import org.onlab.onos.store.AbstractStore;
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -070048import org.onlab.packet.IpAddress;
Ayaka Koshibea9c199f2014-09-16 16:21:40 -070049import org.onlab.packet.MacAddress;
50import org.onlab.packet.VlanId;
Jonathan Hartac60c082014-09-23 08:55:17 -070051import org.slf4j.Logger;
tom7869ad92014-09-09 14:32:08 -070052
Jonathan Harta887ba82014-11-03 15:20:52 -080053import com.google.common.collect.HashMultimap;
54import com.google.common.collect.ImmutableSet;
55import com.google.common.collect.Multimap;
56import com.google.common.collect.Multimaps;
57import com.google.common.collect.SetMultimap;
Ayaka Koshibee5652752014-09-10 23:27:34 -070058
Yuta HIGUCHIa2639152014-10-14 15:08:10 -070059// TODO: multi-provider, annotation not supported.
tom7869ad92014-09-09 14:32:08 -070060/**
61 * Manages inventory of end-station hosts using trivial in-memory
62 * implementation.
63 */
tom5bcc9462014-09-19 10:11:31 -070064@Component(immediate = true)
65@Service
tomf80c9722014-09-24 14:49:18 -070066public class SimpleHostStore
67 extends AbstractStore<HostEvent, HostStoreDelegate>
68 implements HostStore {
tom7869ad92014-09-09 14:32:08 -070069
tom5bcc9462014-09-19 10:11:31 -070070 private final Logger log = getLogger(getClass());
71
72 // Host inventory
tom093340b2014-10-10 00:15:36 -070073 private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
tom7869ad92014-09-09 14:32:08 -070074
tom5bcc9462014-09-19 10:11:31 -070075 // Hosts tracked by their location
Ayaka Koshibee5652752014-09-10 23:27:34 -070076 private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
tome615ee42014-09-11 10:52:10 -070077
Jonathan Harta887ba82014-11-03 15:20:52 -080078 private final SetMultimap<ConnectPoint, PortAddresses> portAddresses =
79 Multimaps.synchronizedSetMultimap(
80 HashMultimap.<ConnectPoint, PortAddresses>create());
Jonathan Hart43c182c2014-09-23 11:13:42 -070081
tom5bcc9462014-09-19 10:11:31 -070082 @Activate
83 public void activate() {
84 log.info("Started");
85 }
86
87 @Deactivate
88 public void deactivate() {
89 log.info("Stopped");
90 }
91
92 @Override
93 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
94 HostDescription hostDescription) {
tom093340b2014-10-10 00:15:36 -070095 StoredHost host = hosts.get(hostId);
Ayaka Koshibee5652752014-09-10 23:27:34 -070096 if (host == null) {
97 return createHost(providerId, hostId, hostDescription);
98 }
99 return updateHost(providerId, host, hostDescription);
100 }
101
102 // creates a new host and sends HOST_ADDED
103 private HostEvent createHost(ProviderId providerId, HostId hostId,
toma56d5fe2014-09-17 11:05:47 -0700104 HostDescription descr) {
tom093340b2014-10-10 00:15:36 -0700105 StoredHost newhost = new StoredHost(providerId, hostId,
106 descr.hwAddress(),
107 descr.vlan(),
108 descr.location(),
Yuta HIGUCHI5fa3dc02014-10-15 17:08:13 -0700109 ImmutableSet.copyOf(descr.ipAddress()));
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700110 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700111 hosts.put(hostId, newhost);
112 locations.put(descr.location(), newhost);
113 }
114 return new HostEvent(HOST_ADDED, newhost);
115 }
116
117 // checks for type of update to host, sends appropriate event
tom093340b2014-10-10 00:15:36 -0700118 private HostEvent updateHost(ProviderId providerId, StoredHost host,
toma56d5fe2014-09-17 11:05:47 -0700119 HostDescription descr) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700120 HostEvent event;
toma56d5fe2014-09-17 11:05:47 -0700121 if (!host.location().equals(descr.location())) {
tom093340b2014-10-10 00:15:36 -0700122 host.setLocation(descr.location());
123 return new HostEvent(HOST_MOVED, host);
124 }
toma56d5fe2014-09-17 11:05:47 -0700125
Yuta HIGUCHI5fa3dc02014-10-15 17:08:13 -0700126 if (host.ipAddresses().containsAll(descr.ipAddress())) {
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
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700130 Set<IpAddress> addresses = new HashSet<>(host.ipAddresses());
Yuta HIGUCHI5fa3dc02014-10-15 17:08:13 -0700131 addresses.addAll(descr.ipAddress());
tom093340b2014-10-10 00:15:36 -0700132 StoredHost updated = new StoredHost(providerId, host.id(),
133 host.mac(), host.vlan(),
134 descr.location(), addresses);
135 event = new HostEvent(HOST_UPDATED, updated);
Ayaka Koshibee5652752014-09-10 23:27:34 -0700136 synchronized (this) {
137 hosts.put(host.id(), updated);
138 locations.remove(host.location(), host);
139 locations.put(updated.location(), updated);
140 }
141 return event;
tom7869ad92014-09-09 14:32:08 -0700142 }
143
tom5bcc9462014-09-19 10:11:31 -0700144 @Override
145 public HostEvent removeHost(HostId hostId) {
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700146 synchronized (this) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700147 Host host = hosts.remove(hostId);
148 if (host != null) {
149 locations.remove((host.location()), host);
150 return new HostEvent(HOST_REMOVED, host);
151 }
152 return null;
153 }
tom7869ad92014-09-09 14:32:08 -0700154 }
155
tom5bcc9462014-09-19 10:11:31 -0700156 @Override
157 public int getHostCount() {
tom7869ad92014-09-09 14:32:08 -0700158 return hosts.size();
159 }
160
tom5bcc9462014-09-19 10:11:31 -0700161 @Override
162 public Iterable<Host> getHosts() {
tom093340b2014-10-10 00:15:36 -0700163 return ImmutableSet.<Host>copyOf(hosts.values());
tom7869ad92014-09-09 14:32:08 -0700164 }
165
tom5bcc9462014-09-19 10:11:31 -0700166 @Override
167 public Host getHost(HostId hostId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700168 return hosts.get(hostId);
tom7869ad92014-09-09 14:32:08 -0700169 }
170
tom5bcc9462014-09-19 10:11:31 -0700171 @Override
172 public Set<Host> getHosts(VlanId vlanId) {
toma56d5fe2014-09-17 11:05:47 -0700173 Set<Host> vlanset = new HashSet<>();
Ayaka Koshibee5652752014-09-10 23:27:34 -0700174 for (Host h : hosts.values()) {
Ayaka Koshibe04a1a4e2014-09-11 14:31:29 -0700175 if (h.vlan().equals(vlanId)) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700176 vlanset.add(h);
177 }
178 }
179 return vlanset;
tom7869ad92014-09-09 14:32:08 -0700180 }
181
tom5bcc9462014-09-19 10:11:31 -0700182 @Override
183 public Set<Host> getHosts(MacAddress mac) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700184 Set<Host> macset = new HashSet<>();
185 for (Host h : hosts.values()) {
186 if (h.mac().equals(mac)) {
187 macset.add(h);
188 }
189 }
190 return macset;
tom7869ad92014-09-09 14:32:08 -0700191 }
192
tom5bcc9462014-09-19 10:11:31 -0700193 @Override
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700194 public Set<Host> getHosts(IpAddress ip) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700195 Set<Host> ipset = new HashSet<>();
196 for (Host h : hosts.values()) {
197 if (h.ipAddresses().contains(ip)) {
198 ipset.add(h);
199 }
200 }
201 return ipset;
tom7869ad92014-09-09 14:32:08 -0700202 }
203
tom5bcc9462014-09-19 10:11:31 -0700204 @Override
205 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700206 return ImmutableSet.copyOf(locations.get(connectPoint));
tom7869ad92014-09-09 14:32:08 -0700207 }
208
tom5bcc9462014-09-19 10:11:31 -0700209 @Override
tom7869ad92014-09-09 14:32:08 -0700210 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Ayaka Koshibee5652752014-09-10 23:27:34 -0700211 Set<Host> hostset = new HashSet<>();
212 for (ConnectPoint p : locations.keySet()) {
213 if (p.deviceId().equals(deviceId)) {
214 hostset.addAll(locations.get(p));
215 }
216 }
217 return hostset;
tom7869ad92014-09-09 14:32:08 -0700218 }
219
Jonathan Hartac60c082014-09-23 08:55:17 -0700220 @Override
221 public void updateAddressBindings(PortAddresses addresses) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800222 portAddresses.put(addresses.connectPoint(), addresses);
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 Harta887ba82014-11-03 15:20:52 -0800227 portAddresses.remove(addresses.connectPoint(), addresses);
Jonathan Hart09585c62014-09-23 16:58:04 -0700228 }
229
230 @Override
231 public void clearAddressBindings(ConnectPoint connectPoint) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800232 portAddresses.removeAll(connectPoint);
Jonathan Hartac60c082014-09-23 08:55:17 -0700233 }
234
235 @Override
236 public Set<PortAddresses> getAddressBindings() {
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700237 synchronized (portAddresses) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800238 return ImmutableSet.copyOf(portAddresses.values());
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700239 }
Jonathan Hartac60c082014-09-23 08:55:17 -0700240 }
241
242 @Override
Jonathan Harta887ba82014-11-03 15:20:52 -0800243 public Set<PortAddresses> getAddressBindingsForPort(ConnectPoint connectPoint) {
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700244 synchronized (portAddresses) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800245 Set<PortAddresses> addresses = portAddresses.get(connectPoint);
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700246
Jonathan Harta887ba82014-11-03 15:20:52 -0800247 if (addresses == null) {
248 return Collections.emptySet();
249 } else {
250 return ImmutableSet.copyOf(addresses);
251 }
Jonathan Hartc884f1b2014-09-24 11:53:33 -0700252 }
Jonathan Hartac60c082014-09-23 08:55:17 -0700253 }
254
tom093340b2014-10-10 00:15:36 -0700255 // Auxiliary extension to allow location to mutate.
Yuta HIGUCHIe5ca93b2014-10-23 09:49:00 -0700256 private static final class StoredHost extends DefaultHost {
tom093340b2014-10-10 00:15:36 -0700257 private HostLocation location;
258
259 /**
260 * Creates an end-station host using the supplied information.
261 *
262 * @param providerId provider identity
263 * @param id host identifier
264 * @param mac host MAC address
265 * @param vlan host VLAN identifier
266 * @param location host location
267 * @param ips host IP addresses
268 * @param annotations optional key/value annotations
269 */
270 public StoredHost(ProviderId providerId, HostId id,
271 MacAddress mac, VlanId vlan, HostLocation location,
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700272 Set<IpAddress> ips, Annotations... annotations) {
tom093340b2014-10-10 00:15:36 -0700273 super(providerId, id, mac, vlan, location, ips, annotations);
274 this.location = location;
275 }
276
277 void setLocation(HostLocation location) {
278 this.location = location;
279 }
280
281 @Override
282 public HostLocation location() {
283 return location;
284 }
285 }
Ayaka Koshibe1c7b38e2014-09-11 13:09:51 -0700286}