blob: de4365fde01a5100c27f026b2be7b734ccb37ac5 [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 */
Yi Tseng28767f02016-09-13 04:27:20 -070016package org.onosproject.vpls;
17
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070018import com.google.common.collect.SetMultimap;
Yi Tseng28767f02016-09-13 04:27:20 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.onosproject.core.ApplicationId;
25import org.onosproject.core.CoreService;
26import org.onosproject.incubator.net.intf.Interface;
27import org.onosproject.incubator.net.intf.InterfaceEvent;
28import org.onosproject.incubator.net.intf.InterfaceListener;
29import org.onosproject.incubator.net.intf.InterfaceService;
30import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
31import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
32import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
33import org.onosproject.net.Host;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070034import org.onosproject.net.config.NetworkConfigEvent;
35import org.onosproject.net.config.NetworkConfigListener;
36import org.onosproject.net.config.NetworkConfigService;
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010037import org.onosproject.net.device.DeviceService;
Yi Tseng28767f02016-09-13 04:27:20 -070038import org.onosproject.net.host.HostService;
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010039import org.onosproject.vpls.config.VplsConfigService;
Yi Tseng28767f02016-09-13 04:27:20 -070040import org.slf4j.Logger;
41
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070042import java.util.Set;
Yi Tseng28767f02016-09-13 04:27:20 -070043
44import static org.slf4j.LoggerFactory.getLogger;
45
46/**
Luca Prete092e8952016-10-26 16:25:56 +020047 * Handles neighbour messages for on behalf of the VPLS application. Handlers
48 * will be changed automatically by interface or network configuration events.
Yi Tseng28767f02016-09-13 04:27:20 -070049 */
50@Component(immediate = true)
51public class VplsNeighbourHandler {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070052 private static final String UNKNOWN_CONTEXT = "Unknown context type: {}";
53
Luca Prete092e8952016-10-26 16:25:56 +020054 private static final String CAN_NOT_FIND_VPLS =
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070055 "Cannot find VPLS for port {} with VLAN Id {}.";
Yi Tseng28767f02016-09-13 04:27:20 -070056
57 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 protected CoreService coreService;
59
60 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010061 protected DeviceService deviceService;
62
63 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Yi Tseng28767f02016-09-13 04:27:20 -070064 protected InterfaceService interfaceService;
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected NeighbourResolutionService neighbourService;
68
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070069 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010070 protected VplsConfigService vplsConfigService;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070071
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected NetworkConfigService configService;
74
Luca Prete092e8952016-10-26 16:25:56 +020075 private VplsInterfaceListener interfaceListener =
76 new VplsInterfaceListener();
Yi Tseng28767f02016-09-13 04:27:20 -070077
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070078 protected VplsNeighbourMessageHandler neighbourHandler =
Yi Tseng28767f02016-09-13 04:27:20 -070079 new VplsNeighbourMessageHandler();
80
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070081 protected VplsConfigListener configListener =
82 new VplsConfigListener();
Yi Tseng28767f02016-09-13 04:27:20 -070083
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070084 private final Logger log = getLogger(getClass());
Yi Tseng28767f02016-09-13 04:27:20 -070085
86 private ApplicationId appId;
87
88
89 @Activate
90 protected void activate() {
91 appId = coreService.registerApplication(Vpls.VPLS_APP);
92 interfaceService.addListener(interfaceListener);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070093 configService.addListener(configListener);
94 configNeighbourHandler();
Yi Tseng28767f02016-09-13 04:27:20 -070095 }
96
97 @Deactivate
98 protected void deactivate() {
99 interfaceService.removeListener(interfaceListener);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700100 configService.removeListener(configListener);
101 neighbourService.unregisterNeighbourHandlers(appId);
Yi Tseng28767f02016-09-13 04:27:20 -0700102 }
103
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700104 private void configNeighbourHandler() {
105 neighbourService.unregisterNeighbourHandlers(appId);
Luca Prete092e8952016-10-26 16:25:56 +0200106 Set<Interface> interfaces = vplsConfigService.allIfaces();
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700107
108 interfaceService.getInterfaces()
109 .stream()
110 .filter(interfaces::contains)
111 .forEach(intf -> {
112 neighbourService.registerNeighbourHandler(intf,
113 neighbourHandler,
114 appId);
115 });
Yi Tseng28767f02016-09-13 04:27:20 -0700116 }
117
118 /**
119 * Handler for neighbour messages.
120 */
121 private class VplsNeighbourMessageHandler implements NeighbourMessageHandler {
122
123 @Override
124 public void handleMessage(NeighbourMessageContext context,
125 HostService hostService) {
126
127 switch (context.type()) {
128 case REQUEST:
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700129 handleRequest(context);
Yi Tseng28767f02016-09-13 04:27:20 -0700130 break;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700131
Yi Tseng28767f02016-09-13 04:27:20 -0700132 case REPLY:
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700133 handleReply(context, hostService);
Yi Tseng28767f02016-09-13 04:27:20 -0700134 break;
135
136 default:
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700137 log.warn(UNKNOWN_CONTEXT, context.type());
Yi Tseng28767f02016-09-13 04:27:20 -0700138 break;
139 }
140 }
141 }
142
143 /**
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700144 * Handles request messages.
145 *
146 * @param context the message context
147 */
148 protected void handleRequest(NeighbourMessageContext context) {
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100149 SetMultimap<String, Interface> interfaces =
Luca Prete092e8952016-10-26 16:25:56 +0200150 vplsConfigService.ifacesByVplsName(context.vlan(),
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100151 context.inPort());
152 if (interfaces != null) {
153 interfaces.values().stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700154 .filter(intf -> !context.inPort().equals(intf.connectPoint()))
155 .forEach(context::forward);
156
157 } else {
Luca Prete092e8952016-10-26 16:25:56 +0200158 log.debug(CAN_NOT_FIND_VPLS, context.inPort(), context.vlan());
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700159 }
160 }
161
162 /**
163 * Handles reply messages between VLAN tagged interfaces.
164 *
165 * @param context the message context
166 * @param hostService the host service
167 */
168 protected void handleReply(NeighbourMessageContext context,
169 HostService hostService) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700170 Set<Host> hosts = hostService.getHostsByMac(context.dstMac());
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100171 SetMultimap<String, Interface> interfaces =
172 vplsConfigService.ifacesByVplsName(context.vlan(),
173 context.inPort());
174 if (interfaces != null) {
175 hosts.forEach(host -> interfaces.values().stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700176 .filter(intf -> intf.connectPoint().equals(host.location()))
177 .filter(intf -> intf.vlan().equals(host.vlan()))
178 .forEach(context::forward));
179 } else {
Luca Prete092e8952016-10-26 16:25:56 +0200180 log.debug(CAN_NOT_FIND_VPLS, context.inPort(), context.vlan());
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700181 }
182 }
183
184 /**
Yi Tseng28767f02016-09-13 04:27:20 -0700185 * Listener for interface configuration events.
186 */
187 private class VplsInterfaceListener implements InterfaceListener {
188
189 @Override
190 public void event(InterfaceEvent event) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700191 configNeighbourHandler();
192 }
193 }
194
195 /**
196 * Listener for network configuration events.
197 */
198 private class VplsConfigListener implements NetworkConfigListener {
199
200 @Override
201 public void event(NetworkConfigEvent event) {
202 configNeighbourHandler();
Yi Tseng28767f02016-09-13 04:27:20 -0700203 }
204 }
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100205}