blob: 2c9a3044d220d2c676f2be50f4274c2fd8699b16 [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
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090018import com.google.common.collect.Lists;
Daniel Park81a61a12016-02-26 08:24:44 +090019import org.onlab.packet.ARP;
20import org.onlab.packet.EthType;
21import org.onlab.packet.Ethernet;
Daniel Park81a61a12016-02-26 08:24:44 +090022import org.onlab.packet.Ip4Address;
23import org.onlab.packet.IpAddress;
24import org.onlab.packet.MacAddress;
25import org.onosproject.core.ApplicationId;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.flow.DefaultTrafficSelector;
28import org.onosproject.net.flow.DefaultTrafficTreatment;
29import org.onosproject.net.flow.TrafficSelector;
30import org.onosproject.net.flow.TrafficTreatment;
31import org.onosproject.net.packet.DefaultOutboundPacket;
32import org.onosproject.net.packet.PacketContext;
33import org.onosproject.net.packet.PacketPriority;
34import 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;
39import org.onosproject.openstacknode.OpenstackNodeService;
Daniel Park81a61a12016-02-26 08:24:44 +090040import org.slf4j.Logger;
41
42import java.nio.ByteBuffer;
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090043import java.util.List;
Daniel Park81a61a12016-02-26 08:24:44 +090044import java.util.Optional;
45
46import static com.google.common.base.Preconditions.checkNotNull;
47import static org.slf4j.LoggerFactory.getLogger;
48
49/**
50 * Handle ARP packet sent from Openstack Gateway nodes.
51 */
52public class OpenstackRoutingArpHandler {
53 protected final Logger log = getLogger(getClass());
54
55 private final PacketService packetService;
56 private final OpenstackInterfaceService openstackService;
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090057 private final ScalableGatewayService gatewayService;
sangho6032f342016-07-07 14:32:03 +090058 private final OpenstackNodeService nodeService;
Daniel Park81a61a12016-02-26 08:24:44 +090059 private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
hyungseo Ryu38b5f182016-06-14 16:42:27 +090060 private static final String NETWORK_FLOATING_IP = "network:floatingip";
Daniel Park81a61a12016-02-26 08:24:44 +090061
62 /**
63 * Default constructor.
sangho6032f342016-07-07 14:32:03 +090064 *
65 * @param packetService packet service
Daniel Park81a61a12016-02-26 08:24:44 +090066 * @param openstackService openstackInterface service
sangho6032f342016-07-07 14:32:03 +090067 * @param gatewayService gateway service
68 * @param nodeService openstackNodeService
Daniel Park81a61a12016-02-26 08:24:44 +090069 */
70 OpenstackRoutingArpHandler(PacketService packetService, OpenstackInterfaceService openstackService,
sangho6032f342016-07-07 14:32:03 +090071 OpenstackNodeService nodeService, ScalableGatewayService gatewayService) {
Daniel Park81a61a12016-02-26 08:24:44 +090072 this.packetService = packetService;
73 this.openstackService = checkNotNull(openstackService);
sangho6032f342016-07-07 14:32:03 +090074 this.nodeService = nodeService;
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090075 this.gatewayService = gatewayService;
Daniel Park81a61a12016-02-26 08:24:44 +090076 }
77
78 /**
79 * Requests ARP packet to GatewayNode.
80 *
81 * @param appId application id
82 */
83 public void requestPacket(ApplicationId appId) {
84
85 TrafficSelector arpSelector = DefaultTrafficSelector.builder()
86 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
87 .build();
88
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090089 getExternalInfo().forEach(deviceId ->
90 packetService.requestPackets(arpSelector,
91 PacketPriority.CONTROL,
92 appId,
93 Optional.of(deviceId))
94 );
Daniel Park81a61a12016-02-26 08:24:44 +090095 }
96
97 /**
98 * Handles ARP packet.
99 *
100 * @param context packet context
101 * @param ethernet ethernet
102 */
103 public void processArpPacketFromRouter(PacketContext context, Ethernet ethernet) {
104 checkNotNull(context, "context can not be null");
105 checkNotNull(ethernet, "ethernet can not be null");
106
Daniel Parkf78306f2016-04-06 17:57:48 +0900107
Daniel Park81a61a12016-02-26 08:24:44 +0900108 ARP arp = (ARP) ethernet.getPayload();
109
Daniel Parkf78306f2016-04-06 17:57:48 +0900110 log.debug("arpEvent called from {} to {}",
111 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
112 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
113
Daniel Park81a61a12016-02-26 08:24:44 +0900114 if (arp.getOpCode() != ARP.OP_REQUEST) {
115 return;
116 }
117
118 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
Daniel Park81a61a12016-02-26 08:24:44 +0900119
hyungseo Ryu38b5f182016-06-14 16:42:27 +0900120 if (getTargetMacForTargetIp(targetIp.getIp4Address()) == MacAddress.NONE) {
121 return;
Daniel Park81a61a12016-02-26 08:24:44 +0900122 }
sangho6032f342016-07-07 14:32:03 +0900123 // FIXME: Set the correct gateway
124 MacAddress targetMac = Constants.GW_EXT_INT_MAC;
Daniel Park81a61a12016-02-26 08:24:44 +0900125
126 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
127 targetMac, ethernet);
128
129 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
130 .setOutput(context.inPacket().receivedFrom().port())
131 .build();
132
133 packetService.emit(new DefaultOutboundPacket(
134 context.inPacket().receivedFrom().deviceId(),
135 treatment,
136 ByteBuffer.wrap(ethReply.serialize())));
137 }
138
139 private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
140 OpenstackPort port = openstackService.ports().stream()
hyungseo Ryu38b5f182016-06-14 16:42:27 +0900141 .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY) ||
142 p.deviceOwner().equals(NETWORK_FLOATING_IP))
Daniel Park81a61a12016-02-26 08:24:44 +0900143 .filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
144 .findAny().orElse(null);
145
146 if (port == null) {
147 return MacAddress.NONE;
148 }
149 return port.macAddress();
150 }
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +0900151
152 private List<DeviceId> getExternalInfo() {
153 List<DeviceId> externalInfoList = Lists.newArrayList();
154 gatewayService.getGatewayDeviceIds().forEach(externalInfoList::add);
155 return externalInfoList;
156 }
Daniel Park81a61a12016-02-26 08:24:44 +0900157}