blob: 4f1e3facee118bad40277ae0b8cf8a0cabdd3ef3 [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;
41import org.onosproject.routing.IntentSynchronizationAdminService;
42import org.onosproject.routing.IntentSynchronizationService;
43import org.slf4j.Logger;
44
45import java.util.Map;
46import java.util.Set;
47
48import static org.slf4j.LoggerFactory.getLogger;
49
50/**
51 * Application to create L2 broadcast overlay networks using VLAN.
52 */
53@Component(immediate = true)
54public class Vpls {
55 private static final String VPLS_APP = "org.onosproject.vpls";
56 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
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected IntentSynchronizationAdminService intentSynchronizerAdmin;
78
79 private final HostListener hostListener = new InternalHostListener();
80
Luca Pretea8854822016-04-26 16:30:55 -070081 private final InternalInterfaceListener interfaceListener
82 = new InternalInterfaceListener();
83
Luca Prete9c2ee072016-02-16 11:00:44 -080084 private IntentInstaller intentInstaller;
85
86 private ApplicationId appId;
87
88 @Activate
89 public void activate() {
90 appId = coreService.registerApplication(VPLS_APP);
91
92 intentInstaller = new IntentInstaller(appId,
93 intentService,
94 intentSynchronizer);
95
Luca Prete2705d662016-04-29 15:30:23 -070096 applicationService.registerDeactivateHook(appId, () -> {
97 intentSynchronizer.removeIntentsByAppId(appId);
98 });
Luca Prete9c2ee072016-02-16 11:00:44 -080099
100 hostService.addListener(hostListener);
Luca Pretea8854822016-04-26 16:30:55 -0700101 interfaceService.addListener(interfaceListener);
Luca Prete9c2ee072016-02-16 11:00:44 -0800102
103 setupConnectivity();
104
105 log.info("Started");
106 }
107
108 @Deactivate
109 public void deactivate() {
110 log.info("Stopped");
111 }
112
113 protected void setupConnectivity() {
114 /*
115 * Parse Configuration and get Connect Point by VlanId.
116 */
117 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan = getConfigCPoints();
118
119 /*
120 * Check that configured Connect Points have hosts attached and
121 * associate their Mac Address to the Connect Points configured.
122 */
123 SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
124 pairAvailableHosts(confCPointsByVlan);
125
126 /*
127 * Create and submit intents between the Connect Points.
128 * Intents for broadcast between all the configured Connect Points.
129 * Intents for unicast between all the configured Connect Points with
130 * hosts attached.
131 */
132 intentInstaller.installIntents(confHostPresentCPoint);
133 }
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())
Luca Prete9c2ee072016-02-16 11:00:44 -0800149 .forEach(intf -> confCPointsByVlan.put(intf.vlan(),
150 intf.connectPoint()));
151 return confCPointsByVlan;
152 }
153
154 /**
155 * Checks if for any ConnectPoint configured there's an host present
156 * and in case it associate them together.
157 *
158 * @param confCPointsByVlan the configured ConnectPoints grouped by vlan id
159 * @return the configured ConnectPoints with eventual hosts associated.
160 */
161 protected SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> pairAvailableHosts(
162 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan) {
163 log.debug("Binding connected hosts mac addresses");
164
165 SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
166 HashMultimap.create();
167
168 confCPointsByVlan.entries()
169 .forEach(e -> bindMacAddr(e, confHostPresentCPoint));
170
171 return confHostPresentCPoint;
172 }
173
174 private void bindMacAddr(Map.Entry<VlanId, ConnectPoint> e,
175 SetMultimap<VlanId, Pair<ConnectPoint,
176 MacAddress>> confHostPresentCPoint) {
177 VlanId vlanId = e.getKey();
178 ConnectPoint cp = e.getValue();
179 Set<Host> connectedHosts = hostService.getConnectedHosts(cp);
180 if (!connectedHosts.isEmpty()) {
181 connectedHosts.forEach(host -> {
182 if (host.vlan().equals(vlanId)) {
Yuta HIGUCHI32e83312016-07-10 00:28:37 -0700183 confHostPresentCPoint.put(vlanId, Pair.of(cp, host.mac()));
Luca Prete9c2ee072016-02-16 11:00:44 -0800184 } else {
Yuta HIGUCHI32e83312016-07-10 00:28:37 -0700185 confHostPresentCPoint.put(vlanId, Pair.of(cp, null));
Luca Prete9c2ee072016-02-16 11:00:44 -0800186 }
187 });
188 } else {
Yuta HIGUCHI32e83312016-07-10 00:28:37 -0700189 confHostPresentCPoint.put(vlanId, Pair.of(cp, null));
Luca Prete9c2ee072016-02-16 11:00:44 -0800190 }
191 }
192
193 /**
194 * Listener for host events.
195 */
196 class InternalHostListener implements HostListener {
197 @Override
198 public void event(HostEvent event) {
199 log.debug("Received HostEvent {}", event);
200 switch (event.type()) {
201 case HOST_ADDED:
202 case HOST_UPDATED:
203 case HOST_REMOVED:
204 setupConnectivity();
205 break;
206 default:
207 break;
208 }
209 }
210 }
Luca Pretea8854822016-04-26 16:30:55 -0700211
212 /**
213 * Listener for interface configuration events.
214 */
215 private class InternalInterfaceListener implements InterfaceListener {
216 @Override
217 public void event(InterfaceEvent event) {
218 log.debug("Received InterfaceConfigEvent {}", event);
219 switch (event.type()) {
220 case INTERFACE_ADDED:
221 case INTERFACE_UPDATED:
222 case INTERFACE_REMOVED:
223 setupConnectivity();
224 break;
225 default:
226 break;
227 }
228 }
229 }
Luca Prete9c2ee072016-02-16 11:00:44 -0800230}