blob: 36da63c5c980018e22d452727ada02a68a2ee57c [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 Pretee113df42016-12-22 15:52:06 -080088 private VplsAppConfig vplsAppConfig = null;
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 Pretee113df42016-12-22 15:52:06 -0800281 vplsAppConfig = configService.addConfig(vplsAppId, VplsAppConfig.class);
nosignal5fd282e2016-09-16 16:11:40 -0700282 }
283
284 oldIfacesOfVpls = ifacesOfVpls;
285 ifacesOfVpls = getConfigInterfaces();
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100286 vplsIfaces = getConfigCPointsFromIfaces();
Luca Prete092e8952016-10-26 16:25:56 +0200287 vplsEncaps = getConfigEncap();
288
nosignal5fd282e2016-09-16 16:11:40 -0700289 log.debug(CONFIG_CHANGED, ifacesOfVpls);
290 }
291
292 /**
293 * Retrieves the application identifier from core service.
294 */
295 private void loadAppId() {
296 vplsAppId = coreService.getAppId(VPLS_APP);
297 if (vplsAppId == null) {
298 log.warn(APP_ID_NULL);
299 }
300 }
301
302 /**
303 * Applies a given configuration to the VPLS application.
304 */
Luca Prete092e8952016-10-26 16:25:56 +0200305 private void applyConfig(VplsAppConfig vplsAppConfig) {
nosignal5fd282e2016-09-16 16:11:40 -0700306 loadAppId();
Luca Prete092e8952016-10-26 16:25:56 +0200307 configService.applyConfig(vplsAppId, VplsAppConfig.class, vplsAppConfig.node());
nosignal5fd282e2016-09-16 16:11:40 -0700308 }
309
310 /**
Luca Prete092e8952016-10-26 16:25:56 +0200311 * Retrieves the VPLS names and related encapsulation types from the
312 * configuration.
nosignal5fd282e2016-09-16 16:11:40 -0700313 *
Luca Prete092e8952016-10-26 16:25:56 +0200314 * @return a map of VPLS names and associated encapsulation types
315 */
316 private Map<String, EncapsulationType> getConfigEncap() {
317 Map<String, EncapsulationType> configEncap = new HashMap<>();
318
319 vplsAppConfig.vplss().forEach(vpls -> {
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100320 configEncap.put(vpls.name(), vpls.encap());
Luca Prete092e8952016-10-26 16:25:56 +0200321 });
322
323 return configEncap;
324 }
325
326 /**
327 * Retrieves the VPLS names and related interfaces names from the configuration.
328 *
329 * @return a map of VPLS names and related interface names
nosignal5fd282e2016-09-16 16:11:40 -0700330 */
331 private SetMultimap<String, String> getConfigInterfaces() {
332 SetMultimap<String, String> confIntfByVpls =
333 HashMultimap.create();
334
Luca Prete092e8952016-10-26 16:25:56 +0200335 vplsAppConfig.vplss().forEach(vpls -> {
nosignal5fd282e2016-09-16 16:11:40 -0700336 if (vpls.ifaces().isEmpty()) {
337 confIntfByVpls.put(vpls.name(), EMPTY);
338 } else {
339 vpls.ifaces().forEach(iface -> confIntfByVpls.put(vpls.name(), iface));
340 }
341 });
342
343 return confIntfByVpls;
344 }
345
346 /**
Luca Prete092e8952016-10-26 16:25:56 +0200347 * Retrieves the VPLS names and related interfaces from the configuration.
nosignal5fd282e2016-09-16 16:11:40 -0700348 *
Luca Prete092e8952016-10-26 16:25:56 +0200349 * @return a map of VPLS names and related interfaces
nosignal5fd282e2016-09-16 16:11:40 -0700350 */
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100351 private SetMultimap<String, Interface> getConfigCPointsFromIfaces() {
nosignal5fd282e2016-09-16 16:11:40 -0700352 log.debug(CHECK_CONFIG);
353
354 SetMultimap<String, Interface> confCPointsByIntf =
355 HashMultimap.create();
356
357 ifacesOfVpls.entries().forEach(vpls -> {
358 interfaceService.getInterfaces()
359 .stream()
360 .filter(intf -> intf.ipAddressesList().isEmpty())
361 .filter(intf -> intf.name().equals(vpls.getValue()))
362 .forEach(intf -> confCPointsByIntf.put(vpls.getKey(), intf));
363 });
364
365 return confCPointsByIntf;
366 }
367
368 /**
369 * Listener for VPLS configuration events.
370 */
371 private class InternalNetworkConfigListener implements NetworkConfigListener {
372 @Override
373 public void event(NetworkConfigEvent event) {
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100374 if (event.configClass() == VplsConfigService.CONFIG_CLASS) {
nosignal5fd282e2016-09-16 16:11:40 -0700375 log.debug(NET_CONF_EVENT, event.configClass());
376 switch (event.type()) {
377 case CONFIG_ADDED:
378 case CONFIG_UPDATED:
379 case CONFIG_REMOVED:
380 loadConfiguration();
381 break;
nosignal5fd282e2016-09-16 16:11:40 -0700382 default:
383 break;
384 }
385 }
386 }
387 }
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100388}