blob: 4898f914c2b547cf62be50a88e789ef56d61a75c [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
95 applicationService.registerDeactivateHook(appId,
96 intentSynchronizerAdmin::removeIntents);
97
98 hostService.addListener(hostListener);
Luca Pretea8854822016-04-26 16:30:55 -070099 interfaceService.addListener(interfaceListener);
Luca Prete9c2ee072016-02-16 11:00:44 -0800100
101 setupConnectivity();
102
103 log.info("Started");
104 }
105
106 @Deactivate
107 public void deactivate() {
108 log.info("Stopped");
109 }
110
111 protected void setupConnectivity() {
112 /*
113 * Parse Configuration and get Connect Point by VlanId.
114 */
115 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan = getConfigCPoints();
116
117 /*
118 * Check that configured Connect Points have hosts attached and
119 * associate their Mac Address to the Connect Points configured.
120 */
121 SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
122 pairAvailableHosts(confCPointsByVlan);
123
124 /*
125 * Create and submit intents between the Connect Points.
126 * Intents for broadcast between all the configured Connect Points.
127 * Intents for unicast between all the configured Connect Points with
128 * hosts attached.
129 */
130 intentInstaller.installIntents(confHostPresentCPoint);
131 }
132
133 /**
134 * Computes the list of configured interfaces with a VLAN Id.
135 *
136 * @return the interfaces grouped by vlan id
137 */
138 protected SetMultimap<VlanId, ConnectPoint> getConfigCPoints() {
139 log.debug("Checking interface configuration");
140
141 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan =
142 HashMultimap.create();
143
144 interfaceService.getInterfaces()
Luca Preteb21d1712016-02-19 11:17:24 -0800145 .stream()
146 .filter(intf -> intf.ipAddressesList().isEmpty())
Luca Prete9c2ee072016-02-16 11:00:44 -0800147 .forEach(intf -> confCPointsByVlan.put(intf.vlan(),
148 intf.connectPoint()));
149 return confCPointsByVlan;
150 }
151
152 /**
153 * Checks if for any ConnectPoint configured there's an host present
154 * and in case it associate them together.
155 *
156 * @param confCPointsByVlan the configured ConnectPoints grouped by vlan id
157 * @return the configured ConnectPoints with eventual hosts associated.
158 */
159 protected SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> pairAvailableHosts(
160 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan) {
161 log.debug("Binding connected hosts mac addresses");
162
163 SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
164 HashMultimap.create();
165
166 confCPointsByVlan.entries()
167 .forEach(e -> bindMacAddr(e, confHostPresentCPoint));
168
169 return confHostPresentCPoint;
170 }
171
172 private void bindMacAddr(Map.Entry<VlanId, ConnectPoint> e,
173 SetMultimap<VlanId, Pair<ConnectPoint,
174 MacAddress>> confHostPresentCPoint) {
175 VlanId vlanId = e.getKey();
176 ConnectPoint cp = e.getValue();
177 Set<Host> connectedHosts = hostService.getConnectedHosts(cp);
178 if (!connectedHosts.isEmpty()) {
179 connectedHosts.forEach(host -> {
180 if (host.vlan().equals(vlanId)) {
181 confHostPresentCPoint.put(vlanId, new Pair<>(cp, host.mac()));
182 } else {
183 confHostPresentCPoint.put(vlanId, new Pair<>(cp, null));
184 }
185 });
186 } else {
187 confHostPresentCPoint.put(vlanId, new Pair<>(cp, null));
188 }
189 }
190
191 /**
192 * Listener for host events.
193 */
194 class InternalHostListener implements HostListener {
195 @Override
196 public void event(HostEvent event) {
197 log.debug("Received HostEvent {}", event);
198 switch (event.type()) {
199 case HOST_ADDED:
200 case HOST_UPDATED:
201 case HOST_REMOVED:
202 setupConnectivity();
203 break;
204 default:
205 break;
206 }
207 }
208 }
Luca Pretea8854822016-04-26 16:30:55 -0700209
210 /**
211 * Listener for interface configuration events.
212 */
213 private class InternalInterfaceListener implements InterfaceListener {
214 @Override
215 public void event(InterfaceEvent event) {
216 log.debug("Received InterfaceConfigEvent {}", event);
217 switch (event.type()) {
218 case INTERFACE_ADDED:
219 case INTERFACE_UPDATED:
220 case INTERFACE_REMOVED:
221 setupConnectivity();
222 break;
223 default:
224 break;
225 }
226 }
227 }
Luca Prete9c2ee072016-02-16 11:00:44 -0800228}