blob: e31f410d601ad726dc61ab1f75efb80e52590294 [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 */
16package org.onosproject.openstacknetworking.routing;
17
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;
35import org.onosproject.openstackinterface.OpenstackInterfaceService;
36import org.onosproject.openstackinterface.OpenstackPort;
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090037import org.onosproject.scalablegateway.api.ScalableGatewayService;
sangho6032f342016-07-07 14:32:03 +090038import org.onosproject.openstacknetworking.Constants;
Daniel Park81a61a12016-02-26 08:24:44 +090039import org.slf4j.Logger;
40
41import java.nio.ByteBuffer;
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;
46import static org.onosproject.openstacknetworking.Constants.DEVICE_OWNER_FLOATING_IP;
47import static org.onosproject.openstacknetworking.Constants.DEVICE_OWNER_ROUTER_GATEWAY;
Daniel Park81a61a12016-02-26 08:24:44 +090048import static org.slf4j.LoggerFactory.getLogger;
49
50/**
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070051 * Handle ARP, ICMP and NAT packets from gateway nodes.
Daniel Park81a61a12016-02-26 08:24:44 +090052 */
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070053@Component(immediate = true)
Daniel Park81a61a12016-02-26 08:24:44 +090054public class OpenstackRoutingArpHandler {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070055 private final Logger log = getLogger(getClass());
Daniel Park81a61a12016-02-26 08:24:44 +090056
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070057 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 protected PacketService packetService;
Daniel Park81a61a12016-02-26 08:24:44 +090059
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070060 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 protected OpenstackInterfaceService openstackService;
62
63 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 protected ScalableGatewayService gatewayService;
65
66 private final ExecutorService executorService =
67 newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "packet-event", log));
68
69 private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
70
71 @Activate
72 protected void activate() {
73 packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
74 log.info("Started");
Daniel Park81a61a12016-02-26 08:24:44 +090075 }
76
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070077 @Deactivate
78 protected void deactivate() {
79 packetService.removeProcessor(packetProcessor);
80 log.info("Stopped");
Daniel Park81a61a12016-02-26 08:24:44 +090081 }
82
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070083 private void processArpPacket(PacketContext context, Ethernet ethernet) {
Daniel Park81a61a12016-02-26 08:24:44 +090084 ARP arp = (ARP) ethernet.getPayload();
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070085 log.trace("arpEvent called from {} to {}",
Daniel Parkf78306f2016-04-06 17:57:48 +090086 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
87 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
88
Daniel Park81a61a12016-02-26 08:24:44 +090089 if (arp.getOpCode() != ARP.OP_REQUEST) {
90 return;
91 }
92
93 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
hyungseo Ryu38b5f182016-06-14 16:42:27 +090094 if (getTargetMacForTargetIp(targetIp.getIp4Address()) == MacAddress.NONE) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070095 return;
Daniel Park81a61a12016-02-26 08:24:44 +090096 }
97
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070098 MacAddress targetMac = Constants.DEFAULT_EXTERNAL_ROUTER_MAC;
Daniel Park81a61a12016-02-26 08:24:44 +090099 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
100 targetMac, ethernet);
101
102 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
103 .setOutput(context.inPacket().receivedFrom().port())
104 .build();
105
106 packetService.emit(new DefaultOutboundPacket(
107 context.inPacket().receivedFrom().deviceId(),
108 treatment,
109 ByteBuffer.wrap(ethReply.serialize())));
110 }
111
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700112 private class InternalPacketProcessor implements PacketProcessor {
113
114 @Override
115 public void process(PacketContext context) {
116 if (context.isHandled()) {
117 return;
118 } else if (!gatewayService.getGatewayDeviceIds().contains(
119 context.inPacket().receivedFrom().deviceId())) {
120 // return if the packet is not from gateway nodes
121 return;
122 }
123
124 InboundPacket pkt = context.inPacket();
125 Ethernet ethernet = pkt.parsed();
126 if (ethernet != null &&
127 ethernet.getEtherType() == Ethernet.TYPE_ARP) {
128 executorService.execute(() -> processArpPacket(context, ethernet));
129 }
130 }
131 }
132
133 // TODO make a cache for the MAC, not a good idea to REST call every time it gets ARP request
Daniel Park81a61a12016-02-26 08:24:44 +0900134 private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
135 OpenstackPort port = openstackService.ports().stream()
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700136 .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_GATEWAY) ||
137 p.deviceOwner().equals(DEVICE_OWNER_FLOATING_IP))
Daniel Park81a61a12016-02-26 08:24:44 +0900138 .filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
139 .findAny().orElse(null);
140
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700141 return port == null ? MacAddress.NONE : port.macAddress();
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +0900142 }
Daniel Park81a61a12016-02-26 08:24:44 +0900143}