blob: ad1c707b202ee15ee1c248383fbe4f5eae982089 [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() {
Luca Pretedce16f82016-11-22 13:11:56 -0800210 Set<Interface> interfaces = new HashSet<>();
211 interfaceService.getInterfaces().stream()
212 .filter(iface -> iface.ipAddressesList() == null ||
213 iface.ipAddressesList().isEmpty())
214 .forEach(interfaces::add);
215 return interfaces;
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100216 }
Luca Prete092e8952016-10-26 16:25:56 +0200217
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100218 @Override
219 public Set<Interface> ifaces() {
Luca Pretedce16f82016-11-22 13:11:56 -0800220 Set<Interface> interfaces = new HashSet<>();
221 vplsIfaces.values().forEach(interfaces::add);
222 return interfaces;
Luca Prete092e8952016-10-26 16:25:56 +0200223 }
224
225 @Override
226 public Set<Interface> ifaces(String vplsName) {
227 Set<Interface> vplsInterfaces = new HashSet<>();
228 vplsIfaces.get(vplsName).forEach(vplsInterfaces::add);
Luca Prete092e8952016-10-26 16:25:56 +0200229 return vplsInterfaces;
230 }
231
232 @Override
233 public Set<String> vplsNames() {
234 return ifacesOfVpls.keySet();
235 }
236
237 @Override
238 public Set<String> vplsNamesOld() {
239 return oldIfacesOfVpls.keySet();
240 }
241
242 @Override
243 public SetMultimap<String, Interface> ifacesByVplsName() {
244 return ImmutableSetMultimap.copyOf(vplsIfaces);
245 }
246
247 @Override
248 public SetMultimap<String, Interface> ifacesByVplsName(VlanId vlan,
249 ConnectPoint connectPoint) {
250 String vplsName =
251 vplsIfaces.entries().stream()
252 .filter(e -> e.getValue().connectPoint().equals(connectPoint))
253 .filter(e -> e.getValue().vlan().equals(vlan))
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100254 .map(Map.Entry::getKey)
Luca Prete092e8952016-10-26 16:25:56 +0200255 .findFirst()
256 .orElse(null);
257 SetMultimap<String, Interface> result = HashMultimap.create();
258 if (vplsName != null && vplsIfaces.containsKey(vplsName)) {
259 vplsIfaces.get(vplsName)
260 .forEach(intf -> result.put(vplsName, intf));
261 return result;
262 }
263 return null;
264 }
265
266 @Override
267 public Map<String, EncapsulationType> encapByVplsName() {
268 return ImmutableMap.copyOf(vplsEncaps);
269 }
270
nosignal5fd282e2016-09-16 16:11:40 -0700271 /**
272 * Retrieves the VPLS configuration from network configuration.
273 */
274 private void loadConfiguration() {
275 loadAppId();
276
Luca Prete092e8952016-10-26 16:25:56 +0200277 vplsAppConfig = configService.getConfig(vplsAppId, VplsAppConfig.class);
nosignal5fd282e2016-09-16 16:11:40 -0700278
Luca Prete092e8952016-10-26 16:25:56 +0200279 if (vplsAppConfig == null) {
nosignal5fd282e2016-09-16 16:11:40 -0700280 log.warn(CONFIG_NULL);
Luca Prete092e8952016-10-26 16:25:56 +0200281 configService.addConfig(vplsAppId, VplsAppConfig.class);
nosignal5fd282e2016-09-16 16:11:40 -0700282 return;
283 }
284
285 oldIfacesOfVpls = ifacesOfVpls;
286 ifacesOfVpls = getConfigInterfaces();
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100287 vplsIfaces = getConfigCPointsFromIfaces();
Luca Prete092e8952016-10-26 16:25:56 +0200288 vplsEncaps = getConfigEncap();
289
nosignal5fd282e2016-09-16 16:11:40 -0700290 log.debug(CONFIG_CHANGED, ifacesOfVpls);
291 }
292
293 /**
294 * Retrieves the application identifier from core service.
295 */
296 private void loadAppId() {
297 vplsAppId = coreService.getAppId(VPLS_APP);
298 if (vplsAppId == null) {
299 log.warn(APP_ID_NULL);
300 }
301 }
302
303 /**
304 * Applies a given configuration to the VPLS application.
305 */
Luca Prete092e8952016-10-26 16:25:56 +0200306 private void applyConfig(VplsAppConfig vplsAppConfig) {
nosignal5fd282e2016-09-16 16:11:40 -0700307 loadAppId();
Luca Prete092e8952016-10-26 16:25:56 +0200308 configService.applyConfig(vplsAppId, VplsAppConfig.class, vplsAppConfig.node());
nosignal5fd282e2016-09-16 16:11:40 -0700309 }
310
311 /**
Luca Prete092e8952016-10-26 16:25:56 +0200312 * Retrieves the VPLS names and related encapsulation types from the
313 * configuration.
nosignal5fd282e2016-09-16 16:11:40 -0700314 *
Luca Prete092e8952016-10-26 16:25:56 +0200315 * @return a map of VPLS names and associated encapsulation types
316 */
317 private Map<String, EncapsulationType> getConfigEncap() {
318 Map<String, EncapsulationType> configEncap = new HashMap<>();
319
320 vplsAppConfig.vplss().forEach(vpls -> {
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100321 configEncap.put(vpls.name(), vpls.encap());
Luca Prete092e8952016-10-26 16:25:56 +0200322 });
323
324 return configEncap;
325 }
326
327 /**
328 * Retrieves the VPLS names and related interfaces names from the configuration.
329 *
330 * @return a map of VPLS names and related interface names
nosignal5fd282e2016-09-16 16:11:40 -0700331 */
332 private SetMultimap<String, String> getConfigInterfaces() {
333 SetMultimap<String, String> confIntfByVpls =
334 HashMultimap.create();
335
Luca Prete092e8952016-10-26 16:25:56 +0200336 vplsAppConfig.vplss().forEach(vpls -> {
nosignal5fd282e2016-09-16 16:11:40 -0700337 if (vpls.ifaces().isEmpty()) {
338 confIntfByVpls.put(vpls.name(), EMPTY);
339 } else {
340 vpls.ifaces().forEach(iface -> confIntfByVpls.put(vpls.name(), iface));
341 }
342 });
343
344 return confIntfByVpls;
345 }
346
347 /**
Luca Prete092e8952016-10-26 16:25:56 +0200348 * Retrieves the VPLS names and related interfaces from the configuration.
nosignal5fd282e2016-09-16 16:11:40 -0700349 *
Luca Prete092e8952016-10-26 16:25:56 +0200350 * @return a map of VPLS names and related interfaces
nosignal5fd282e2016-09-16 16:11:40 -0700351 */
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100352 private SetMultimap<String, Interface> getConfigCPointsFromIfaces() {
nosignal5fd282e2016-09-16 16:11:40 -0700353 log.debug(CHECK_CONFIG);
354
355 SetMultimap<String, Interface> confCPointsByIntf =
356 HashMultimap.create();
357
358 ifacesOfVpls.entries().forEach(vpls -> {
359 interfaceService.getInterfaces()
360 .stream()
361 .filter(intf -> intf.ipAddressesList().isEmpty())
362 .filter(intf -> intf.name().equals(vpls.getValue()))
363 .forEach(intf -> confCPointsByIntf.put(vpls.getKey(), intf));
364 });
365
366 return confCPointsByIntf;
367 }
368
369 /**
370 * Listener for VPLS configuration events.
371 */
372 private class InternalNetworkConfigListener implements NetworkConfigListener {
373 @Override
374 public void event(NetworkConfigEvent event) {
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100375 if (event.configClass() == VplsConfigService.CONFIG_CLASS) {
nosignal5fd282e2016-09-16 16:11:40 -0700376 log.debug(NET_CONF_EVENT, event.configClass());
377 switch (event.type()) {
378 case CONFIG_ADDED:
379 case CONFIG_UPDATED:
380 case CONFIG_REMOVED:
381 loadConfiguration();
382 break;
nosignal5fd282e2016-09-16 16:11:40 -0700383 default:
384 break;
385 }
386 }
387 }
388 }
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100389}