blob: 9e23b5d7fedf12e9f8d0f334c4af02cd27c70995 [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;
sangho48907542016-03-28 16:07:07 +090037import org.onosproject.openstacknetworking.OpenstackNetworkingConfig;
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090038import org.onosproject.scalablegateway.api.ScalableGatewayService;
Daniel Park81a61a12016-02-26 08:24:44 +090039import org.slf4j.Logger;
40
41import java.nio.ByteBuffer;
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090042import java.util.List;
Daniel Park81a61a12016-02-26 08:24:44 +090043import java.util.Optional;
44
45import static com.google.common.base.Preconditions.checkNotNull;
46import static org.slf4j.LoggerFactory.getLogger;
47
48/**
49 * Handle ARP packet sent from Openstack Gateway nodes.
50 */
51public class OpenstackRoutingArpHandler {
52 protected final Logger log = getLogger(getClass());
53
54 private final PacketService packetService;
55 private final OpenstackInterfaceService openstackService;
sangho48907542016-03-28 16:07:07 +090056 private final OpenstackNetworkingConfig config;
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090057 private final ScalableGatewayService gatewayService;
Daniel Park81a61a12016-02-26 08:24:44 +090058 private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
hyungseo Ryu38b5f182016-06-14 16:42:27 +090059 private static final String NETWORK_FLOATING_IP = "network:floatingip";
Daniel Park81a61a12016-02-26 08:24:44 +090060
61 /**
62 * Default constructor.
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090063 * @param packetService packet service
Daniel Park81a61a12016-02-26 08:24:44 +090064 * @param openstackService openstackInterface service
65 * @param config openstackRoutingConfig
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090066 * @param gatewayService
Daniel Park81a61a12016-02-26 08:24:44 +090067 */
68 OpenstackRoutingArpHandler(PacketService packetService, OpenstackInterfaceService openstackService,
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090069 OpenstackNetworkingConfig config, ScalableGatewayService gatewayService) {
Daniel Park81a61a12016-02-26 08:24:44 +090070 this.packetService = packetService;
71 this.openstackService = checkNotNull(openstackService);
72 this.config = checkNotNull(config);
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090073 this.gatewayService = gatewayService;
Daniel Park81a61a12016-02-26 08:24:44 +090074 }
75
76 /**
77 * Requests ARP packet to GatewayNode.
78 *
79 * @param appId application id
80 */
81 public void requestPacket(ApplicationId appId) {
82
83 TrafficSelector arpSelector = DefaultTrafficSelector.builder()
84 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
85 .build();
86
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090087 getExternalInfo().forEach(deviceId ->
88 packetService.requestPackets(arpSelector,
89 PacketPriority.CONTROL,
90 appId,
91 Optional.of(deviceId))
92 );
Daniel Park81a61a12016-02-26 08:24:44 +090093 }
94
95 /**
96 * Handles ARP packet.
97 *
98 * @param context packet context
99 * @param ethernet ethernet
100 */
101 public void processArpPacketFromRouter(PacketContext context, Ethernet ethernet) {
102 checkNotNull(context, "context can not be null");
103 checkNotNull(ethernet, "ethernet can not be null");
104
Daniel Parkf78306f2016-04-06 17:57:48 +0900105
Daniel Park81a61a12016-02-26 08:24:44 +0900106 ARP arp = (ARP) ethernet.getPayload();
107
Daniel Parkf78306f2016-04-06 17:57:48 +0900108 log.debug("arpEvent called from {} to {}",
109 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
110 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
111
Daniel Park81a61a12016-02-26 08:24:44 +0900112 if (arp.getOpCode() != ARP.OP_REQUEST) {
113 return;
114 }
115
116 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
Daniel Park81a61a12016-02-26 08:24:44 +0900117
hyungseo Ryu38b5f182016-06-14 16:42:27 +0900118 if (getTargetMacForTargetIp(targetIp.getIp4Address()) == MacAddress.NONE) {
119 return;
Daniel Park81a61a12016-02-26 08:24:44 +0900120 }
hyungseo Ryu38b5f182016-06-14 16:42:27 +0900121 MacAddress targetMac = MacAddress.valueOf(config.gatewayExternalInterfaceMac());
Daniel Park81a61a12016-02-26 08:24:44 +0900122
123 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
124 targetMac, ethernet);
125
126 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
127 .setOutput(context.inPacket().receivedFrom().port())
128 .build();
129
130 packetService.emit(new DefaultOutboundPacket(
131 context.inPacket().receivedFrom().deviceId(),
132 treatment,
133 ByteBuffer.wrap(ethReply.serialize())));
134 }
135
136 private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
137 OpenstackPort port = openstackService.ports().stream()
hyungseo Ryu38b5f182016-06-14 16:42:27 +0900138 .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY) ||
139 p.deviceOwner().equals(NETWORK_FLOATING_IP))
Daniel Park81a61a12016-02-26 08:24:44 +0900140 .filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
141 .findAny().orElse(null);
142
143 if (port == null) {
144 return MacAddress.NONE;
145 }
146 return port.macAddress();
147 }
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +0900148
149 private List<DeviceId> getExternalInfo() {
150 List<DeviceId> externalInfoList = Lists.newArrayList();
151 gatewayService.getGatewayDeviceIds().forEach(externalInfoList::add);
152 return externalInfoList;
153 }
Daniel Park81a61a12016-02-26 08:24:44 +0900154}