blob: 03810c322657a410131be63e756bdaf74c183635 [file] [log] [blame]
Daniel Park81a61a12016-02-26 08:24:44 +09001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Daniel Park81a61a12016-02-26 08:24:44 +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 */
Hyunsun Moon05400872017-02-07 17:11:25 +090016package org.onosproject.openstacknetworking.impl;
Daniel Park81a61a12016-02-26 08:24:44 +090017
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
Daniel Park81a61a12016-02-26 08:24:44 +090023import org.onlab.packet.ARP;
Daniel Park81a61a12016-02-26 08:24:44 +090024import org.onlab.packet.Ethernet;
Daniel Park81a61a12016-02-26 08:24:44 +090025import org.onlab.packet.Ip4Address;
26import org.onlab.packet.IpAddress;
27import org.onlab.packet.MacAddress;
Daniel Park81a61a12016-02-26 08:24:44 +090028import org.onosproject.net.flow.DefaultTrafficTreatment;
Daniel Park81a61a12016-02-26 08:24:44 +090029import org.onosproject.net.flow.TrafficTreatment;
30import org.onosproject.net.packet.DefaultOutboundPacket;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070031import org.onosproject.net.packet.InboundPacket;
Daniel Park81a61a12016-02-26 08:24:44 +090032import org.onosproject.net.packet.PacketContext;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070033import org.onosproject.net.packet.PacketProcessor;
Daniel Park81a61a12016-02-26 08:24:44 +090034import org.onosproject.net.packet.PacketService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090035import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090036import org.onosproject.scalablegateway.api.ScalableGatewayService;
Hyunsun Moon05400872017-02-07 17:11:25 +090037import org.onosproject.openstacknetworking.api.Constants;
Daniel Park81a61a12016-02-26 08:24:44 +090038import org.slf4j.Logger;
39
40import java.nio.ByteBuffer;
Hyunsun Moon44aac662017-02-18 02:07:01 +090041import java.util.Objects;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070042import java.util.concurrent.ExecutorService;
Daniel Park81a61a12016-02-26 08:24:44 +090043
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070044import static java.util.concurrent.Executors.newSingleThreadExecutor;
45import static org.onlab.util.Tools.groupedThreads;
Daniel Park81a61a12016-02-26 08:24:44 +090046import static org.slf4j.LoggerFactory.getLogger;
47
48/**
Hyunsun Moon44aac662017-02-18 02:07:01 +090049 * Handle ARP requests from gateway nodes.
Daniel Park81a61a12016-02-26 08:24:44 +090050 */
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070051@Component(immediate = true)
Daniel Park81a61a12016-02-26 08:24:44 +090052public class OpenstackRoutingArpHandler {
Hyunsun Moon44aac662017-02-18 02:07:01 +090053
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070054 private final Logger log = getLogger(getClass());
Daniel Park81a61a12016-02-26 08:24:44 +090055
Hyunsun Moon44aac662017-02-18 02:07:01 +090056 private static final String DEVICE_OWNER_ROUTER_GW = "network:router_gateway";
57 private static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
58
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070059 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected PacketService packetService;
Daniel Park81a61a12016-02-26 08:24:44 +090061
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070062 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070063 protected ScalableGatewayService gatewayService;
64
Hyunsun Moon44aac662017-02-18 02:07:01 +090065 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected OpenstackNetworkService osNetworkService;
67
68 private final ExecutorService eventExecutor = newSingleThreadExecutor(
69 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070070
71 private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
72
73 @Activate
74 protected void activate() {
75 packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
76 log.info("Started");
Daniel Park81a61a12016-02-26 08:24:44 +090077 }
78
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070079 @Deactivate
80 protected void deactivate() {
81 packetService.removeProcessor(packetProcessor);
Hyunsun Moon44aac662017-02-18 02:07:01 +090082 eventExecutor.shutdown();
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070083 log.info("Stopped");
Daniel Park81a61a12016-02-26 08:24:44 +090084 }
85
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070086 private void processArpPacket(PacketContext context, Ethernet ethernet) {
Daniel Park81a61a12016-02-26 08:24:44 +090087 ARP arp = (ARP) ethernet.getPayload();
Daniel Park81a61a12016-02-26 08:24:44 +090088 if (arp.getOpCode() != ARP.OP_REQUEST) {
89 return;
90 }
91
Hyunsun Moon44aac662017-02-18 02:07:01 +090092 if (log.isTraceEnabled()) {
93 log.trace("ARP request received from {} for {}",
94 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
95 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
96 }
97
Daniel Park81a61a12016-02-26 08:24:44 +090098 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
Hyunsun Moon44aac662017-02-18 02:07:01 +090099 if (!isServiceIp(targetIp.getIp4Address())) {
100 log.trace("Unknown target ARP request for {}, ignore it", targetIp);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700101 return;
Daniel Park81a61a12016-02-26 08:24:44 +0900102 }
103
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700104 MacAddress targetMac = Constants.DEFAULT_EXTERNAL_ROUTER_MAC;
Daniel Park81a61a12016-02-26 08:24:44 +0900105 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
106 targetMac, ethernet);
107
108 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
109 .setOutput(context.inPacket().receivedFrom().port())
110 .build();
111
112 packetService.emit(new DefaultOutboundPacket(
113 context.inPacket().receivedFrom().deviceId(),
114 treatment,
115 ByteBuffer.wrap(ethReply.serialize())));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900116
117 context.block();
Daniel Park81a61a12016-02-26 08:24:44 +0900118 }
119
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700120 private class InternalPacketProcessor implements PacketProcessor {
121
122 @Override
123 public void process(PacketContext context) {
124 if (context.isHandled()) {
125 return;
126 } else if (!gatewayService.getGatewayDeviceIds().contains(
127 context.inPacket().receivedFrom().deviceId())) {
128 // return if the packet is not from gateway nodes
129 return;
130 }
131
132 InboundPacket pkt = context.inPacket();
133 Ethernet ethernet = pkt.parsed();
134 if (ethernet != null &&
135 ethernet.getEtherType() == Ethernet.TYPE_ARP) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900136 eventExecutor.execute(() -> processArpPacket(context, ethernet));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700137 }
138 }
139 }
140
Hyunsun Moon44aac662017-02-18 02:07:01 +0900141 private boolean isServiceIp(IpAddress targetIp) {
142 // FIXME use floating IP and external gateway information of router instead
143 // once openstack4j fixed
144 return osNetworkService.ports().stream()
145 .filter(osPort -> Objects.equals(osPort.getDeviceOwner(),
146 DEVICE_OWNER_ROUTER_GW) ||
147 Objects.equals(osPort.getDeviceOwner(),
148 DEVICE_OWNER_FLOATING_IP))
149 .flatMap(osPort -> osPort.getFixedIps().stream())
150 .anyMatch(ip -> IpAddress.valueOf(ip.getIpAddress()).equals(targetIp));
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +0900151 }
Daniel Park81a61a12016-02-26 08:24:44 +0900152}