blob: 0c2f09ba75c130691fab6a6cb404f60fa5d19e8e [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;
nosignal5fd282e2016-09-16 16:11:40 -070045import org.onosproject.vpls.config.VplsConfigurationService;
46import 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
60public class VplsConfigurationImpl implements VplsConfigurationService {
61 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();
93 private Map<String, EncapsulationType> vplsEncaps = Maps.newHashMap();
nosignal5fd282e2016-09-16 16:11:40 -070094
95 private final InternalNetworkConfigListener configListener =
96 new InternalNetworkConfigListener();
97
Luca Prete092e8952016-10-26 16:25:56 +020098 private ConfigFactory<ApplicationId, VplsAppConfig> vplsConfigFactory =
99 new ConfigFactory<ApplicationId, VplsAppConfig>(
100 SubjectFactories.APP_SUBJECT_FACTORY, VplsAppConfig.class, VPLS) {
nosignal5fd282e2016-09-16 16:11:40 -0700101 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200102 public VplsAppConfig createConfig() {
103 return new VplsAppConfig();
nosignal5fd282e2016-09-16 16:11:40 -0700104 }
105 };
106
107 private ApplicationId vplsAppId;
108
109 @Activate
110 protected void active() {
111 configService.addListener(configListener);
112 registry.registerConfigFactory(vplsConfigFactory);
113 loadConfiguration();
114 log.info("Started");
115 }
116
117 @Deactivate
118 protected void deactive() {
119 registry.unregisterConfigFactory(vplsConfigFactory);
120 configService.removeListener(configListener);
121 log.info("Stopped");
122 }
123
Luca Prete092e8952016-10-26 16:25:56 +0200124 @Override
125 public void addVpls(String vplsName, Set<String> ifaces, String encap) {
126 EncapsulationType encapType = EncapsulationType.enumFromString(encap);
127
128 if (ifacesOfVpls.containsKey(vplsName)) {
129 if (ifaces.isEmpty()) {
130 return;
131 }
132 ifaces.forEach(iface -> vplsAppConfig.addIface(vplsName, iface));
133 vplsAppConfig.setEncap(vplsName, encapType);
134 } else {
135 vplsAppConfig.addVpls(new VplsConfig(vplsName, ifaces, encapType));
136 }
137
138 vplsAffectedByApi.add(vplsName);
139 applyConfig(vplsAppConfig);
140 }
141
142 @Override
143 public void removeVpls(String vplsName) {
144 if (ifacesOfVpls.containsKey(vplsName)) {
145 vplsAppConfig.removeVpls(vplsName);
146 vplsAffectedByApi.add(vplsName);
147 applyConfig(vplsAppConfig);
148 }
149 }
150
151 @Override
152 public void addIface(String vplsName, String iface) {
153 if (ifacesOfVpls.containsKey(vplsName)) {
154 vplsAppConfig.addIface(vplsName, iface);
155 vplsAffectedByApi.add(vplsName);
156 applyConfig(vplsAppConfig);
157 }
158 }
159
160 @Override
161 public void setEncap(String vplsName, String encap) {
162 EncapsulationType encapType = EncapsulationType.enumFromString(encap);
163
164 if (ifacesOfVpls.containsKey(vplsName)) {
165 vplsAppConfig.setEncap(vplsName, encapType);
166 vplsAffectedByApi.add(vplsName);
167 applyConfig(vplsAppConfig);
168 }
169 }
170
171 @Override
172 public void removeIface(String iface) {
173 if (ifacesOfVpls.containsValue(iface)) {
174 VplsConfig vpls = vplsAppConfig.vplsFromIface(iface);
175 vplsAppConfig.removeIface(vpls, iface);
176 vplsAffectedByApi.add(vpls.name());
177 applyConfig(vplsAppConfig);
178 }
179 }
180
181 @Override
182 public void cleanVplsConfig() {
183 ifacesOfVpls.entries().forEach(e -> {
184 vplsAppConfig.removeVpls(e.getKey());
185 vplsAffectedByApi.add(e.getKey());
186 });
187 applyConfig(vplsAppConfig);
188 }
189
190 @Override
191 public EncapsulationType encap(String vplsName) {
192 EncapsulationType encap = null;
193 if (vplsEncaps.containsKey(vplsName)) {
194 encap = vplsEncaps.get(vplsName);
195 }
196
197 return encap;
198 }
199
200 @Override
201 public Set<String> vplsAffectedByApi() {
202 Set<String> vplsNames = ImmutableSet.copyOf(vplsAffectedByApi);
203 vplsAffectedByApi.clear();
204
205 return vplsNames;
206 }
207
208 @Override
209 public Set<Interface> allIfaces() {
210 Set<Interface> allVplsInterfaces = new HashSet<>();
211 vplsIfaces.values().forEach(allVplsInterfaces::add);
212
213 return allVplsInterfaces;
214 }
215
216 @Override
217 public Set<Interface> ifaces(String vplsName) {
218 Set<Interface> vplsInterfaces = new HashSet<>();
219 vplsIfaces.get(vplsName).forEach(vplsInterfaces::add);
220
221 return vplsInterfaces;
222 }
223
224 @Override
225 public Set<String> vplsNames() {
226 return ifacesOfVpls.keySet();
227 }
228
229 @Override
230 public Set<String> vplsNamesOld() {
231 return oldIfacesOfVpls.keySet();
232 }
233
234 @Override
235 public SetMultimap<String, Interface> ifacesByVplsName() {
236 return ImmutableSetMultimap.copyOf(vplsIfaces);
237 }
238
239 @Override
240 public SetMultimap<String, Interface> ifacesByVplsName(VlanId vlan,
241 ConnectPoint connectPoint) {
242 String vplsName =
243 vplsIfaces.entries().stream()
244 .filter(e -> e.getValue().connectPoint().equals(connectPoint))
245 .filter(e -> e.getValue().vlan().equals(vlan))
246 .map(e -> e.getKey())
247 .findFirst()
248 .orElse(null);
249 SetMultimap<String, Interface> result = HashMultimap.create();
250 if (vplsName != null && vplsIfaces.containsKey(vplsName)) {
251 vplsIfaces.get(vplsName)
252 .forEach(intf -> result.put(vplsName, intf));
253 return result;
254 }
255 return null;
256 }
257
258 @Override
259 public Map<String, EncapsulationType> encapByVplsName() {
260 return ImmutableMap.copyOf(vplsEncaps);
261 }
262
nosignal5fd282e2016-09-16 16:11:40 -0700263 /**
264 * Retrieves the VPLS configuration from network configuration.
265 */
266 private void loadConfiguration() {
267 loadAppId();
268
Luca Prete092e8952016-10-26 16:25:56 +0200269 vplsAppConfig = configService.getConfig(vplsAppId, VplsAppConfig.class);
nosignal5fd282e2016-09-16 16:11:40 -0700270
Luca Prete092e8952016-10-26 16:25:56 +0200271 if (vplsAppConfig == null) {
nosignal5fd282e2016-09-16 16:11:40 -0700272 log.warn(CONFIG_NULL);
Luca Prete092e8952016-10-26 16:25:56 +0200273 configService.addConfig(vplsAppId, VplsAppConfig.class);
nosignal5fd282e2016-09-16 16:11:40 -0700274 return;
275 }
276
277 oldIfacesOfVpls = ifacesOfVpls;
278 ifacesOfVpls = getConfigInterfaces();
Luca Prete092e8952016-10-26 16:25:56 +0200279 vplsIfaces = getConfigCPoints();
280 vplsEncaps = getConfigEncap();
281
nosignal5fd282e2016-09-16 16:11:40 -0700282 log.debug(CONFIG_CHANGED, ifacesOfVpls);
283 }
284
285 /**
286 * Retrieves the application identifier from core service.
287 */
288 private void loadAppId() {
289 vplsAppId = coreService.getAppId(VPLS_APP);
290 if (vplsAppId == null) {
291 log.warn(APP_ID_NULL);
292 }
293 }
294
295 /**
296 * Applies a given configuration to the VPLS application.
297 */
Luca Prete092e8952016-10-26 16:25:56 +0200298 private void applyConfig(VplsAppConfig vplsAppConfig) {
nosignal5fd282e2016-09-16 16:11:40 -0700299 loadAppId();
Luca Prete092e8952016-10-26 16:25:56 +0200300 configService.applyConfig(vplsAppId, VplsAppConfig.class, vplsAppConfig.node());
nosignal5fd282e2016-09-16 16:11:40 -0700301 }
302
303 /**
Luca Prete092e8952016-10-26 16:25:56 +0200304 * Retrieves the VPLS names and related encapsulation types from the
305 * configuration.
nosignal5fd282e2016-09-16 16:11:40 -0700306 *
Luca Prete092e8952016-10-26 16:25:56 +0200307 * @return a map of VPLS names and associated encapsulation types
308 */
309 private Map<String, EncapsulationType> getConfigEncap() {
310 Map<String, EncapsulationType> configEncap = new HashMap<>();
311
312 vplsAppConfig.vplss().forEach(vpls -> {
313 configEncap.put(vpls.name(), vpls.encap());
314 });
315
316 return configEncap;
317 }
318
319 /**
320 * Retrieves the VPLS names and related interfaces names from the configuration.
321 *
322 * @return a map of VPLS names and related interface names
nosignal5fd282e2016-09-16 16:11:40 -0700323 */
324 private SetMultimap<String, String> getConfigInterfaces() {
325 SetMultimap<String, String> confIntfByVpls =
326 HashMultimap.create();
327
Luca Prete092e8952016-10-26 16:25:56 +0200328 vplsAppConfig.vplss().forEach(vpls -> {
nosignal5fd282e2016-09-16 16:11:40 -0700329 if (vpls.ifaces().isEmpty()) {
330 confIntfByVpls.put(vpls.name(), EMPTY);
331 } else {
332 vpls.ifaces().forEach(iface -> confIntfByVpls.put(vpls.name(), iface));
333 }
334 });
335
336 return confIntfByVpls;
337 }
338
339 /**
Luca Prete092e8952016-10-26 16:25:56 +0200340 * Retrieves the VPLS names and related interfaces from the configuration.
nosignal5fd282e2016-09-16 16:11:40 -0700341 *
Luca Prete092e8952016-10-26 16:25:56 +0200342 * @return a map of VPLS names and related interfaces
nosignal5fd282e2016-09-16 16:11:40 -0700343 */
344 private SetMultimap<String, Interface> getConfigCPoints() {
345 log.debug(CHECK_CONFIG);
346
347 SetMultimap<String, Interface> confCPointsByIntf =
348 HashMultimap.create();
349
350 ifacesOfVpls.entries().forEach(vpls -> {
351 interfaceService.getInterfaces()
352 .stream()
353 .filter(intf -> intf.ipAddressesList().isEmpty())
354 .filter(intf -> intf.name().equals(vpls.getValue()))
355 .forEach(intf -> confCPointsByIntf.put(vpls.getKey(), intf));
356 });
357
358 return confCPointsByIntf;
359 }
360
361 /**
362 * Listener for VPLS configuration events.
363 */
364 private class InternalNetworkConfigListener implements NetworkConfigListener {
365 @Override
366 public void event(NetworkConfigEvent event) {
367 if (event.configClass() == VplsConfigurationService.CONFIG_CLASS) {
368 log.debug(NET_CONF_EVENT, event.configClass());
369 switch (event.type()) {
370 case CONFIG_ADDED:
371 case CONFIG_UPDATED:
372 case CONFIG_REMOVED:
373 loadConfiguration();
374 break;
nosignal5fd282e2016-09-16 16:11:40 -0700375 default:
376 break;
377 }
378 }
379 }
380 }
nosignal5fd282e2016-09-16 16:11:40 -0700381}