blob: 4dc69a2b4e3c55ffef70cbdd4bd0da5bd0ef74e9 [file] [log] [blame]
Hyunsun Moon022272f2016-01-11 15:30:42 -08001/*
Brian O'Connor8e57fd52016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Hyunsun Moon022272f2016-01-11 15:30:42 -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 */
alshabibb4d31712016-06-01 18:51:03 -070016package org.opencord.cordvtn.impl;
Hyunsun Moon022272f2016-01-11 15:30:42 -080017
Hyunsun Moonbcf49252017-02-21 22:28:41 +090018import com.google.common.base.Strings;
Hyunsun Moonb5f92e52016-02-17 15:02:06 -080019import com.google.common.collect.Maps;
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090023import org.apache.felix.scr.annotations.Modified;
24import org.apache.felix.scr.annotations.Property;
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070025import org.apache.felix.scr.annotations.Reference;
26import org.apache.felix.scr.annotations.ReferenceCardinality;
Hyunsun Moon022272f2016-01-11 15:30:42 -080027import org.onlab.packet.ARP;
28import org.onlab.packet.EthType;
29import org.onlab.packet.Ethernet;
30import org.onlab.packet.Ip4Address;
31import org.onlab.packet.IpAddress;
32import org.onlab.packet.MacAddress;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090033import org.onlab.util.Tools;
34import org.onosproject.cfg.ComponentConfigService;
Hyunsun Moon4302c2b2017-01-19 14:20:34 +090035import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
Hyunsun Moonc031d9b2016-08-04 13:57:22 -070037import org.onosproject.net.DeviceId;
Hyunsun Moon187bf532017-01-19 10:57:40 +090038import org.onosproject.net.Host;
Hyunsun Moonc031d9b2016-08-04 13:57:22 -070039import org.onosproject.net.PortNumber;
Hyunsun Mooneaf75e62016-09-27 16:40:23 -070040import org.onosproject.net.config.NetworkConfigEvent;
41import org.onosproject.net.config.NetworkConfigListener;
Hyunsun Moon187bf532017-01-19 10:57:40 +090042import org.onosproject.net.config.NetworkConfigService;
Hyunsun Moon022272f2016-01-11 15:30:42 -080043import org.onosproject.net.flow.DefaultTrafficSelector;
44import org.onosproject.net.flow.DefaultTrafficTreatment;
45import org.onosproject.net.flow.TrafficSelector;
46import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moon4302c2b2017-01-19 14:20:34 +090047import org.onosproject.net.host.HostService;
Hyunsun Moon022272f2016-01-11 15:30:42 -080048import org.onosproject.net.packet.DefaultOutboundPacket;
49import org.onosproject.net.packet.PacketContext;
50import org.onosproject.net.packet.PacketPriority;
Hyunsun Moon187bf532017-01-19 10:57:40 +090051import org.onosproject.net.packet.PacketProcessor;
Hyunsun Moon022272f2016-01-11 15:30:42 -080052import org.onosproject.net.packet.PacketService;
Hyunsun Moon4302c2b2017-01-19 14:20:34 +090053import org.opencord.cordvtn.api.Constants;
Hyunsun Moon187bf532017-01-19 10:57:40 +090054import org.opencord.cordvtn.api.CordVtnConfig;
55import org.opencord.cordvtn.api.core.Instance;
Hyunsun Moon4302c2b2017-01-19 14:20:34 +090056import org.opencord.cordvtn.api.core.ServiceNetworkEvent;
57import org.opencord.cordvtn.api.core.ServiceNetworkListener;
58import org.opencord.cordvtn.api.core.ServiceNetworkService;
Hyunsun Moon187bf532017-01-19 10:57:40 +090059import org.opencord.cordvtn.api.net.ServiceNetwork;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090060import org.osgi.service.component.ComponentContext;
Hyunsun Moon022272f2016-01-11 15:30:42 -080061import org.slf4j.Logger;
62
63import java.nio.ByteBuffer;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090064import java.util.Dictionary;
Hyunsun Moonb5f92e52016-02-17 15:02:06 -080065import java.util.Map;
Hyunsun Moon022272f2016-01-11 15:30:42 -080066import java.util.Optional;
67import java.util.Set;
68
Hyunsun Moon4302c2b2017-01-19 14:20:34 +090069import static com.google.common.base.Preconditions.checkArgument;
Hyunsun Moon022272f2016-01-11 15:30:42 -080070import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moonbcf49252017-02-21 22:28:41 +090071import static org.opencord.cordvtn.api.Constants.DEFAULT_GATEWAY_MAC_STR;
Hyunsun Moon187bf532017-01-19 10:57:40 +090072import static org.opencord.cordvtn.api.net.ServiceNetwork.NetworkType.*;
Hyunsun Moon022272f2016-01-11 15:30:42 -080073import static org.slf4j.LoggerFactory.getLogger;
74
75/**
76 * Handles ARP requests for virtual network service IPs.
77 */
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070078@Component(immediate = true)
Hyunsun Moon4302c2b2017-01-19 14:20:34 +090079public class CordVtnArpProxy {
Hyunsun Moon022272f2016-01-11 15:30:42 -080080 protected final Logger log = getLogger(getClass());
Hyunsun Moon022272f2016-01-11 15:30:42 -080081
Hyunsun Moonbcf49252017-02-21 22:28:41 +090082 private static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";
83
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070084 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected PacketService packetService;
Hyunsun Moon022272f2016-01-11 15:30:42 -080086
Hyunsun Moonc031d9b2016-08-04 13:57:22 -070087 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon4302c2b2017-01-19 14:20:34 +090088 protected CoreService coreService;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected HostService hostService;
Hyunsun Moonc031d9b2016-08-04 13:57:22 -070092
Hyunsun Mooneaf75e62016-09-27 16:40:23 -070093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonbcf49252017-02-21 22:28:41 +090094 protected NetworkConfigService netConfigService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected ComponentConfigService compConfigService;
Hyunsun Mooneaf75e62016-09-27 16:40:23 -070098
Hyunsun Moon4302c2b2017-01-19 14:20:34 +090099 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected CordVtnNodeManager nodeManager;
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected ServiceNetworkService snetService;
104
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900105 @Property(name = PRIVATE_GATEWAY_MAC, value = DEFAULT_GATEWAY_MAC_STR,
106 label = "Fake MAC address for virtual network gateway")
107 private String privateGatewayMacStr = DEFAULT_GATEWAY_MAC_STR;
108 private MacAddress privateGatewayMac = MacAddress.valueOf(privateGatewayMacStr);
109
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700110 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moon8e9bc932017-01-31 21:32:20 +0900111 private final Map<IpAddress, MacAddress> gateways = Maps.newConcurrentMap();
Hyunsun Moon022272f2016-01-11 15:30:42 -0800112
Hyunsun Mooneaf75e62016-09-27 16:40:23 -0700113 private NetworkConfigListener configListener = new InternalConfigListener();
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900114 private ServiceNetworkListener snetListener = new InternalServiceNetworkListener();
115 private ApplicationId appId;
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700116
117 @Activate
118 protected void activate() {
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900119 appId = coreService.registerApplication(Constants.CORDVTN_APP_ID);
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900120 compConfigService.registerProperties(getClass());
121
122 netConfigService.addListener(configListener);
123 readPublicGateways();
124 snetService.addListener(snetListener);
125 readPrivateGateways();
Hyunsun Mooneaf75e62016-09-27 16:40:23 -0700126
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700127 packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
128 requestPacket();
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900129
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900130 log.info("Started");
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700131 }
132
133 @Deactivate
134 protected void deactivate() {
135 packetService.removeProcessor(packetProcessor);
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900136 snetService.removeListener(snetListener);
137 netConfigService.removeListener(configListener);
138 compConfigService.unregisterProperties(getClass(), false);
139
140 log.info("Stopped");
141 }
142
143 @Modified
144 protected void modified(ComponentContext context) {
145 Dictionary<?, ?> properties = context.getProperties();
146 String updatedMac;
147
148 updatedMac = Tools.get(properties, PRIVATE_GATEWAY_MAC);
149 if (!Strings.isNullOrEmpty(updatedMac) &&
150 !updatedMac.equals(privateGatewayMacStr)) {
151 privateGatewayMacStr = updatedMac;
152 privateGatewayMac = MacAddress.valueOf(privateGatewayMacStr);
153 }
154
155 log.info("Modified");
Hyunsun Moon022272f2016-01-11 15:30:42 -0800156 }
157
158 /**
159 * Requests ARP packet.
160 */
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700161 private void requestPacket() {
Hyunsun Moon022272f2016-01-11 15:30:42 -0800162 TrafficSelector selector = DefaultTrafficSelector.builder()
163 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
164 .build();
165
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900166 packetService.requestPackets(
167 selector,
168 PacketPriority.CONTROL,
169 appId,
170 Optional.empty());
Hyunsun Moon022272f2016-01-11 15:30:42 -0800171 }
172
173 /**
174 * Cancels ARP packet.
175 */
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700176 private void cancelPacket() {
Hyunsun Moon022272f2016-01-11 15:30:42 -0800177 TrafficSelector selector = DefaultTrafficSelector.builder()
178 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
179 .build();
180
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900181 packetService.cancelPackets(
182 selector,
183 PacketPriority.CONTROL,
184 appId,
185 Optional.empty());
Hyunsun Moon022272f2016-01-11 15:30:42 -0800186 }
187
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900188 private void readPrivateGateways() {
189 snetService.serviceNetworks().stream()
190 .filter(net -> net.type() == PRIVATE || net.type() == VSG)
191 .filter(net -> net.serviceIp() != null)
192 .forEach(net -> addGateway(net.serviceIp(), privateGatewayMac));
193 }
194
Hyunsun Moon022272f2016-01-11 15:30:42 -0800195 /**
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800196 * Adds a given gateway IP and MAC address to this ARP proxy.
Hyunsun Moon022272f2016-01-11 15:30:42 -0800197 *
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800198 * @param gatewayIp gateway ip address
199 * @param gatewayMac gateway mac address
Hyunsun Moon022272f2016-01-11 15:30:42 -0800200 */
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700201 private void addGateway(IpAddress gatewayIp, MacAddress gatewayMac) {
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900202 checkNotNull(gatewayIp, "Gateway IP address cannot be null");
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900203 checkArgument(gatewayMac != null && gatewayMac != MacAddress.NONE,
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900204 "Gateway MAC address cannot be null or NONE");
Hyunsun Moon8e9bc932017-01-31 21:32:20 +0900205
206 MacAddress existing = gateways.get(gatewayIp);
207 if (existing != null && !existing.equals(privateGatewayMac) &&
208 gatewayMac.equals(privateGatewayMac)) {
209 // this is public gateway IP and MAC configured via netcfg
210 // don't update with private gateway MAC
211 return;
212 }
213 gateways.put(gatewayIp, gatewayMac);
214 log.debug("Added ARP proxy entry IP:{} MAC:{}", gatewayIp, gatewayMac);
Hyunsun Moon022272f2016-01-11 15:30:42 -0800215 }
216
217 /**
218 * Removes a given service IP address from this ARP proxy.
219 *
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800220 * @param gatewayIp gateway ip address
Hyunsun Moon022272f2016-01-11 15:30:42 -0800221 */
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700222 private void removeGateway(IpAddress gatewayIp) {
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800223 checkNotNull(gatewayIp);
Hyunsun Moon8e9bc932017-01-31 21:32:20 +0900224 MacAddress existing = gateways.get(gatewayIp);
225 if (existing == null) {
226 return;
227 }
228 if (!existing.equals(privateGatewayMac)) {
229 // this is public gateway IP and MAC configured via netcfg
230 // do nothing
231 return;
232 }
233 gateways.remove(gatewayIp);
234 log.debug("Removed ARP proxy entry for IP:{} MAC: {}", gatewayIp, existing);
Hyunsun Moon022272f2016-01-11 15:30:42 -0800235 }
236
237 /**
238 * Emits ARP reply with fake MAC address for a given ARP request.
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700239 * It only handles requests for the registered gateway IPs and host IPs.
Hyunsun Moon022272f2016-01-11 15:30:42 -0800240 *
241 * @param context packet context
242 * @param ethPacket ethernet packet
243 */
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700244 private void processArpRequest(PacketContext context, Ethernet ethPacket) {
Hyunsun Moon022272f2016-01-11 15:30:42 -0800245 ARP arpPacket = (ARP) ethPacket.getPayload();
Hyunsun Moonb6febbe2016-02-12 15:59:53 -0800246 Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
Hyunsun Moonb6febbe2016-02-12 15:59:53 -0800247
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800248 MacAddress gatewayMac = gateways.get(targetIp);
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700249 MacAddress replyMac = gatewayMac != null ? gatewayMac :
250 getMacFromHostService(targetIp);
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800251
252 if (replyMac.equals(MacAddress.NONE)) {
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700253 log.trace("Failed to find MAC for {}", targetIp);
254 forwardManagementArpRequest(context, ethPacket);
Hyunsun Moon0d836e22016-02-01 23:30:58 -0800255 return;
256 }
257
Hyunsun Moon022272f2016-01-11 15:30:42 -0800258 Ethernet ethReply = ARP.buildArpReply(
259 targetIp,
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800260 replyMac,
Hyunsun Moon022272f2016-01-11 15:30:42 -0800261 ethPacket);
262
263 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
264 .setOutput(context.inPacket().receivedFrom().port())
265 .build();
266
267 packetService.emit(new DefaultOutboundPacket(
268 context.inPacket().receivedFrom().deviceId(),
269 treatment,
270 ByteBuffer.wrap(ethReply.serialize())));
271
272 context.block();
273 }
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800274
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700275 private void processArpReply(PacketContext context, Ethernet ethPacket) {
276 ARP arpPacket = (ARP) ethPacket.getPayload();
277 Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
278
279 DeviceId deviceId = context.inPacket().receivedFrom().deviceId();
280 Host host = hostService.getHostsByIp(targetIp).stream()
281 .filter(h -> h.location().deviceId().equals(deviceId))
282 .findFirst()
283 .orElse(null);
284
285 if (host == null) {
286 // do nothing for the unknown ARP reply
287 log.trace("No host found for {} in {}", targetIp, deviceId);
288 context.block();
289 return;
290 }
291
292 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
293 .setOutput(host.location().port())
294 .build();
295
296 packetService.emit(new DefaultOutboundPacket(
297 deviceId,
298 treatment,
299 ByteBuffer.wrap(ethPacket.serialize())));
300
301 context.block();
302 }
303
304 private void forwardManagementArpRequest(PacketContext context, Ethernet ethPacket) {
305 DeviceId deviceId = context.inPacket().receivedFrom().deviceId();
306 PortNumber hostMgmtPort = nodeManager.hostManagementPort(deviceId);
307 Host host = hostService.getConnectedHosts(context.inPacket().receivedFrom())
308 .stream()
309 .findFirst().orElse(null);
310
311 if (host == null ||
Hyunsun Mooneaf75e62016-09-27 16:40:23 -0700312 !Instance.of(host).netType().name().contains("MANAGEMENT") ||
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700313 hostMgmtPort == null) {
314 context.block();
315 return;
316 }
317
318 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
319 .setOutput(hostMgmtPort)
320 .build();
321
322 packetService.emit(new DefaultOutboundPacket(
323 context.inPacket().receivedFrom().deviceId(),
324 treatment,
325 ByteBuffer.wrap(ethPacket.serialize())));
326
327 log.trace("Forward ARP request to management network");
328 context.block();
329 }
330
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800331 /**
332 * Emits gratuitous ARP when a gateway mac address has been changed.
333 *
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800334 * @param gatewayIp gateway ip address to update MAC
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700335 * @param instances set of instances to send gratuitous ARP packet
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800336 */
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700337 private void sendGratuitousArp(IpAddress gatewayIp, Set<Instance> instances) {
Hyunsun Moon8e9bc932017-01-31 21:32:20 +0900338 MacAddress gatewayMac = gateways.get(gatewayIp);
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800339 if (gatewayMac == null) {
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700340 log.debug("Gateway {} is not registered to ARP proxy", gatewayIp);
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800341 return;
342 }
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800343
Hyunsun Moonb5f92e52016-02-17 15:02:06 -0800344 Ethernet ethArp = buildGratuitousArp(gatewayIp.getIp4Address(), gatewayMac);
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900345 instances.forEach(instance -> {
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800346 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700347 .setOutput(instance.portNumber())
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800348 .build();
349
350 packetService.emit(new DefaultOutboundPacket(
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700351 instance.deviceId(),
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800352 treatment,
353 ByteBuffer.wrap(ethArp.serialize())));
354 });
355 }
356
357 /**
358 * Builds gratuitous ARP packet with a given IP and MAC address.
359 *
360 * @param ip ip address for TPA and SPA
361 * @param mac new mac address
362 * @return ethernet packet
363 */
364 private Ethernet buildGratuitousArp(IpAddress ip, MacAddress mac) {
365 Ethernet eth = new Ethernet();
366
367 eth.setEtherType(Ethernet.TYPE_ARP);
368 eth.setSourceMACAddress(mac);
369 eth.setDestinationMACAddress(MacAddress.BROADCAST);
370
371 ARP arp = new ARP();
372 arp.setOpCode(ARP.OP_REQUEST);
373 arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
374 arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
375 arp.setProtocolType(ARP.PROTO_TYPE_IP);
376 arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
377
378 arp.setSenderHardwareAddress(mac.toBytes());
379 arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
380 arp.setSenderProtocolAddress(ip.getIp4Address().toOctets());
381 arp.setTargetProtocolAddress(ip.getIp4Address().toOctets());
382
383 eth.setPayload(arp);
384 return eth;
385 }
Hyunsun Moonb6febbe2016-02-12 15:59:53 -0800386
387 /**
388 * Returns MAC address of a host with a given target IP address by asking to
389 * host service. It does not support overlapping IP.
390 *
391 * @param targetIp target ip
392 * @return mac address, or NONE mac address if it fails to find the mac
393 */
394 private MacAddress getMacFromHostService(IpAddress targetIp) {
395 checkNotNull(targetIp);
396
397 Host host = hostService.getHostsByIp(targetIp)
398 .stream()
399 .findFirst()
400 .orElse(null);
401
402 if (host != null) {
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700403 log.trace("Found MAC from host service for {}", targetIp);
Hyunsun Moonb6febbe2016-02-12 15:59:53 -0800404 return host.mac();
405 } else {
406 return MacAddress.NONE;
407 }
408 }
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700409
410 private class InternalPacketProcessor implements PacketProcessor {
411
412 @Override
413 public void process(PacketContext context) {
414 if (context.isHandled()) {
415 return;
416 }
417 Ethernet ethPacket = context.inPacket().parsed();
418 if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
419 return;
420 }
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700421
422 ARP arpPacket = (ARP) ethPacket.getPayload();
423 switch (arpPacket.getOpCode()) {
424 case ARP.OP_REQUEST:
425 processArpRequest(context, ethPacket);
426 break;
427 case ARP.OP_REPLY:
428 processArpReply(context, ethPacket);
429 break;
430 default:
431 break;
432 }
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700433 }
434 }
435
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900436 private class InternalServiceNetworkListener implements ServiceNetworkListener {
437
438 @Override
439 public boolean isRelevant(ServiceNetworkEvent event) {
440 ServiceNetwork snet = event.subject();
Hyunsun Moon8e9bc932017-01-31 21:32:20 +0900441 return snet.serviceIp() != null;
Hyunsun Moon1e88fef2016-08-04 14:00:35 -0700442 }
443
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900444 @Override
445 public void event(ServiceNetworkEvent event) {
446 ServiceNetwork snet = event.subject();
447 switch (event.type()) {
448 case SERVICE_NETWORK_CREATED:
449 case SERVICE_NETWORK_UPDATED:
Hyunsun Moon8e9bc932017-01-31 21:32:20 +0900450 addGateway(snet.serviceIp(), privateGatewayMac);
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900451 break;
452 case SERVICE_NETWORK_REMOVED:
453 removeGateway(snet.serviceIp());
454 break;
455 case SERVICE_PORT_CREATED:
456 case SERVICE_PORT_UPDATED:
457 case SERVICE_PORT_REMOVED:
458 default:
459 // do nothing for the other events
460 break;
461 }
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700462 }
463 }
464
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900465 private void readPublicGateways() {
466 CordVtnConfig config = netConfigService.getConfig(appId, CordVtnConfig.class);
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700467 if (config == null) {
468 log.debug("No configuration found");
469 return;
470 }
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700471
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900472 config.publicGateways().entrySet().forEach(entry -> {
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700473 addGateway(entry.getKey(), entry.getValue());
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700474 });
475 // TODO send gratuitous arp in case the MAC is changed
Hyunsun Mooneaf75e62016-09-27 16:40:23 -0700476 }
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700477
Hyunsun Mooneaf75e62016-09-27 16:40:23 -0700478 private class InternalConfigListener implements NetworkConfigListener {
479
480 @Override
Hyunsun Moon4302c2b2017-01-19 14:20:34 +0900481 public boolean isRelevant(NetworkConfigEvent event) {
482 return event.configClass().equals(CordVtnConfig.class);
483 }
484
485 @Override
Hyunsun Mooneaf75e62016-09-27 16:40:23 -0700486 public void event(NetworkConfigEvent event) {
Hyunsun Mooneaf75e62016-09-27 16:40:23 -0700487
488 switch (event.type()) {
489 case CONFIG_ADDED:
490 case CONFIG_UPDATED:
Hyunsun Moonbcf49252017-02-21 22:28:41 +0900491 readPublicGateways();
Hyunsun Mooneaf75e62016-09-27 16:40:23 -0700492 break;
493 default:
494 break;
495 }
496 }
Hyunsun Moon5401aaa2016-06-12 17:40:34 -0700497 }
Hyunsun Moon022272f2016-01-11 15:30:42 -0800498}