blob: 2951d13e3dfaab52d01f51d13f80b99029411706 [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;
Yuta HIGUCHI32e83312016-07-10 00:28:37 -070020
21import org.apache.commons.lang3.tuple.Pair;
Luca Prete9c2ee072016-02-16 11:00:44 -080022import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
24import org.apache.felix.scr.annotations.Deactivate;
25import org.apache.felix.scr.annotations.Reference;
26import org.apache.felix.scr.annotations.ReferenceCardinality;
27import org.onlab.packet.MacAddress;
28import org.onlab.packet.VlanId;
29import org.onosproject.app.ApplicationService;
30import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
Luca Pretea8854822016-04-26 16:30:55 -070032import org.onosproject.incubator.net.intf.InterfaceEvent;
33import org.onosproject.incubator.net.intf.InterfaceListener;
Luca Prete9c2ee072016-02-16 11:00:44 -080034import org.onosproject.incubator.net.intf.InterfaceService;
35import org.onosproject.net.ConnectPoint;
36import org.onosproject.net.Host;
37import org.onosproject.net.host.HostEvent;
38import org.onosproject.net.host.HostListener;
39import org.onosproject.net.host.HostService;
40import org.onosproject.net.intent.IntentService;
Luca Prete9c2ee072016-02-16 11:00:44 -080041import 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 {
Yi Tseng28767f02016-09-13 04:27:20 -070054 protected static final String VPLS_APP = "org.onosproject.vpls";
55
Luca Prete9c2ee072016-02-16 11:00:44 -080056 private final Logger log = getLogger(getClass());
57
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 protected ApplicationService applicationService;
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
62 protected CoreService coreService;
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected HostService hostService;
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected IntentService intentService;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected InterfaceService interfaceService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected IntentSynchronizationService intentSynchronizer;
75
Luca Prete9c2ee072016-02-16 11:00:44 -080076 private final HostListener hostListener = new InternalHostListener();
77
Luca Pretea8854822016-04-26 16:30:55 -070078 private final InternalInterfaceListener interfaceListener
79 = new InternalInterfaceListener();
80
Luca Prete9c2ee072016-02-16 11:00:44 -080081 private IntentInstaller intentInstaller;
82
83 private ApplicationId appId;
84
Yi Tseng28767f02016-09-13 04:27:20 -070085
Luca Prete9c2ee072016-02-16 11:00:44 -080086 @Activate
87 public void activate() {
88 appId = coreService.registerApplication(VPLS_APP);
89
90 intentInstaller = new IntentInstaller(appId,
91 intentService,
92 intentSynchronizer);
93
Luca Prete2705d662016-04-29 15:30:23 -070094 applicationService.registerDeactivateHook(appId, () -> {
95 intentSynchronizer.removeIntentsByAppId(appId);
96 });
Luca Prete9c2ee072016-02-16 11:00:44 -080097
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
Luca Pretec21c6e62016-09-22 14:52:21 -0700103 log.info("Activated");
Luca Prete9c2ee072016-02-16 11:00:44 -0800104 }
105
106 @Deactivate
107 public void deactivate() {
Yi Tseng28767f02016-09-13 04:27:20 -0700108 intentSynchronizer.removeIntentsByAppId(appId);
Luca Pretec21c6e62016-09-22 14:52:21 -0700109 log.info("Deactivated");
Luca Prete9c2ee072016-02-16 11:00:44 -0800110 }
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);
Yi Tseng28767f02016-09-13 04:27:20 -0700132
Luca Prete9c2ee072016-02-16 11:00:44 -0800133 }
134
135 /**
136 * Computes the list of configured interfaces with a VLAN Id.
137 *
138 * @return the interfaces grouped by vlan id
139 */
140 protected SetMultimap<VlanId, ConnectPoint> getConfigCPoints() {
141 log.debug("Checking interface configuration");
142
143 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan =
144 HashMultimap.create();
145
146 interfaceService.getInterfaces()
Luca Preteb21d1712016-02-19 11:17:24 -0800147 .stream()
148 .filter(intf -> intf.ipAddressesList().isEmpty())
Yi Tseng28767f02016-09-13 04:27:20 -0700149 .forEach(intf -> confCPointsByVlan.put(intf.vlan(), intf.connectPoint()));
Luca Prete9c2ee072016-02-16 11:00:44 -0800150 return confCPointsByVlan;
151 }
152
153 /**
Yi Tseng28767f02016-09-13 04:27:20 -0700154 * Checks if for any ConnectPoint configured there's an host presents
155 * and in case it associates them together.
Luca Prete9c2ee072016-02-16 11:00:44 -0800156 *
Yi Tseng28767f02016-09-13 04:27:20 -0700157 * @param confCPointsByVlan the configured ConnectPoints grouped by VLAN Id
Luca Prete9c2ee072016-02-16 11:00:44 -0800158 * @return the configured ConnectPoints with eventual hosts associated.
159 */
160 protected SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> pairAvailableHosts(
161 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan) {
Yi Tseng28767f02016-09-13 04:27:20 -0700162 log.debug("Binding connected hosts MAC addresses");
Luca Prete9c2ee072016-02-16 11:00:44 -0800163
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
Yi Tseng28767f02016-09-13 04:27:20 -0700173 // Bind VLAN Id with hosts and connect points
Luca Prete9c2ee072016-02-16 11:00:44 -0800174 private void bindMacAddr(Map.Entry<VlanId, ConnectPoint> e,
175 SetMultimap<VlanId, Pair<ConnectPoint,
Yi Tseng28767f02016-09-13 04:27:20 -0700176 MacAddress>> confHostPresentCPoint) {
Luca Prete9c2ee072016-02-16 11:00:44 -0800177 VlanId vlanId = e.getKey();
178 ConnectPoint cp = e.getValue();
179 Set<Host> connectedHosts = hostService.getConnectedHosts(cp);
Yi Tsengbf8b67e2016-09-01 15:02:11 +0800180 connectedHosts.forEach(host -> {
181 if (host.vlan().equals(vlanId)) {
182 confHostPresentCPoint.put(vlanId, Pair.of(cp, host.mac()));
183 } else {
184 confHostPresentCPoint.put(vlanId, Pair.of(cp, null));
185 }
186 });
187 if (connectedHosts.isEmpty()) {
Yuta HIGUCHI32e83312016-07-10 00:28:37 -0700188 confHostPresentCPoint.put(vlanId, Pair.of(cp, null));
Luca Prete9c2ee072016-02-16 11:00:44 -0800189 }
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}