blob: 817c49e29778d6eef9591ad317493099c93fc99d [file] [log] [blame]
Yi Tseng28767f02016-09-13 04:27:20 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
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 */
16
17package org.onosproject.vpls;
18
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070019import com.google.common.collect.SetMultimap;
Yi Tseng28767f02016-09-13 04:27:20 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
27import org.onosproject.incubator.net.intf.Interface;
28import org.onosproject.incubator.net.intf.InterfaceEvent;
29import org.onosproject.incubator.net.intf.InterfaceListener;
30import org.onosproject.incubator.net.intf.InterfaceService;
31import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
32import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
33import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
34import org.onosproject.net.Host;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070035import org.onosproject.net.config.NetworkConfigEvent;
36import org.onosproject.net.config.NetworkConfigListener;
37import org.onosproject.net.config.NetworkConfigService;
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010038import org.onosproject.net.device.DeviceService;
Yi Tseng28767f02016-09-13 04:27:20 -070039import org.onosproject.net.host.HostService;
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010040import org.onosproject.vpls.config.VplsConfigService;
Yi Tseng28767f02016-09-13 04:27:20 -070041import org.slf4j.Logger;
42
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070043import java.util.Set;
Yi Tseng28767f02016-09-13 04:27:20 -070044
45import static org.slf4j.LoggerFactory.getLogger;
46
47/**
Luca Prete092e8952016-10-26 16:25:56 +020048 * Handles neighbour messages for on behalf of the VPLS application. Handlers
49 * will be changed automatically by interface or network configuration events.
Yi Tseng28767f02016-09-13 04:27:20 -070050 */
51@Component(immediate = true)
52public class VplsNeighbourHandler {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070053 private static final String UNKNOWN_CONTEXT = "Unknown context type: {}";
54
Luca Prete092e8952016-10-26 16:25:56 +020055 private static final String CAN_NOT_FIND_VPLS =
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070056 "Cannot find VPLS for port {} with VLAN Id {}.";
Yi Tseng28767f02016-09-13 04:27:20 -070057
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 protected CoreService coreService;
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010062 protected DeviceService deviceService;
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Yi Tseng28767f02016-09-13 04:27:20 -070065 protected InterfaceService interfaceService;
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected NeighbourResolutionService neighbourService;
69
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070070 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010071 protected VplsConfigService vplsConfigService;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070072
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected NetworkConfigService configService;
75
Luca Prete092e8952016-10-26 16:25:56 +020076 private VplsInterfaceListener interfaceListener =
77 new VplsInterfaceListener();
Yi Tseng28767f02016-09-13 04:27:20 -070078
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070079 protected VplsNeighbourMessageHandler neighbourHandler =
Yi Tseng28767f02016-09-13 04:27:20 -070080 new VplsNeighbourMessageHandler();
81
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070082 protected VplsConfigListener configListener =
83 new VplsConfigListener();
Yi Tseng28767f02016-09-13 04:27:20 -070084
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070085 private final Logger log = getLogger(getClass());
Yi Tseng28767f02016-09-13 04:27:20 -070086
87 private ApplicationId appId;
88
89
90 @Activate
91 protected void activate() {
92 appId = coreService.registerApplication(Vpls.VPLS_APP);
93 interfaceService.addListener(interfaceListener);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070094 configService.addListener(configListener);
95 configNeighbourHandler();
Yi Tseng28767f02016-09-13 04:27:20 -070096 }
97
98 @Deactivate
99 protected void deactivate() {
100 interfaceService.removeListener(interfaceListener);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700101 configService.removeListener(configListener);
102 neighbourService.unregisterNeighbourHandlers(appId);
Yi Tseng28767f02016-09-13 04:27:20 -0700103 }
104
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700105 private void configNeighbourHandler() {
106 neighbourService.unregisterNeighbourHandlers(appId);
Luca Prete092e8952016-10-26 16:25:56 +0200107 Set<Interface> interfaces = vplsConfigService.allIfaces();
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700108
109 interfaceService.getInterfaces()
110 .stream()
111 .filter(interfaces::contains)
112 .forEach(intf -> {
113 neighbourService.registerNeighbourHandler(intf,
114 neighbourHandler,
115 appId);
116 });
Yi Tseng28767f02016-09-13 04:27:20 -0700117 }
118
119 /**
120 * Handler for neighbour messages.
121 */
122 private class VplsNeighbourMessageHandler implements NeighbourMessageHandler {
123
124 @Override
125 public void handleMessage(NeighbourMessageContext context,
126 HostService hostService) {
127
128 switch (context.type()) {
129 case REQUEST:
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700130 handleRequest(context);
Yi Tseng28767f02016-09-13 04:27:20 -0700131 break;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700132
Yi Tseng28767f02016-09-13 04:27:20 -0700133 case REPLY:
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700134 handleReply(context, hostService);
Yi Tseng28767f02016-09-13 04:27:20 -0700135 break;
136
137 default:
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700138 log.warn(UNKNOWN_CONTEXT, context.type());
Yi Tseng28767f02016-09-13 04:27:20 -0700139 break;
140 }
141 }
142 }
143
144 /**
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700145 * Handles request messages.
146 *
147 * @param context the message context
148 */
149 protected void handleRequest(NeighbourMessageContext context) {
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100150 SetMultimap<String, Interface> interfaces =
Luca Prete092e8952016-10-26 16:25:56 +0200151 vplsConfigService.ifacesByVplsName(context.vlan(),
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100152 context.inPort());
153 if (interfaces != null) {
154 interfaces.values().stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700155 .filter(intf -> !context.inPort().equals(intf.connectPoint()))
156 .forEach(context::forward);
157
158 } else {
Luca Prete092e8952016-10-26 16:25:56 +0200159 log.debug(CAN_NOT_FIND_VPLS, context.inPort(), context.vlan());
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700160 }
161 }
162
163 /**
164 * Handles reply messages between VLAN tagged interfaces.
165 *
166 * @param context the message context
167 * @param hostService the host service
168 */
169 protected void handleReply(NeighbourMessageContext context,
170 HostService hostService) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700171 Set<Host> hosts = hostService.getHostsByMac(context.dstMac());
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100172 SetMultimap<String, Interface> interfaces =
173 vplsConfigService.ifacesByVplsName(context.vlan(),
174 context.inPort());
175 if (interfaces != null) {
176 hosts.forEach(host -> interfaces.values().stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700177 .filter(intf -> intf.connectPoint().equals(host.location()))
178 .filter(intf -> intf.vlan().equals(host.vlan()))
179 .forEach(context::forward));
180 } else {
Luca Prete092e8952016-10-26 16:25:56 +0200181 log.debug(CAN_NOT_FIND_VPLS, context.inPort(), context.vlan());
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700182 }
183 }
184
185 /**
Yi Tseng28767f02016-09-13 04:27:20 -0700186 * Listener for interface configuration events.
187 */
188 private class VplsInterfaceListener implements InterfaceListener {
189
190 @Override
191 public void event(InterfaceEvent event) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700192 configNeighbourHandler();
193 }
194 }
195
196 /**
197 * Listener for network configuration events.
198 */
199 private class VplsConfigListener implements NetworkConfigListener {
200
201 @Override
202 public void event(NetworkConfigEvent event) {
203 configNeighbourHandler();
Yi Tseng28767f02016-09-13 04:27:20 -0700204 }
205 }
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100206}