diff options
Diffstat (limited to 'framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleHostStore.java')
-rw-r--r-- | framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleHostStore.java | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleHostStore.java b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleHostStore.java new file mode 100644 index 00000000..f5604f68 --- /dev/null +++ b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleHostStore.java @@ -0,0 +1,293 @@ +/* + * Copyright 2014 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.store.trivial; + +import static org.onosproject.net.DefaultAnnotations.merge; +import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED; +import static org.onosproject.net.host.HostEvent.Type.HOST_MOVED; +import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED; +import static org.onosproject.net.host.HostEvent.Type.HOST_UPDATED; +import static org.slf4j.LoggerFactory.getLogger; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.net.Annotations; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DefaultAnnotations; +import org.onosproject.net.DefaultHost; +import org.onosproject.net.DeviceId; +import org.onosproject.net.Host; +import org.onosproject.net.HostId; +import org.onosproject.net.HostLocation; +import org.onosproject.net.host.HostDescription; +import org.onosproject.net.host.HostEvent; +import org.onosproject.net.host.HostStore; +import org.onosproject.net.host.HostStoreDelegate; +import org.onosproject.net.host.PortAddresses; +import org.onosproject.net.provider.ProviderId; +import org.onosproject.store.AbstractStore; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; +import org.slf4j.Logger; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; + +// TODO: multi-provider, annotation not supported. +/** + * Manages inventory of end-station hosts using trivial in-memory + * implementation. + */ +@Component(immediate = true) +@Service +public class SimpleHostStore + extends AbstractStore<HostEvent, HostStoreDelegate> + implements HostStore { + + private final Logger log = getLogger(getClass()); + + // Host inventory + private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16); + + // Hosts tracked by their location + private final Multimap<ConnectPoint, Host> locations = HashMultimap.create(); + + private final SetMultimap<ConnectPoint, PortAddresses> portAddresses = + Multimaps.synchronizedSetMultimap( + HashMultimap.<ConnectPoint, PortAddresses>create()); + + @Activate + public void activate() { + log.info("Started"); + } + + @Deactivate + public void deactivate() { + log.info("Stopped"); + } + + @Override + public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId, + HostDescription hostDescription) { + StoredHost host = hosts.get(hostId); + if (host == null) { + return createHost(providerId, hostId, hostDescription); + } + return updateHost(providerId, host, hostDescription); + } + + // creates a new host and sends HOST_ADDED + private HostEvent createHost(ProviderId providerId, HostId hostId, + HostDescription descr) { + StoredHost newhost = new StoredHost(providerId, hostId, + descr.hwAddress(), + descr.vlan(), + descr.location(), + ImmutableSet.copyOf(descr.ipAddress()), + descr.annotations()); + synchronized (this) { + hosts.put(hostId, newhost); + locations.put(descr.location(), newhost); + } + return new HostEvent(HOST_ADDED, newhost); + } + + // checks for type of update to host, sends appropriate event + private HostEvent updateHost(ProviderId providerId, StoredHost host, + HostDescription descr) { + HostEvent event; + if (!host.location().equals(descr.location())) { + host.setLocation(descr.location()); + return new HostEvent(HOST_MOVED, host); + } + + if (host.ipAddresses().containsAll(descr.ipAddress()) && + descr.annotations().keys().isEmpty()) { + return null; + } + + Set<IpAddress> addresses = new HashSet<>(host.ipAddresses()); + addresses.addAll(descr.ipAddress()); + Annotations annotations = merge((DefaultAnnotations) host.annotations(), + descr.annotations()); + StoredHost updated = new StoredHost(providerId, host.id(), + host.mac(), host.vlan(), + descr.location(), addresses, + annotations); + event = new HostEvent(HOST_UPDATED, updated); + synchronized (this) { + hosts.put(host.id(), updated); + locations.remove(host.location(), host); + locations.put(updated.location(), updated); + } + return event; + } + + @Override + public HostEvent removeHost(HostId hostId) { + synchronized (this) { + Host host = hosts.remove(hostId); + if (host != null) { + locations.remove((host.location()), host); + return new HostEvent(HOST_REMOVED, host); + } + return null; + } + } + + @Override + public int getHostCount() { + return hosts.size(); + } + + @Override + public Iterable<Host> getHosts() { + return ImmutableSet.<Host>copyOf(hosts.values()); + } + + @Override + public Host getHost(HostId hostId) { + return hosts.get(hostId); + } + + @Override + public Set<Host> getHosts(VlanId vlanId) { + Set<Host> vlanset = new HashSet<>(); + for (Host h : hosts.values()) { + if (h.vlan().equals(vlanId)) { + vlanset.add(h); + } + } + return vlanset; + } + + @Override + public Set<Host> getHosts(MacAddress mac) { + Set<Host> macset = new HashSet<>(); + for (Host h : hosts.values()) { + if (h.mac().equals(mac)) { + macset.add(h); + } + } + return macset; + } + + @Override + public Set<Host> getHosts(IpAddress ip) { + Set<Host> ipset = new HashSet<>(); + for (Host h : hosts.values()) { + if (h.ipAddresses().contains(ip)) { + ipset.add(h); + } + } + return ipset; + } + + @Override + public Set<Host> getConnectedHosts(ConnectPoint connectPoint) { + return ImmutableSet.copyOf(locations.get(connectPoint)); + } + + @Override + public Set<Host> getConnectedHosts(DeviceId deviceId) { + Set<Host> hostset = new HashSet<>(); + for (ConnectPoint p : locations.keySet()) { + if (p.deviceId().equals(deviceId)) { + hostset.addAll(locations.get(p)); + } + } + return hostset; + } + + @Override + public void updateAddressBindings(PortAddresses addresses) { + portAddresses.put(addresses.connectPoint(), addresses); + } + + @Override + public void removeAddressBindings(PortAddresses addresses) { + portAddresses.remove(addresses.connectPoint(), addresses); + } + + @Override + public void clearAddressBindings(ConnectPoint connectPoint) { + portAddresses.removeAll(connectPoint); + } + + @Override + public Set<PortAddresses> getAddressBindings() { + synchronized (portAddresses) { + return ImmutableSet.copyOf(portAddresses.values()); + } + } + + @Override + public Set<PortAddresses> getAddressBindingsForPort(ConnectPoint connectPoint) { + synchronized (portAddresses) { + Set<PortAddresses> addresses = portAddresses.get(connectPoint); + + if (addresses == null) { + return Collections.emptySet(); + } else { + return ImmutableSet.copyOf(addresses); + } + } + } + + // Auxiliary extension to allow location to mutate. + private static final class StoredHost extends DefaultHost { + private HostLocation location; + + /** + * Creates an end-station host using the supplied information. + * + * @param providerId provider identity + * @param id host identifier + * @param mac host MAC address + * @param vlan host VLAN identifier + * @param location host location + * @param ips host IP addresses + * @param annotations optional key/value annotations + */ + public StoredHost(ProviderId providerId, HostId id, + MacAddress mac, VlanId vlan, HostLocation location, + Set<IpAddress> ips, Annotations... annotations) { + super(providerId, id, mac, vlan, location, ips, annotations); + this.location = location; + } + + void setLocation(HostLocation location) { + this.location = location; + } + + @Override + public HostLocation location() { + return location; + } + } +} |