blob: 658a27d5af8a402a52683a9f4d913e604e462b73 [file] [log] [blame]
nosignal5fd282e2016-09-16 16:11:40 -07001/*
2 * Copyright 2016-present 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 */
16package org.onosproject.vpls.config.impl;
17
18import com.google.common.collect.HashMultimap;
Luca Prete092e8952016-10-26 16:25:56 +020019import com.google.common.collect.ImmutableMap;
nosignal5fd282e2016-09-16 16:11:40 -070020import com.google.common.collect.ImmutableSet;
21import com.google.common.collect.ImmutableSetMultimap;
Luca Prete092e8952016-10-26 16:25:56 +020022import com.google.common.collect.Maps;
nosignal5fd282e2016-09-16 16:11:40 -070023import com.google.common.collect.SetMultimap;
24import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Component;
26import org.apache.felix.scr.annotations.Deactivate;
27import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
29import org.apache.felix.scr.annotations.Service;
30import org.onlab.packet.VlanId;
31import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
33import org.onosproject.incubator.net.intf.Interface;
34import org.onosproject.incubator.net.intf.InterfaceService;
35import org.onosproject.net.ConnectPoint;
Luca Prete092e8952016-10-26 16:25:56 +020036import org.onosproject.net.EncapsulationType;
37import org.onosproject.net.config.ConfigFactory;
38import org.onosproject.net.config.NetworkConfigEvent;
39import org.onosproject.net.config.NetworkConfigListener;
nosignal5fd282e2016-09-16 16:11:40 -070040import org.onosproject.net.config.NetworkConfigRegistry;
41import org.onosproject.net.config.NetworkConfigService;
nosignal5fd282e2016-09-16 16:11:40 -070042import org.onosproject.net.config.basics.SubjectFactories;
Luca Prete092e8952016-10-26 16:25:56 +020043import org.onosproject.vpls.config.VplsAppConfig;
nosignal5fd282e2016-09-16 16:11:40 -070044import org.onosproject.vpls.config.VplsConfig;
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010045import org.onosproject.vpls.config.VplsConfigService;
nosignal5fd282e2016-09-16 16:11:40 -070046import org.slf4j.Logger;
47import org.slf4j.LoggerFactory;
48
Luca Prete092e8952016-10-26 16:25:56 +020049import java.util.HashMap;
nosignal5fd282e2016-09-16 16:11:40 -070050import java.util.HashSet;
Luca Prete092e8952016-10-26 16:25:56 +020051import java.util.Map;
nosignal5fd282e2016-09-16 16:11:40 -070052import java.util.Set;
53
54/**
55 * Implementation of VPLSConfigurationService which reads VPLS configuration
56 * from the network configuration service.
57 */
58@Component(immediate = true)
59@Service
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010060public class VplsConfigImpl implements VplsConfigService {
nosignal5fd282e2016-09-16 16:11:40 -070061 private static final String VPLS_APP = "org.onosproject.vpls";
62 private static final String VPLS = "vpls";
63 private static final String EMPTY = "";
64 private static final String CONFIG_NULL = "VPLS configuration not defined";
65 private static final String APP_ID_NULL = "VPLS application ID is null";
66 private static final String CONFIG_CHANGED = "VPLS configuration changed: {}";
67 private static final String CHECK_CONFIG =
68 "Checking the interface configuration";
69 private static final String NET_CONF_EVENT =
70 "Received NetworkConfigEvent {}";
71
72 private final Logger log = LoggerFactory.getLogger(getClass());
73
74 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 protected NetworkConfigRegistry registry;
76
77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 protected CoreService coreService;
79
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected InterfaceService interfaceService;
82
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected NetworkConfigService configService;
85
86 private final Set<String> vplsAffectedByApi = new HashSet<>();
87
Luca Prete092e8952016-10-26 16:25:56 +020088 private VplsAppConfig vplsAppConfig = new VplsAppConfig();
nosignal5fd282e2016-09-16 16:11:40 -070089
90 private SetMultimap<String, String> ifacesOfVpls = HashMultimap.create();
91 private SetMultimap<String, String> oldIfacesOfVpls = HashMultimap.create();
Luca Prete092e8952016-10-26 16:25:56 +020092 private SetMultimap<String, Interface> vplsIfaces = HashMultimap.create();
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010093
Luca Prete092e8952016-10-26 16:25:56 +020094 private Map<String, EncapsulationType> vplsEncaps = Maps.newHashMap();
nosignal5fd282e2016-09-16 16:11:40 -070095
96 private final InternalNetworkConfigListener configListener =
97 new InternalNetworkConfigListener();
98
Luca Prete092e8952016-10-26 16:25:56 +020099 private ConfigFactory<ApplicationId, VplsAppConfig> vplsConfigFactory =
100 new ConfigFactory<ApplicationId, VplsAppConfig>(
101 SubjectFactories.APP_SUBJECT_FACTORY, VplsAppConfig.class, VPLS) {
nosignal5fd282e2016-09-16 16:11:40 -0700102 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200103 public VplsAppConfig createConfig() {
104 return new VplsAppConfig();
nosignal5fd282e2016-09-16 16:11:40 -0700105 }
106 };
107
108 private ApplicationId vplsAppId;
109
110 @Activate
111 protected void active() {
112 configService.addListener(configListener);
113 registry.registerConfigFactory(vplsConfigFactory);
114 loadConfiguration();
115 log.info("Started");
116 }
117
118 @Deactivate
119 protected void deactive() {
120 registry.unregisterConfigFactory(vplsConfigFactory);
121 configService.removeListener(configListener);
122 log.info("Stopped");
123 }
124
Luca Prete092e8952016-10-26 16:25:56 +0200125 @Override
126 public void addVpls(String vplsName, Set<String> ifaces, String encap) {
127 EncapsulationType encapType = EncapsulationType.enumFromString(encap);
128
129 if (ifacesOfVpls.containsKey(vplsName)) {
130 if (ifaces.isEmpty()) {
131 return;
132 }
133 ifaces.forEach(iface -> vplsAppConfig.addIface(vplsName, iface));
134 vplsAppConfig.setEncap(vplsName, encapType);
135 } else {
136 vplsAppConfig.addVpls(new VplsConfig(vplsName, ifaces, encapType));
137 }
138
139 vplsAffectedByApi.add(vplsName);
140 applyConfig(vplsAppConfig);
141 }
142
143 @Override
144 public void removeVpls(String vplsName) {
145 if (ifacesOfVpls.containsKey(vplsName)) {
146 vplsAppConfig.removeVpls(vplsName);
147 vplsAffectedByApi.add(vplsName);
148 applyConfig(vplsAppConfig);
149 }
150 }
151
152 @Override
153 public void addIface(String vplsName, String iface) {
154 if (ifacesOfVpls.containsKey(vplsName)) {
155 vplsAppConfig.addIface(vplsName, iface);
156 vplsAffectedByApi.add(vplsName);
157 applyConfig(vplsAppConfig);
158 }
159 }
160
161 @Override
162 public void setEncap(String vplsName, String encap) {
163 EncapsulationType encapType = EncapsulationType.enumFromString(encap);
164
165 if (ifacesOfVpls.containsKey(vplsName)) {
166 vplsAppConfig.setEncap(vplsName, encapType);
167 vplsAffectedByApi.add(vplsName);
168 applyConfig(vplsAppConfig);
169 }
170 }
171
172 @Override
173 public void removeIface(String iface) {
174 if (ifacesOfVpls.containsValue(iface)) {
175 VplsConfig vpls = vplsAppConfig.vplsFromIface(iface);
176 vplsAppConfig.removeIface(vpls, iface);
177 vplsAffectedByApi.add(vpls.name());
178 applyConfig(vplsAppConfig);
179 }
180 }
181
182 @Override
183 public void cleanVplsConfig() {
184 ifacesOfVpls.entries().forEach(e -> {
185 vplsAppConfig.removeVpls(e.getKey());
186 vplsAffectedByApi.add(e.getKey());
187 });
188 applyConfig(vplsAppConfig);
189 }
190
191 @Override
192 public EncapsulationType encap(String vplsName) {
193 EncapsulationType encap = null;
194 if (vplsEncaps.containsKey(vplsName)) {
195 encap = vplsEncaps.get(vplsName);
196 }
197
198 return encap;
199 }
200
201 @Override
202 public Set<String> vplsAffectedByApi() {
203 Set<String> vplsNames = ImmutableSet.copyOf(vplsAffectedByApi);
204 vplsAffectedByApi.clear();
Luca Prete092e8952016-10-26 16:25:56 +0200205 return vplsNames;
206 }
207
208 @Override
209 public Set<Interface> allIfaces() {
210 Set<Interface> allVplsInterfaces = new HashSet<>();
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100211 interfaceService.getInterfaces().forEach(allVplsInterfaces::add);
212 return allVplsInterfaces;
213 }
Luca Prete092e8952016-10-26 16:25:56 +0200214
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100215 @Override
216 public Set<Interface> ifaces() {
217 Set<Interface> allVplsInterfaces = new HashSet<>();
218 vplsIfaces.values().forEach(allVplsInterfaces::add);
Luca Prete092e8952016-10-26 16:25:56 +0200219 return allVplsInterfaces;
220 }
221
222 @Override
223 public Set<Interface> ifaces(String vplsName) {
224 Set<Interface> vplsInterfaces = new HashSet<>();
225 vplsIfaces.get(vplsName).forEach(vplsInterfaces::add);
Luca Prete092e8952016-10-26 16:25:56 +0200226 return vplsInterfaces;
227 }
228
229 @Override
230 public Set<String> vplsNames() {
231 return ifacesOfVpls.keySet();
232 }
233
234 @Override
235 public Set<String> vplsNamesOld() {
236 return oldIfacesOfVpls.keySet();
237 }
238
239 @Override
240 public SetMultimap<String, Interface> ifacesByVplsName() {
241 return ImmutableSetMultimap.copyOf(vplsIfaces);
242 }
243
244 @Override
245 public SetMultimap<String, Interface> ifacesByVplsName(VlanId vlan,
246 ConnectPoint connectPoint) {
247 String vplsName =
248 vplsIfaces.entries().stream()
249 .filter(e -> e.getValue().connectPoint().equals(connectPoint))
250 .filter(e -> e.getValue().vlan().equals(vlan))
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100251 .map(Map.Entry::getKey)
Luca Prete092e8952016-10-26 16:25:56 +0200252 .findFirst()
253 .orElse(null);
254 SetMultimap<String, Interface> result = HashMultimap.create();
255 if (vplsName != null && vplsIfaces.containsKey(vplsName)) {
256 vplsIfaces.get(vplsName)
257 .forEach(intf -> result.put(vplsName, intf));
258 return result;
259 }
260 return null;
261 }
262
263 @Override
264 public Map<String, EncapsulationType> encapByVplsName() {
265 return ImmutableMap.copyOf(vplsEncaps);
266 }
267
nosignal5fd282e2016-09-16 16:11:40 -0700268 /**
269 * Retrieves the VPLS configuration from network configuration.
270 */
271 private void loadConfiguration() {
272 loadAppId();
273
Luca Prete092e8952016-10-26 16:25:56 +0200274 vplsAppConfig = configService.getConfig(vplsAppId, VplsAppConfig.class);
nosignal5fd282e2016-09-16 16:11:40 -0700275
Luca Prete092e8952016-10-26 16:25:56 +0200276 if (vplsAppConfig == null) {
nosignal5fd282e2016-09-16 16:11:40 -0700277 log.warn(CONFIG_NULL);
Luca Prete092e8952016-10-26 16:25:56 +0200278 configService.addConfig(vplsAppId, VplsAppConfig.class);
nosignal5fd282e2016-09-16 16:11:40 -0700279 return;
280 }
281
282 oldIfacesOfVpls = ifacesOfVpls;
283 ifacesOfVpls = getConfigInterfaces();
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100284 vplsIfaces = getConfigCPointsFromIfaces();
Luca Prete092e8952016-10-26 16:25:56 +0200285 vplsEncaps = getConfigEncap();
286
nosignal5fd282e2016-09-16 16:11:40 -0700287 log.debug(CONFIG_CHANGED, ifacesOfVpls);
288 }
289
290 /**
291 * Retrieves the application identifier from core service.
292 */
293 private void loadAppId() {
294 vplsAppId = coreService.getAppId(VPLS_APP);
295 if (vplsAppId == null) {
296 log.warn(APP_ID_NULL);
297 }
298 }
299
300 /**
301 * Applies a given configuration to the VPLS application.
302 */
Luca Prete092e8952016-10-26 16:25:56 +0200303 private void applyConfig(VplsAppConfig vplsAppConfig) {
nosignal5fd282e2016-09-16 16:11:40 -0700304 loadAppId();
Luca Prete092e8952016-10-26 16:25:56 +0200305 configService.applyConfig(vplsAppId, VplsAppConfig.class, vplsAppConfig.node());
nosignal5fd282e2016-09-16 16:11:40 -0700306 }
307
308 /**
Luca Prete092e8952016-10-26 16:25:56 +0200309 * Retrieves the VPLS names and related encapsulation types from the
310 * configuration.
nosignal5fd282e2016-09-16 16:11:40 -0700311 *
Luca Prete092e8952016-10-26 16:25:56 +0200312 * @return a map of VPLS names and associated encapsulation types
313 */
314 private Map<String, EncapsulationType> getConfigEncap() {
315 Map<String, EncapsulationType> configEncap = new HashMap<>();
316
317 vplsAppConfig.vplss().forEach(vpls -> {
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100318 configEncap.put(vpls.name(), vpls.encap());
Luca Prete092e8952016-10-26 16:25:56 +0200319 });
320
321 return configEncap;
322 }
323
324 /**
325 * Retrieves the VPLS names and related interfaces names from the configuration.
326 *
327 * @return a map of VPLS names and related interface names
nosignal5fd282e2016-09-16 16:11:40 -0700328 */
329 private SetMultimap<String, String> getConfigInterfaces() {
330 SetMultimap<String, String> confIntfByVpls =
331 HashMultimap.create();
332
Luca Prete092e8952016-10-26 16:25:56 +0200333 vplsAppConfig.vplss().forEach(vpls -> {
nosignal5fd282e2016-09-16 16:11:40 -0700334 if (vpls.ifaces().isEmpty()) {
335 confIntfByVpls.put(vpls.name(), EMPTY);
336 } else {
337 vpls.ifaces().forEach(iface -> confIntfByVpls.put(vpls.name(), iface));
338 }
339 });
340
341 return confIntfByVpls;
342 }
343
344 /**
Luca Prete092e8952016-10-26 16:25:56 +0200345 * Retrieves the VPLS names and related interfaces from the configuration.
nosignal5fd282e2016-09-16 16:11:40 -0700346 *
Luca Prete092e8952016-10-26 16:25:56 +0200347 * @return a map of VPLS names and related interfaces
nosignal5fd282e2016-09-16 16:11:40 -0700348 */
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100349 private SetMultimap<String, Interface> getConfigCPointsFromIfaces() {
nosignal5fd282e2016-09-16 16:11:40 -0700350 log.debug(CHECK_CONFIG);
351
352 SetMultimap<String, Interface> confCPointsByIntf =
353 HashMultimap.create();
354
355 ifacesOfVpls.entries().forEach(vpls -> {
356 interfaceService.getInterfaces()
357 .stream()
358 .filter(intf -> intf.ipAddressesList().isEmpty())
359 .filter(intf -> intf.name().equals(vpls.getValue()))
360 .forEach(intf -> confCPointsByIntf.put(vpls.getKey(), intf));
361 });
362
363 return confCPointsByIntf;
364 }
365
366 /**
367 * Listener for VPLS configuration events.
368 */
369 private class InternalNetworkConfigListener implements NetworkConfigListener {
370 @Override
371 public void event(NetworkConfigEvent event) {
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100372 if (event.configClass() == VplsConfigService.CONFIG_CLASS) {
nosignal5fd282e2016-09-16 16:11:40 -0700373 log.debug(NET_CONF_EVENT, event.configClass());
374 switch (event.type()) {
375 case CONFIG_ADDED:
376 case CONFIG_UPDATED:
377 case CONFIG_REMOVED:
378 loadConfiguration();
379 break;
nosignal5fd282e2016-09-16 16:11:40 -0700380 default:
381 break;
382 }
383 }
384 }
385 }
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100386}