blob: ebf0750c0a6635bf6427f2b8f9d42f8aa0c2dae6 [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;
31import org.onosproject.incubator.net.intf.InterfaceService;
32import org.onosproject.net.ConnectPoint;
33import org.onosproject.net.Host;
34import org.onosproject.net.host.HostEvent;
35import org.onosproject.net.host.HostListener;
36import org.onosproject.net.host.HostService;
37import org.onosproject.net.intent.IntentService;
38import org.onosproject.routing.IntentSynchronizationAdminService;
39import org.onosproject.routing.IntentSynchronizationService;
40import org.slf4j.Logger;
41
42import java.util.Map;
43import java.util.Set;
44
45import static org.slf4j.LoggerFactory.getLogger;
46
47/**
48 * Application to create L2 broadcast overlay networks using VLAN.
49 */
50@Component(immediate = true)
51public class Vpls {
52 private static final String VPLS_APP = "org.onosproject.vpls";
53 private final Logger log = getLogger(getClass());
54
55 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 protected ApplicationService applicationService;
57
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 protected CoreService coreService;
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
62 protected HostService hostService;
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected IntentService intentService;
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected InterfaceService interfaceService;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected IntentSynchronizationService intentSynchronizer;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected IntentSynchronizationAdminService intentSynchronizerAdmin;
75
76 private final HostListener hostListener = new InternalHostListener();
77
78 private IntentInstaller intentInstaller;
79
80 private ApplicationId appId;
81
82 @Activate
83 public void activate() {
84 appId = coreService.registerApplication(VPLS_APP);
85
86 intentInstaller = new IntentInstaller(appId,
87 intentService,
88 intentSynchronizer);
89
90 applicationService.registerDeactivateHook(appId,
91 intentSynchronizerAdmin::removeIntents);
92
93 hostService.addListener(hostListener);
94
95 setupConnectivity();
96
97 log.info("Started");
98 }
99
100 @Deactivate
101 public void deactivate() {
102 log.info("Stopped");
103 }
104
105 protected void setupConnectivity() {
106 /*
107 * Parse Configuration and get Connect Point by VlanId.
108 */
109 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan = getConfigCPoints();
110
111 /*
112 * Check that configured Connect Points have hosts attached and
113 * associate their Mac Address to the Connect Points configured.
114 */
115 SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
116 pairAvailableHosts(confCPointsByVlan);
117
118 /*
119 * Create and submit intents between the Connect Points.
120 * Intents for broadcast between all the configured Connect Points.
121 * Intents for unicast between all the configured Connect Points with
122 * hosts attached.
123 */
124 intentInstaller.installIntents(confHostPresentCPoint);
125 }
126
127 /**
128 * Computes the list of configured interfaces with a VLAN Id.
129 *
130 * @return the interfaces grouped by vlan id
131 */
132 protected SetMultimap<VlanId, ConnectPoint> getConfigCPoints() {
133 log.debug("Checking interface configuration");
134
135 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan =
136 HashMultimap.create();
137
138 interfaceService.getInterfaces()
Luca Preteb21d1712016-02-19 11:17:24 -0800139 .stream()
140 .filter(intf -> intf.ipAddressesList().isEmpty())
Luca Prete9c2ee072016-02-16 11:00:44 -0800141 .forEach(intf -> confCPointsByVlan.put(intf.vlan(),
142 intf.connectPoint()));
143 return confCPointsByVlan;
144 }
145
146 /**
147 * Checks if for any ConnectPoint configured there's an host present
148 * and in case it associate them together.
149 *
150 * @param confCPointsByVlan the configured ConnectPoints grouped by vlan id
151 * @return the configured ConnectPoints with eventual hosts associated.
152 */
153 protected SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> pairAvailableHosts(
154 SetMultimap<VlanId, ConnectPoint> confCPointsByVlan) {
155 log.debug("Binding connected hosts mac addresses");
156
157 SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
158 HashMultimap.create();
159
160 confCPointsByVlan.entries()
161 .forEach(e -> bindMacAddr(e, confHostPresentCPoint));
162
163 return confHostPresentCPoint;
164 }
165
166 private void bindMacAddr(Map.Entry<VlanId, ConnectPoint> e,
167 SetMultimap<VlanId, Pair<ConnectPoint,
168 MacAddress>> confHostPresentCPoint) {
169 VlanId vlanId = e.getKey();
170 ConnectPoint cp = e.getValue();
171 Set<Host> connectedHosts = hostService.getConnectedHosts(cp);
172 if (!connectedHosts.isEmpty()) {
173 connectedHosts.forEach(host -> {
174 if (host.vlan().equals(vlanId)) {
175 confHostPresentCPoint.put(vlanId, new Pair<>(cp, host.mac()));
176 } else {
177 confHostPresentCPoint.put(vlanId, new Pair<>(cp, null));
178 }
179 });
180 } else {
181 confHostPresentCPoint.put(vlanId, new Pair<>(cp, null));
182 }
183 }
184
185 /**
186 * Listener for host events.
187 */
188 class InternalHostListener implements HostListener {
189 @Override
190 public void event(HostEvent event) {
191 log.debug("Received HostEvent {}", event);
192 switch (event.type()) {
193 case HOST_ADDED:
194 case HOST_UPDATED:
195 case HOST_REMOVED:
196 setupConnectivity();
197 break;
198 default:
199 break;
200 }
201 }
202 }
203}