blob: d506a7e4965e8690c04533dedf647abbc03524d0 [file] [log] [blame]
Lee Yongjae7c27bb42017-11-17 12:00:45 +09001/*
2 * Copyright 2017-present Open Networking Foundation
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 */
16package org.onosproject.simplefabric;
17
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;
33import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
35
36import java.util.HashSet;
37import java.util.Objects;
38import java.util.Set;
39
40
41/**
42 * Handles neighbour messages for on behalf of the L2 Network application. Handlers
43 * will be changed automatically by interface or network configuration events.
44 */
45@Component(immediate = true, enabled = false)
46public class SimpleFabricNeighbour {
47
48 private final Logger log = LoggerFactory.getLogger(getClass());
49 protected ApplicationId appId;
50
Ray Milkeyd84f89b2018-08-17 14:54:17 -070051 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090052 protected CoreService coreService;
53
Ray Milkeyd84f89b2018-08-17 14:54:17 -070054 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090055 protected HostService hostService;
56
Ray Milkeyd84f89b2018-08-17 14:54:17 -070057 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090058 protected InterfaceService interfaceService;
59
Ray Milkeyd84f89b2018-08-17 14:54:17 -070060 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090061 protected NeighbourResolutionService neighbourService;
62
Ray Milkeyd84f89b2018-08-17 14:54:17 -070063 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Lee Yongjae7c27bb42017-11-17 12:00:45 +090064 protected SimpleFabricService simpleFabric;
65
66 private final InternalSimpleFabricListener simpleFabricListener =
67 new InternalSimpleFabricListener();
68
69 private L2NetworkNeighbourMessageHandler neighbourHandler =
70 new L2NetworkNeighbourMessageHandler();
71
72 private Set<Interface> monitoredInterfaces = new HashSet<>();
73
74 @Activate
75 public void activate() {
76 appId = simpleFabric.getAppId();
77 simpleFabric.addListener(simpleFabricListener);
78 refresh();
79 log.info("simple fabric neighbour started");
80 }
81
82 @Deactivate
83 public void deactivate() {
84 simpleFabric.removeListener(simpleFabricListener);
85 unregister();
86 monitoredInterfaces.clear();
87 log.info("simple fabric neighbour stoped");
88 }
89
90 /**
91 * Registers neighbour handler to all available interfaces.
92 */
93 protected void refresh() {
94 Set<Interface> interfaces = interfaceService.getInterfaces();
95 // check for new interfaces
96 for (Interface intf : interfaces) {
97 if (!monitoredInterfaces.contains(intf) && simpleFabric.isL2NetworkInterface(intf)) {
98 log.info("simple fabric neighbour register handler: {}", intf);
99 neighbourService.registerNeighbourHandler(intf, neighbourHandler, appId);
100 monitoredInterfaces.add(intf);
101 } else {
102 log.debug("simple fabric neighobur unknown interface: {}", intf);
103 }
104 }
105 // check for removed interfaces
106 Set<Interface> monitoredInterfacesToBeRemoved = new HashSet<>();
107 for (Interface intf : monitoredInterfaces) {
108 if (!interfaces.contains(intf)) {
109 log.info("simple fabric neighbour unregister handler: {}", intf);
110 neighbourService.unregisterNeighbourHandler(intf, neighbourHandler, appId);
111 monitoredInterfacesToBeRemoved.add(intf);
112 }
113 }
114 for (Interface intf : monitoredInterfacesToBeRemoved) {
115 monitoredInterfaces.remove(intf);
116 }
117 }
118
119 /**
120 * Unregisters neighbour handler to all available interfaces.
121 */
122 protected void unregister() {
123 log.info("simple fabric neighbour unregister handler");
124 neighbourService.unregisterNeighbourHandlers(appId);
125 }
126
127 /**
128 * Handles request messages.
129 *
130 * @param context the message context
131 */
132 protected void handleRequest(NeighbourMessageContext context) {
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900133 MacAddress mac = simpleFabric.findVMacForIp(context.target());
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900134 if (mac != null) {
135 log.trace("simple fabric neightbour request on virtualGatewayAddress {}; response to {} {} mac={}",
136 context.target(), context.inPort(), context.vlan(), mac);
137 context.reply(mac);
138 return;
139 }
140 // else forward to corresponding host
141
142 L2Network l2Network = simpleFabric.findL2Network(context.inPort(), context.vlan());
143 if (l2Network != null) {
144 int numForwards = 0;
145 if (!context.dstMac().isBroadcast() && !context.dstMac().isMulticast()) {
146 for (Host host : hostService.getHostsByMac(context.dstMac())) {
147 log.trace("simple fabric neightbour request forward unicast to {}", host.location());
148 context.forward(host.location()); // ASSUME: vlan is same
149 // TODO: may need to check host.location().time()
150 numForwards++;
151 }
152 if (numForwards > 0) {
153 return;
154 }
155 }
156 // else do broadcast to all host in the same l2 network
157 log.trace("simple fabric neightbour request forward broadcast: {} {}",
158 context.inPort(), context.vlan());
159 for (Interface iface : l2Network.interfaces()) {
160 if (!context.inPort().equals(iface.connectPoint())) {
161 log.trace("simple fabric forward neighbour request broadcast to {}", iface);
162 context.forward(iface);
163 }
164 }
165 } else {
166 log.warn("simple fabric neightbour request drop: {} {}",
167 context.inPort(), context.vlan());
168 context.drop();
169 }
170 }
171
172 /**
173 * Handles reply messages between VLAN tagged interfaces.
174 *
175 * @param context the message context
176 * @param hostService the host service
177 */
178 protected void handleReply(NeighbourMessageContext context,
179 HostService hostService) {
180 // Find target L2 Network, then reply to the host
181 L2Network l2Network = simpleFabric.findL2Network(context.inPort(), context.vlan());
182 if (l2Network != null) {
183 // TODO: need to check and update simpleFabric.L2Network
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900184 MacAddress mac = simpleFabric.findVMacForIp(context.target());
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900185 if (mac != null) {
186 log.trace("simple fabric neightbour response message to virtual gateway; drop: {} {} target={}",
187 context.inPort(), context.vlan(), context.target());
188 context.drop();
189 } else {
190 // forward reply to the hosts of the dstMac
191 Set<Host> hosts = hostService.getHostsByMac(context.dstMac());
192 log.trace("simple fabric neightbour response message forward: {} {} target={} -> {}",
193 context.inPort(), context.vlan(), context.target(), hosts);
194 hosts.stream()
Lee Yongjae6dc7e4f2017-12-06 16:17:51 +0900195 .map(host -> simpleFabric.findHostInterface(host))
Lee Yongjae7c27bb42017-11-17 12:00:45 +0900196 .filter(Objects::nonNull)
197 .forEach(context::forward);
198 }
199 } else {
200 // this might be happened when we remove an interface from L2 Network
201 // just ignore this message
202 log.warn("simple fabric neightbour response message drop for unknown l2Network: {} {}",
203 context.inPort(), context.vlan());
204 context.drop();
205 }
206 }
207
208 private class L2NetworkNeighbourMessageHandler implements NeighbourMessageHandler {
209 @Override
210 public void handleMessage(NeighbourMessageContext context,
211 HostService hostService) {
212 switch (context.type()) {
213 case REQUEST:
214 handleRequest(context);
215 break;
216 case REPLY:
217 handleReply(context, hostService);
218 break;
219 default:
220 log.warn("simple fabric neightor unknown context type: {}", context.type());
221 break;
222 }
223 }
224 }
225
226 private class InternalSimpleFabricListener implements SimpleFabricListener {
227 @Override
228 public void event(SimpleFabricEvent event) {
229 switch (event.type()) {
230 case SIMPLE_FABRIC_UPDATED:
231 refresh();
232 break;
233 default:
234 break;
235 }
236 }
237 }
238
239}
240