blob: 09820f4bc09ed7ec178def24af6e0c57af6ce011 [file] [log] [blame]
alshabib339a3d92014-09-26 17:54:32 -07001package org.onlab.onos.store.host.impl;
2
3import 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;
7import static org.slf4j.LoggerFactory.getLogger;
8
9import java.util.Collections;
10import java.util.HashSet;
11import java.util.Map;
12import java.util.Set;
13import java.util.concurrent.ConcurrentHashMap;
14
15import 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;
19import org.onlab.onos.net.ConnectPoint;
20import org.onlab.onos.net.DefaultHost;
21import 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;
26import org.onlab.onos.net.host.HostStore;
27import org.onlab.onos.net.host.HostStoreDelegate;
28import org.onlab.onos.net.host.PortAddresses;
29import org.onlab.onos.net.provider.ProviderId;
30import org.onlab.onos.store.AbstractStore;
31import org.onlab.packet.IpPrefix;
32import org.onlab.packet.MacAddress;
33import org.onlab.packet.VlanId;
34import org.slf4j.Logger;
35
36import com.google.common.collect.HashMultimap;
37import com.google.common.collect.ImmutableSet;
38import com.google.common.collect.Multimap;
39import com.google.common.collect.Sets;
40
41/**
42 * Manages inventory of end-station hosts using trivial in-memory
43 * implementation.
44 */
45//FIXME: I LIE I AM NOT DISTRIBUTED
46@Component(immediate = true)
47@Service
48public class DistributedHostStore
49extends AbstractStore<HostEvent, HostStoreDelegate>
50implements HostStore {
51
52 private final Logger log = getLogger(getClass());
53
54 // Host inventory
55 private final Map<HostId, Host> hosts = new ConcurrentHashMap<>();
56
57 // Hosts tracked by their location
58 private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
59
60 private final Map<ConnectPoint, PortAddresses> portAddresses =
61 new ConcurrentHashMap<>();
62
63 @Activate
64 public void activate() {
65 log.info("Started");
66 }
67
68 @Deactivate
69 public void deactivate() {
70 log.info("Stopped");
71 }
72
73 @Override
74 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
75 HostDescription hostDescription) {
76 Host host = hosts.get(hostId);
77 if (host == null) {
78 return createHost(providerId, hostId, hostDescription);
79 }
80 return updateHost(providerId, host, hostDescription);
81 }
82
83 // creates a new host and sends HOST_ADDED
84 private HostEvent createHost(ProviderId providerId, HostId hostId,
85 HostDescription descr) {
86 DefaultHost newhost = new DefaultHost(providerId, hostId,
87 descr.hwAddress(),
88 descr.vlan(),
89 descr.location(),
90 descr.ipAddresses());
91 synchronized (this) {
92 hosts.put(hostId, newhost);
93 locations.put(descr.location(), newhost);
94 }
95 return new HostEvent(HOST_ADDED, newhost);
96 }
97
98 // checks for type of update to host, sends appropriate event
99 private HostEvent updateHost(ProviderId providerId, Host host,
100 HostDescription descr) {
101 DefaultHost updated;
102 HostEvent event;
103 if (!host.location().equals(descr.location())) {
104 updated = new DefaultHost(providerId, host.id(),
105 host.mac(),
106 host.vlan(),
107 descr.location(),
108 host.ipAddresses());
109 event = new HostEvent(HOST_MOVED, updated);
110
111 } else if (!(host.ipAddresses().equals(descr.ipAddresses()))) {
112 updated = new DefaultHost(providerId, host.id(),
113 host.mac(),
114 host.vlan(),
115 descr.location(),
116 descr.ipAddresses());
117 event = new HostEvent(HOST_UPDATED, updated);
118 } else {
119 return null;
120 }
121 synchronized (this) {
122 hosts.put(host.id(), updated);
123 locations.remove(host.location(), host);
124 locations.put(updated.location(), updated);
125 }
126 return event;
127 }
128
129 @Override
130 public HostEvent removeHost(HostId hostId) {
131 synchronized (this) {
132 Host host = hosts.remove(hostId);
133 if (host != null) {
134 locations.remove((host.location()), host);
135 return new HostEvent(HOST_REMOVED, host);
136 }
137 return null;
138 }
139 }
140
141 @Override
142 public int getHostCount() {
143 return hosts.size();
144 }
145
146 @Override
147 public Iterable<Host> getHosts() {
148 return Collections.unmodifiableSet(new HashSet<>(hosts.values()));
149 }
150
151 @Override
152 public Host getHost(HostId hostId) {
153 return hosts.get(hostId);
154 }
155
156 @Override
157 public Set<Host> getHosts(VlanId vlanId) {
158 Set<Host> vlanset = new HashSet<>();
159 for (Host h : hosts.values()) {
160 if (h.vlan().equals(vlanId)) {
161 vlanset.add(h);
162 }
163 }
164 return vlanset;
165 }
166
167 @Override
168 public Set<Host> getHosts(MacAddress mac) {
169 Set<Host> macset = new HashSet<>();
170 for (Host h : hosts.values()) {
171 if (h.mac().equals(mac)) {
172 macset.add(h);
173 }
174 }
175 return macset;
176 }
177
178 @Override
179 public Set<Host> getHosts(IpPrefix ip) {
180 Set<Host> ipset = new HashSet<>();
181 for (Host h : hosts.values()) {
182 if (h.ipAddresses().contains(ip)) {
183 ipset.add(h);
184 }
185 }
186 return ipset;
187 }
188
189 @Override
190 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
191 return ImmutableSet.copyOf(locations.get(connectPoint));
192 }
193
194 @Override
195 public Set<Host> getConnectedHosts(DeviceId deviceId) {
196 Set<Host> hostset = new HashSet<>();
197 for (ConnectPoint p : locations.keySet()) {
198 if (p.deviceId().equals(deviceId)) {
199 hostset.addAll(locations.get(p));
200 }
201 }
202 return hostset;
203 }
204
205 @Override
206 public void updateAddressBindings(PortAddresses addresses) {
207 synchronized (portAddresses) {
208 PortAddresses existing = portAddresses.get(addresses.connectPoint());
209 if (existing == null) {
210 portAddresses.put(addresses.connectPoint(), addresses);
211 } else {
212 Set<IpPrefix> union = Sets.union(existing.ips(), addresses.ips())
213 .immutableCopy();
214
215 MacAddress newMac = (addresses.mac() == null) ? existing.mac()
216 : addresses.mac();
217
218 PortAddresses newAddresses =
219 new PortAddresses(addresses.connectPoint(), union, newMac);
220
221 portAddresses.put(newAddresses.connectPoint(), newAddresses);
222 }
223 }
224 }
225
226 @Override
227 public void removeAddressBindings(PortAddresses addresses) {
228 synchronized (portAddresses) {
229 PortAddresses existing = portAddresses.get(addresses.connectPoint());
230 if (existing != null) {
231 Set<IpPrefix> difference =
232 Sets.difference(existing.ips(), addresses.ips()).immutableCopy();
233
234 // If they removed the existing mac, set the new mac to null.
235 // Otherwise, keep the existing mac.
236 MacAddress newMac = existing.mac();
237 if (addresses.mac() != null && addresses.mac().equals(existing.mac())) {
238 newMac = null;
239 }
240
241 PortAddresses newAddresses =
242 new PortAddresses(addresses.connectPoint(), difference, newMac);
243
244 portAddresses.put(newAddresses.connectPoint(), newAddresses);
245 }
246 }
247 }
248
249 @Override
250 public void clearAddressBindings(ConnectPoint connectPoint) {
251 synchronized (portAddresses) {
252 portAddresses.remove(connectPoint);
253 }
254 }
255
256 @Override
257 public Set<PortAddresses> getAddressBindings() {
258 synchronized (portAddresses) {
259 return new HashSet<>(portAddresses.values());
260 }
261 }
262
263 @Override
264 public PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint) {
265 PortAddresses addresses;
266
267 synchronized (portAddresses) {
268 addresses = portAddresses.get(connectPoint);
269 }
270
271 if (addresses == null) {
272 addresses = new PortAddresses(connectPoint, null, null);
273 }
274
275 return addresses;
276 }
277
278}