blob: 310c8fde9d841cdbcda314479e931fb597bafa0d [file] [log] [blame]
Charles Chand6d581a2015-11-18 16:51:08 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Charles Chand6d581a2015-11-18 16:51:08 -08003 *
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 */
16
17package org.onosproject.provider.netcfghost;
18
Ray Milkeyd84f89b2018-08-17 14:54:17 -070019import org.osgi.service.component.annotations.Activate;
20import org.osgi.service.component.annotations.Component;
21import org.osgi.service.component.annotations.Deactivate;
22import org.osgi.service.component.annotations.Reference;
23import org.osgi.service.component.annotations.ReferenceCardinality;
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -070024import org.onlab.packet.EthType;
Charles Chand6d581a2015-11-18 16:51:08 -080025import org.onlab.packet.IpAddress;
26import org.onlab.packet.MacAddress;
27import org.onlab.packet.VlanId;
28import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
Charles Chand6d581a2015-11-18 16:51:08 -080030import org.onosproject.net.Host;
31import org.onosproject.net.HostId;
32import org.onosproject.net.HostLocation;
33import org.onosproject.net.config.NetworkConfigEvent;
34import org.onosproject.net.config.NetworkConfigListener;
35import org.onosproject.net.config.NetworkConfigRegistry;
36import org.onosproject.net.config.basics.BasicHostConfig;
37import org.onosproject.net.host.DefaultHostDescription;
38import org.onosproject.net.host.HostDescription;
39import org.onosproject.net.host.HostProvider;
40import org.onosproject.net.host.HostProviderRegistry;
41import org.onosproject.net.host.HostProviderService;
42import org.onosproject.net.provider.AbstractProvider;
43import org.onosproject.net.provider.ProviderId;
44import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
Charles Chan61fc0d82017-04-28 14:13:36 -070046
47import java.util.Collections;
Charles Chand6d581a2015-11-18 16:51:08 -080048import java.util.Set;
Charles Chan61fc0d82017-04-28 14:13:36 -070049import java.util.stream.Collectors;
Charles Chand6d581a2015-11-18 16:51:08 -080050
51/**
52 * Host provider that uses network config service to discover hosts.
53 */
54@Component(immediate = true)
55public class NetworkConfigHostProvider extends AbstractProvider implements HostProvider {
Ray Milkeyd84f89b2018-08-17 14:54:17 -070056 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Charles Chand6d581a2015-11-18 16:51:08 -080057 protected CoreService coreService;
58
Ray Milkeyd84f89b2018-08-17 14:54:17 -070059 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Charles Chand6d581a2015-11-18 16:51:08 -080060 protected HostProviderRegistry providerRegistry;
61
Ray Milkeyd84f89b2018-08-17 14:54:17 -070062 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Charles Chand6d581a2015-11-18 16:51:08 -080063 protected NetworkConfigRegistry networkConfigRegistry;
64
Charles Chand6d581a2015-11-18 16:51:08 -080065 private ApplicationId appId;
Charles Chan6ea94fc2016-05-10 17:29:47 -070066 private static final String APP_NAME = "org.onosproject.netcfghost";
Charles Chanb3007e12016-05-20 10:55:40 -070067 private static final ProviderId PROVIDER_ID = new ProviderId("host", APP_NAME);
Charles Chand6d581a2015-11-18 16:51:08 -080068 protected HostProviderService providerService;
69
70 private final Logger log = LoggerFactory.getLogger(getClass());
71 private final InternalNetworkConfigListener networkConfigListener =
72 new InternalNetworkConfigListener();
73
74 /**
75 * Creates an network config host location provider.
76 */
77 public NetworkConfigHostProvider() {
Charles Chan6ea94fc2016-05-10 17:29:47 -070078 super(PROVIDER_ID);
Charles Chand6d581a2015-11-18 16:51:08 -080079 }
80
81 @Activate
82 protected void activate() {
83 appId = coreService.registerApplication(APP_NAME);
84 providerService = providerRegistry.register(this);
85 networkConfigRegistry.addListener(networkConfigListener);
86 readInitialConfig();
87 log.info("Started");
88 }
89
90 @Deactivate
91 protected void deactivate() {
92 networkConfigRegistry.removeListener(networkConfigListener);
93 providerRegistry.unregister(this);
94 providerService = null;
95 log.info("Stopped");
96 }
97
98 @Override
99 public void triggerProbe(Host host) {
100 /*
Charles Chanb3007e12016-05-20 10:55:40 -0700101 * Note: All hosts are configured in network config host provider.
Charles Chand6d581a2015-11-18 16:51:08 -0800102 * Therefore no probe is required.
103 */
104 }
105
106 /**
107 * Adds host information.
108 * IP information will be appended if host exists.
109 *
110 * @param mac MAC address of the host
111 * @param vlan VLAN ID of the host
Charles Chan61fc0d82017-04-28 14:13:36 -0700112 * @param locations Location of the host
Charles Chand6d581a2015-11-18 16:51:08 -0800113 * @param ips Set of IP addresses of the host
114 */
Charles Chan61fc0d82017-04-28 14:13:36 -0700115 protected void addHost(MacAddress mac, VlanId vlan, Set<HostLocation> locations, Set<IpAddress> ips) {
Charles Chand6d581a2015-11-18 16:51:08 -0800116 HostId hid = HostId.hostId(mac, vlan);
Charles Chan7e0e2e62016-04-15 16:30:41 -0700117 HostDescription desc = (ips != null) ?
Charles Chan61fc0d82017-04-28 14:13:36 -0700118 new DefaultHostDescription(mac, vlan, locations, ips, true) :
119 new DefaultHostDescription(mac, vlan, locations, Collections.emptySet(), true);
Charles Chanb1e99242017-07-07 14:11:09 -0700120 providerService.hostDetected(hid, desc, true);
Charles Chand6d581a2015-11-18 16:51:08 -0800121 }
122
123 /**
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700124 * Adds host information.
125 * IP information will be appended if host exists.
126 *
127 * @param mac MAC address of the host
128 * @param vlan VLAN ID of the host
Charles Chaneb5bd492019-12-18 15:49:39 -0800129 * @param locations Locations of the host
130 * @param auxLocations auxiliary locations of the host
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700131 * @param ips Set of IP addresses of the host
132 * @param innerVlan host inner VLAN identifier
133 * @param outerTpid outer TPID of a host
134 */
Charles Chaneb5bd492019-12-18 15:49:39 -0800135 protected void addHost(MacAddress mac, VlanId vlan, Set<HostLocation> locations, Set<HostLocation> auxLocations,
136 Set<IpAddress> ips, VlanId innerVlan, EthType outerTpid) {
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700137 HostId hid = HostId.hostId(mac, vlan);
138 HostDescription desc = (ips != null) ?
Charles Chaneb5bd492019-12-18 15:49:39 -0800139 new DefaultHostDescription(mac, vlan, locations, auxLocations, ips,
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700140 innerVlan, outerTpid, true) :
Charles Chaneb5bd492019-12-18 15:49:39 -0800141 new DefaultHostDescription(mac, vlan, locations, auxLocations, Collections.emptySet(),
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700142 innerVlan, outerTpid, true);
143 providerService.hostDetected(hid, desc, true);
144 }
145
146 /**
Charles Chand6d581a2015-11-18 16:51:08 -0800147 * Updates host information.
148 * IP information will be replaced if host exists.
149 *
150 * @param mac MAC address of the host
151 * @param vlan VLAN ID of the host
Charles Chan61fc0d82017-04-28 14:13:36 -0700152 * @param locations Location of the host
Charles Chand6d581a2015-11-18 16:51:08 -0800153 * @param ips Set of IP addresses of the host
154 */
Charles Chan61fc0d82017-04-28 14:13:36 -0700155 protected void updateHost(MacAddress mac, VlanId vlan, Set<HostLocation> locations, Set<IpAddress> ips) {
Charles Chand6d581a2015-11-18 16:51:08 -0800156 HostId hid = HostId.hostId(mac, vlan);
Charles Chan61fc0d82017-04-28 14:13:36 -0700157 HostDescription desc = new DefaultHostDescription(mac, vlan, locations, ips, true);
Charles Chand6d581a2015-11-18 16:51:08 -0800158 providerService.hostDetected(hid, desc, true);
159 }
160
161 /**
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700162 * Updates host information.
163 * IP information will be replaced if host exists.
164 *
165 * @param mac MAC address of the host
166 * @param vlan VLAN ID of the host
Charles Chaneb5bd492019-12-18 15:49:39 -0800167 * @param locations Locations of the host
168 * @param auxLocations auxiliary locations of the host
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700169 * @param ips Set of IP addresses of the host
170 * @param innerVlan host inner VLAN identifier
171 * @param outerTpid outer TPID of a host
172 */
Charles Chaneb5bd492019-12-18 15:49:39 -0800173 protected void updateHost(MacAddress mac, VlanId vlan, Set<HostLocation> locations, Set<HostLocation> auxLocations,
174 Set<IpAddress> ips, VlanId innerVlan, EthType outerTpid) {
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700175 HostId hid = HostId.hostId(mac, vlan);
Charles Chaneb5bd492019-12-18 15:49:39 -0800176 HostDescription desc = new DefaultHostDescription(mac, vlan, locations, auxLocations, ips,
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700177 innerVlan, outerTpid, true);
178 providerService.hostDetected(hid, desc, true);
179 }
180
181 /**
Charles Chand6d581a2015-11-18 16:51:08 -0800182 * Removes host information.
183 *
184 * @param mac MAC address of the host
185 * @param vlan VLAN ID of the host
186 */
187 protected void removeHost(MacAddress mac, VlanId vlan) {
188 HostId hid = HostId.hostId(mac, vlan);
189 providerService.hostVanished(hid);
190 }
191
192 private void readInitialConfig() {
193 networkConfigRegistry.getSubjects(HostId.class).forEach(hostId -> {
194 MacAddress mac = hostId.mac();
195 VlanId vlan = hostId.vlanId();
196 BasicHostConfig hostConfig =
197 networkConfigRegistry.getConfig(hostId, BasicHostConfig.class);
198 Set<IpAddress> ipAddresses = hostConfig.ipAddresses();
Thomas Vachuska53cdbaa2018-05-01 11:23:29 -0700199 Set<HostLocation> locs = hostConfig.locations();
200 if (locs != null) {
201 Set<HostLocation> locations = locs.stream()
202 .map(hostLocation -> new HostLocation(hostLocation, System.currentTimeMillis()))
203 .collect(Collectors.toSet());
Charles Chaneb5bd492019-12-18 15:49:39 -0800204
205 // auxLocations allows to be null
206 Set<HostLocation> auxLocations = hostConfig.auxLocations();
207 if (auxLocations != null) {
208 auxLocations = auxLocations.stream()
209 .map(auxLocation -> new HostLocation(auxLocation, System.currentTimeMillis()))
210 .collect(Collectors.toSet());
211 }
212
Thomas Vachuska53cdbaa2018-05-01 11:23:29 -0700213 VlanId innerVlan = hostConfig.innerVlan();
214 EthType outerTpid = hostConfig.outerTpid();
Charles Chaneb5bd492019-12-18 15:49:39 -0800215 addHost(mac, vlan, locations, auxLocations, ipAddresses, innerVlan, outerTpid);
Thomas Vachuska53cdbaa2018-05-01 11:23:29 -0700216 } else {
217 log.warn("Host {} configuration {} is missing locations", hostId, hostConfig);
218 }
Charles Chand6d581a2015-11-18 16:51:08 -0800219 });
220 }
221
222 private class InternalNetworkConfigListener implements NetworkConfigListener {
223 @Override
224 public void event(NetworkConfigEvent event) {
225 // Do not process non-host, register and unregister events
226 if (!event.configClass().equals(BasicHostConfig.class) ||
227 event.type() == NetworkConfigEvent.Type.CONFIG_REGISTERED ||
228 event.type() == NetworkConfigEvent.Type.CONFIG_UNREGISTERED) {
229 return;
230 }
231
232 HostId hostId = (HostId) event.subject();
233 MacAddress mac = hostId.mac();
234 VlanId vlan = hostId.vlanId();
Charles Chanb34a0bd2017-09-12 13:32:41 -0700235 BasicHostConfig hostConfig = networkConfigRegistry.getConfig(hostId, BasicHostConfig.class);
Charles Chand6d581a2015-11-18 16:51:08 -0800236 Set<IpAddress> ipAddresses = null;
Charles Chan61fc0d82017-04-28 14:13:36 -0700237 Set<HostLocation> locations = null;
Charles Chaneb5bd492019-12-18 15:49:39 -0800238 Set<HostLocation> auxLocations = null;
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700239 VlanId innerVlan = VlanId.NONE;
240 EthType outerTpid = EthType.EtherType.UNKNOWN.ethType();
Charles Chand6d581a2015-11-18 16:51:08 -0800241
242 // Note: There will be no config presented in the CONFIG_REMOVE case
243 if (hostConfig != null) {
244 ipAddresses = hostConfig.ipAddresses();
Charles Chanb34a0bd2017-09-12 13:32:41 -0700245 locations = hostConfig.locations();
246 if (locations == null || locations.size() < 1) {
247 log.debug("Ignore network config event without host locations {}", event);
248 return;
249 }
250 locations = locations.stream()
Charles Chan61fc0d82017-04-28 14:13:36 -0700251 .map(hostLocation -> new HostLocation(hostLocation, System.currentTimeMillis()))
252 .collect(Collectors.toSet());
Charles Chaneb5bd492019-12-18 15:49:39 -0800253
254 // auxLocations allows to be null
255 auxLocations = hostConfig.auxLocations();
256 if (auxLocations != null) {
257 auxLocations = auxLocations.stream()
258 .map(auxLocation -> new HostLocation(auxLocation, System.currentTimeMillis()))
259 .collect(Collectors.toSet());
260 }
261
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700262 innerVlan = hostConfig.innerVlan();
263 outerTpid = hostConfig.outerTpid();
Charles Chand6d581a2015-11-18 16:51:08 -0800264 }
265
266 switch (event.type()) {
267 case CONFIG_ADDED:
Charles Chaneb5bd492019-12-18 15:49:39 -0800268 addHost(mac, vlan, locations, auxLocations, ipAddresses, innerVlan, outerTpid);
Charles Chand6d581a2015-11-18 16:51:08 -0800269 break;
270 case CONFIG_UPDATED:
Charles Chaneb5bd492019-12-18 15:49:39 -0800271 updateHost(mac, vlan, locations, auxLocations, ipAddresses, innerVlan, outerTpid);
Charles Chand6d581a2015-11-18 16:51:08 -0800272 break;
273 case CONFIG_REMOVED:
274 removeHost(mac, vlan);
275 break;
276 default:
277 break;
278 }
279 }
280 }
281}