blob: 5d7c8b0c7e0e6a1597741aa7e349701be1f1e80d [file] [log] [blame]
Lee Yongjae7c27bb42017-11-17 12:00:45 +09001/*
Jian Li8df54a92018-08-23 17:01:31 +09002 * Copyright 2018-present Open Networking Foundation
Lee Yongjae7c27bb42017-11-17 12:00:45 +09003 *
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 */
Jian Li8df54a92018-08-23 17:01:31 +090016package org.onosproject.simplefabric.impl;
Lee Yongjae7c27bb42017-11-17 12:00:45 +090017
Ray Milkeyd84f89b2018-08-17 14:54:17 -070018import org.osgi.service.component.annotations.Activate;
19import org.osgi.service.component.annotations.Component;
20import org.osgi.service.component.annotations.Deactivate;
21import org.osgi.service.component.annotations.Reference;
22import org.osgi.service.component.annotations.ReferenceCardinality;
Lee Yongjae7c27bb42017-11-17 12:00:45 +090023import org.onlab.packet.MacAddress;
24import org.onosproject.core.ApplicationId;
25import org.onosproject.core.CoreService;
26import org.onosproject.net.intf.Interface;
27import org.onosproject.net.intf.InterfaceService;
28import org.onosproject.net.neighbour.NeighbourMessageContext;
29import org.onosproject.net.neighbour.NeighbourMessageHandler;
30import org.onosproject.net.neighbour.NeighbourResolutionService;
31import org.onosproject.net.Host;
32import org.onosproject.net.host.HostService;
Jian Lie2d87512018-08-23 17:33:05 +090033import org.onosproject.simplefabric.api.FabricNetwork;
Jian Lic7efc1d2018-08-23 16:37:34 +090034import org.onosproject.simplefabric.api.SimpleFabricEvent;
35import org.onosproject.simplefabric.api.SimpleFabricListener;
36import org.onosproject.simplefabric.api.SimpleFabricService;
Lee Yongjae7c27bb42017-11-17 12:00:45 +090037import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import java.util.HashSet;
41import java.util.Objects;
42import java.util.Set;
43
44
45/**
46 * Handles neighbour messages for on behalf of the L2 Network application. Handlers
47 * will be changed automatically by interface or network configuration events.
48 */
49@Component(immediate = true, enabled = false)
50public class SimpleFabricNeighbour {
51
52 private final Logger log = LoggerFactory.getLogger(getClass());
53 protected ApplicationId appId;
54
Ray Milkeyd84f89b2018-08-17 14:54:17 -070055 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090056 protected CoreService coreService;
57
Ray Milkeyd84f89b2018-08-17 14:54:17 -070058 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090059 protected HostService hostService;
60
Ray Milkeyd84f89b2018-08-17 14:54:17 -070061 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090062 protected InterfaceService interfaceService;
63
Ray Milkeyd84f89b2018-08-17 14:54:17 -070064 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090065 protected NeighbourResolutionService neighbourService;
66
Ray Milkeyd84f89b2018-08-17 14:54:17 -070067 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090068 protected SimpleFabricService simpleFabric;
69
70 private final InternalSimpleFabricListener simpleFabricListener =
71 new InternalSimpleFabricListener();
72
73 private L2NetworkNeighbourMessageHandler neighbourHandler =
74 new L2NetworkNeighbourMessageHandler();
75
76 private Set<Interface> monitoredInterfaces = new HashSet<>();
77
78 @Activate
79 public void activate() {
Jian Lie2d87512018-08-23 17:33:05 +090080 appId = simpleFabric.appId();
Lee Yongjae7c27bb42017-11-17 12:00:45 +090081 simpleFabric.addListener(simpleFabricListener);
82 refresh();
83 log.info("simple fabric neighbour started");
84 }
85
86 @Deactivate
87 public void deactivate() {
88 simpleFabric.removeListener(simpleFabricListener);
89 unregister();
90 monitoredInterfaces.clear();
91 log.info("simple fabric neighbour stoped");
92 }
93
94 /**
95 * Registers neighbour handler to all available interfaces.
96 */
97 protected void refresh() {
98 Set<Interface> interfaces = interfaceService.getInterfaces();
99 // check for new interfaces
100 for (Interface intf : interfaces) {
Jian Lie2d87512018-08-23 17:33:05 +0900101 if (!monitoredInterfaces.contains(intf) && simpleFabric.isFabricNetworkInterface(intf)) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900102 log.info("simple fabric neighbour register handler: {}", intf);
103 neighbourService.registerNeighbourHandler(intf, neighbourHandler, appId);
104 monitoredInterfaces.add(intf);
105 } else {
106 log.debug("simple fabric neighobur unknown interface: {}", intf);
107 }
108 }
109 // check for removed interfaces
110 Set<Interface> monitoredInterfacesToBeRemoved = new HashSet<>();
111 for (Interface intf : monitoredInterfaces) {
112 if (!interfaces.contains(intf)) {
113 log.info("simple fabric neighbour unregister handler: {}", intf);
114 neighbourService.unregisterNeighbourHandler(intf, neighbourHandler, appId);
115 monitoredInterfacesToBeRemoved.add(intf);
116 }
117 }
118 for (Interface intf : monitoredInterfacesToBeRemoved) {
119 monitoredInterfaces.remove(intf);
120 }
121 }
122
123 /**
124 * Unregisters neighbour handler to all available interfaces.
125 */
126 protected void unregister() {
127 log.info("simple fabric neighbour unregister handler");
128 neighbourService.unregisterNeighbourHandlers(appId);
129 }
130
131 /**
132 * Handles request messages.
133 *
134 * @param context the message context
135 */
136 protected void handleRequest(NeighbourMessageContext context) {
Jian Lie2d87512018-08-23 17:33:05 +0900137 MacAddress mac = simpleFabric.vMacForIp(context.target());
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900138 if (mac != null) {
139 log.trace("simple fabric neightbour request on virtualGatewayAddress {}; response to {} {} mac={}",
140 context.target(), context.inPort(), context.vlan(), mac);
141 context.reply(mac);
142 return;
143 }
144 // else forward to corresponding host
145
Jian Lie2d87512018-08-23 17:33:05 +0900146 FabricNetwork fabricNetwork = simpleFabric.fabricNetwork(context.inPort(), context.vlan());
147 if (fabricNetwork != null) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900148 int numForwards = 0;
149 if (!context.dstMac().isBroadcast() && !context.dstMac().isMulticast()) {
150 for (Host host : hostService.getHostsByMac(context.dstMac())) {
151 log.trace("simple fabric neightbour request forward unicast to {}", host.location());
152 context.forward(host.location()); // ASSUME: vlan is same
153 // TODO: may need to check host.location().time()
154 numForwards++;
155 }
156 if (numForwards > 0) {
157 return;
158 }
159 }
160 // else do broadcast to all host in the same l2 network
161 log.trace("simple fabric neightbour request forward broadcast: {} {}",
162 context.inPort(), context.vlan());
Jian Lie2d87512018-08-23 17:33:05 +0900163 for (Interface iface : fabricNetwork.interfaces()) {
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900164 if (!context.inPort().equals(iface.connectPoint())) {
165 log.trace("simple fabric forward neighbour request broadcast to {}", iface);
166 context.forward(iface);
167 }
168 }
169 } else {
170 log.warn("simple fabric neightbour request drop: {} {}",
171 context.inPort(), context.vlan());
172 context.drop();
173 }
174 }
175
176 /**
177 * Handles reply messages between VLAN tagged interfaces.
178 *
179 * @param context the message context
180 * @param hostService the host service
181 */
182 protected void handleReply(NeighbourMessageContext context,
183 HostService hostService) {
184 // Find target L2 Network, then reply to the host
Jian Lie2d87512018-08-23 17:33:05 +0900185 FabricNetwork fabricNetwork = simpleFabric.fabricNetwork(context.inPort(), context.vlan());
186 if (fabricNetwork != null) {
187 // TODO: need to check and update simpleFabric.DefaultFabricNetwork
188 MacAddress mac = simpleFabric.vMacForIp(context.target());
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900189 if (mac != null) {
190 log.trace("simple fabric neightbour response message to virtual gateway; drop: {} {} target={}",
191 context.inPort(), context.vlan(), context.target());
192 context.drop();
193 } else {
194 // forward reply to the hosts of the dstMac
195 Set<Host> hosts = hostService.getHostsByMac(context.dstMac());
196 log.trace("simple fabric neightbour response message forward: {} {} target={} -> {}",
197 context.inPort(), context.vlan(), context.target(), hosts);
198 hosts.stream()
Jian Lie2d87512018-08-23 17:33:05 +0900199 .map(host -> simpleFabric.hostInterface(host))
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900200 .filter(Objects::nonNull)
201 .forEach(context::forward);
202 }
203 } else {
204 // this might be happened when we remove an interface from L2 Network
205 // just ignore this message
Jian Lie2d87512018-08-23 17:33:05 +0900206 log.warn("simple fabric neightbour response message drop for unknown fabricNetwork: {} {}",
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900207 context.inPort(), context.vlan());
208 context.drop();
209 }
210 }
211
212 private class L2NetworkNeighbourMessageHandler implements NeighbourMessageHandler {
213 @Override
214 public void handleMessage(NeighbourMessageContext context,
215 HostService hostService) {
216 switch (context.type()) {
217 case REQUEST:
218 handleRequest(context);
219 break;
220 case REPLY:
221 handleReply(context, hostService);
222 break;
223 default:
224 log.warn("simple fabric neightor unknown context type: {}", context.type());
225 break;
226 }
227 }
228 }
229
230 private class InternalSimpleFabricListener implements SimpleFabricListener {
231 @Override
232 public void event(SimpleFabricEvent event) {
233 switch (event.type()) {
234 case SIMPLE_FABRIC_UPDATED:
235 refresh();
236 break;
237 default:
238 break;
239 }
240 }
241 }
242
243}
244