blob: 2622bc80657e9556dd3d975238d836150c763db4 [file] [log] [blame]
Luca Prete9c2ee072016-02-16 11:00:44 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Luca Prete9c2ee072016-02-16 11:00:44 -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 */
16package org.onosproject.vpls;
17
18import com.google.common.collect.HashMultimap;
19import com.google.common.collect.SetMultimap;
20import javafx.util.Pair;
21import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.onlab.packet.MacAddress;
27import org.onlab.packet.VlanId;
28import org.onosproject.app.ApplicationService;
29import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
Luca Pretea8854822016-04-26 16:30:55 -070031import org.onosproject.incubator.net.intf.InterfaceEvent;
32import org.onosproject.incubator.net.intf.InterfaceListener;
Luca Prete9c2ee072016-02-16 11:00:44 -080033import org.onosproject.incubator.net.intf.InterfaceService;
34import org.onosproject.net.ConnectPoint;
35import org.onosproject.net.Host;
36import org.onosproject.net.host.HostEvent;
37import org.onosproject.net.host.HostListener;
38import org.onosproject.net.host.HostService;
39import org.onosproject.net.intent.IntentService;
40import org.onosproject.routing.IntentSynchronizationAdminService;
41import org.onosproject.routing.IntentSynchronizationService;
42import org.slf4j.Logger;
43
44import java.util.Map;
45import java.util.Set;
46
47import static org.slf4j.LoggerFactory.getLogger;
48
49/**
50 * Application to create L2 broadcast overlay networks using VLAN.
51 */
52@Component(immediate = true)
53public class Vpls {
54 private static final String VPLS_APP = "org.onosproject.vpls";
55 private final Logger log = getLogger(getClass());
56
57 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 protected ApplicationService applicationService;
59
60 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 protected CoreService coreService;
62
63 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 protected HostService hostService;
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected IntentService intentService;
68
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected InterfaceService interfaceService;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected IntentSynchronizationService intentSynchronizer;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected IntentSynchronizationAdminService intentSynchronizerAdmin;
77
78 private final HostListener hostListener = new InternalHostListener();
79
Luca Pretea8854822016-04-26 16:30:55 -070080 private final InternalInterfaceListener interfaceListener
81 = new InternalInterfaceListener();
82
Luca Prete9c2ee072016-02-16 11:00:44 -080083 private IntentInstaller intentInstaller;
84
85 private ApplicationId appId;
86
87 @Activate
88 public void activate() {
89 appId = coreService.registerApplication(VPLS_APP);
90
91 intentInstaller = new IntentInstaller(appId,
92 intentService,
93 intentSynchronizer);
94
Luca Prete2705d662016-04-29 15:30:23 -070095 applicationService.registerDeactivateHook(appId, () -> {
96 intentSynchronizer.removeIntentsByAppId(appId);
97 });
Luca Prete9c2ee072016-02-16 11:00:44 -080098
99 hostService.addListener(hostListener);
Luca Pretea8854822016-04-26 16:30:55 -0700100 interfaceService.addListener(interfaceListener);
Luca Prete9c2ee072016-02-16 11:00:44 -0800101
102 setupConnectivity();
103
104 log.info("Started");
105 }
106
107 @Deactivate
108 public void deactivate() {
109 log.info("Stopped");
110 }
111
112 protected void setupConnectivity() {
113 /*
114 * Parse Configuration and get Connect Point by VlanId.
115 */
116 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan = getConfigCPoints();
117
118 /*
119 * Check that configured Connect Points have hosts attached and
120 * associate their Mac Address to the Connect Points configured.
121 */
122 SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
123 pairAvailableHosts(confCPointsByVlan);
124
125 /*
126 * Create and submit intents between the Connect Points.
127 * Intents for broadcast between all the configured Connect Points.
128 * Intents for unicast between all the configured Connect Points with
129 * hosts attached.
130 */
131 intentInstaller.installIntents(confHostPresentCPoint);
132 }
133
134 /**
135 * Computes the list of configured interfaces with a VLAN Id.
136 *
137 * @return the interfaces grouped by vlan id
138 */
139 protected SetMultimap<VlanId, ConnectPoint> getConfigCPoints() {
140 log.debug("Checking interface configuration");
141
142 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan =
143 HashMultimap.create();
144
145 interfaceService.getInterfaces()
Luca Preteb21d1712016-02-19 11:17:24 -0800146 .stream()
147 .filter(intf -> intf.ipAddressesList().isEmpty())
Luca Prete9c2ee072016-02-16 11:00:44 -0800148 .forEach(intf -> confCPointsByVlan.put(intf.vlan(),
149 intf.connectPoint()));
150 return confCPointsByVlan;
151 }
152
153 /**
154 * Checks if for any ConnectPoint configured there's an host present
155 * and in case it associate them together.
156 *
157 * @param confCPointsByVlan the configured ConnectPoints grouped by vlan id
158 * @return the configured ConnectPoints with eventual hosts associated.
159 */
160 protected SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> pairAvailableHosts(
161 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan) {
162 log.debug("Binding connected hosts mac addresses");
163
164 SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
165 HashMultimap.create();
166
167 confCPointsByVlan.entries()
168 .forEach(e -> bindMacAddr(e, confHostPresentCPoint));
169
170 return confHostPresentCPoint;
171 }
172
173 private void bindMacAddr(Map.Entry<VlanId, ConnectPoint> e,
174 SetMultimap<VlanId, Pair<ConnectPoint,
175 MacAddress>> confHostPresentCPoint) {
176 VlanId vlanId = e.getKey();
177 ConnectPoint cp = e.getValue();
178 Set<Host> connectedHosts = hostService.getConnectedHosts(cp);
179 if (!connectedHosts.isEmpty()) {
180 connectedHosts.forEach(host -> {
181 if (host.vlan().equals(vlanId)) {
182 confHostPresentCPoint.put(vlanId, new Pair<>(cp, host.mac()));
183 } else {
184 confHostPresentCPoint.put(vlanId, new Pair<>(cp, null));
185 }
186 });
187 } else {
188 confHostPresentCPoint.put(vlanId, new Pair<>(cp, null));
189 }
190 }
191
192 /**
193 * Listener for host events.
194 */
195 class InternalHostListener implements HostListener {
196 @Override
197 public void event(HostEvent event) {
198 log.debug("Received HostEvent {}", event);
199 switch (event.type()) {
200 case HOST_ADDED:
201 case HOST_UPDATED:
202 case HOST_REMOVED:
203 setupConnectivity();
204 break;
205 default:
206 break;
207 }
208 }
209 }
Luca Pretea8854822016-04-26 16:30:55 -0700210
211 /**
212 * Listener for interface configuration events.
213 */
214 private class InternalInterfaceListener implements InterfaceListener {
215 @Override
216 public void event(InterfaceEvent event) {
217 log.debug("Received InterfaceConfigEvent {}", event);
218 switch (event.type()) {
219 case INTERFACE_ADDED:
220 case INTERFACE_UPDATED:
221 case INTERFACE_REMOVED:
222 setupConnectivity();
223 break;
224 default:
225 break;
226 }
227 }
228 }
Luca Prete9c2ee072016-02-16 11:00:44 -0800229}