blob: 0ad21019b5ba662fba519fcc246f24a10e8e2cf4 [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
18import org.onlab.packet.ARP;
19import org.onlab.packet.EthType;
20import org.onlab.packet.Ethernet;
Daniel Park81a61a12016-02-26 08:24:44 +090021import org.onlab.packet.Ip4Address;
22import org.onlab.packet.IpAddress;
23import org.onlab.packet.MacAddress;
24import org.onosproject.core.ApplicationId;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.flow.DefaultTrafficSelector;
27import org.onosproject.net.flow.DefaultTrafficTreatment;
28import org.onosproject.net.flow.TrafficSelector;
29import org.onosproject.net.flow.TrafficTreatment;
30import org.onosproject.net.packet.DefaultOutboundPacket;
31import org.onosproject.net.packet.PacketContext;
32import org.onosproject.net.packet.PacketPriority;
33import org.onosproject.net.packet.PacketService;
34import org.onosproject.openstackinterface.OpenstackInterfaceService;
35import org.onosproject.openstackinterface.OpenstackPort;
sangho48907542016-03-28 16:07:07 +090036import org.onosproject.openstacknetworking.OpenstackNetworkingConfig;
Daniel Park81a61a12016-02-26 08:24:44 +090037import org.slf4j.Logger;
38
39import java.nio.ByteBuffer;
40import java.util.Optional;
41
42import static com.google.common.base.Preconditions.checkNotNull;
43import static org.slf4j.LoggerFactory.getLogger;
44
45/**
46 * Handle ARP packet sent from Openstack Gateway nodes.
47 */
48public class OpenstackRoutingArpHandler {
49 protected final Logger log = getLogger(getClass());
50
51 private final PacketService packetService;
52 private final OpenstackInterfaceService openstackService;
sangho48907542016-03-28 16:07:07 +090053 private final OpenstackNetworkingConfig config;
Daniel Park81a61a12016-02-26 08:24:44 +090054 private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
hyungseo Ryu38b5f182016-06-14 16:42:27 +090055 private static final String NETWORK_FLOATING_IP = "network:floatingip";
Daniel Park81a61a12016-02-26 08:24:44 +090056
57 /**
58 * Default constructor.
59 *
60 * @param packetService packet service
61 * @param openstackService openstackInterface service
62 * @param config openstackRoutingConfig
63 */
64 OpenstackRoutingArpHandler(PacketService packetService, OpenstackInterfaceService openstackService,
sangho48907542016-03-28 16:07:07 +090065 OpenstackNetworkingConfig config) {
Daniel Park81a61a12016-02-26 08:24:44 +090066 this.packetService = packetService;
67 this.openstackService = checkNotNull(openstackService);
68 this.config = checkNotNull(config);
69 }
70
71 /**
72 * Requests ARP packet to GatewayNode.
73 *
74 * @param appId application id
75 */
76 public void requestPacket(ApplicationId appId) {
77
78 TrafficSelector arpSelector = DefaultTrafficSelector.builder()
79 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
80 .build();
81
82 packetService.requestPackets(arpSelector,
83 PacketPriority.CONTROL,
84 appId,
85 Optional.of(DeviceId.deviceId(config.gatewayBridgeId())));
86 }
87
88 /**
89 * Handles ARP packet.
90 *
91 * @param context packet context
92 * @param ethernet ethernet
93 */
94 public void processArpPacketFromRouter(PacketContext context, Ethernet ethernet) {
95 checkNotNull(context, "context can not be null");
96 checkNotNull(ethernet, "ethernet can not be null");
97
Daniel Parkf78306f2016-04-06 17:57:48 +090098
Daniel Park81a61a12016-02-26 08:24:44 +090099 ARP arp = (ARP) ethernet.getPayload();
100
Daniel Parkf78306f2016-04-06 17:57:48 +0900101 log.debug("arpEvent called from {} to {}",
102 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
103 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
104
Daniel Park81a61a12016-02-26 08:24:44 +0900105 if (arp.getOpCode() != ARP.OP_REQUEST) {
106 return;
107 }
108
109 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
Daniel Park81a61a12016-02-26 08:24:44 +0900110
hyungseo Ryu38b5f182016-06-14 16:42:27 +0900111 if (getTargetMacForTargetIp(targetIp.getIp4Address()) == MacAddress.NONE) {
112 return;
Daniel Park81a61a12016-02-26 08:24:44 +0900113 }
hyungseo Ryu38b5f182016-06-14 16:42:27 +0900114 MacAddress targetMac = MacAddress.valueOf(config.gatewayExternalInterfaceMac());
Daniel Park81a61a12016-02-26 08:24:44 +0900115
116 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
117 targetMac, ethernet);
118
119 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
120 .setOutput(context.inPacket().receivedFrom().port())
121 .build();
122
123 packetService.emit(new DefaultOutboundPacket(
124 context.inPacket().receivedFrom().deviceId(),
125 treatment,
126 ByteBuffer.wrap(ethReply.serialize())));
127 }
128
129 private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
130 OpenstackPort port = openstackService.ports().stream()
hyungseo Ryu38b5f182016-06-14 16:42:27 +0900131 .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY) ||
132 p.deviceOwner().equals(NETWORK_FLOATING_IP))
Daniel Park81a61a12016-02-26 08:24:44 +0900133 .filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
134 .findAny().orElse(null);
135
136 if (port == null) {
137 return MacAddress.NONE;
138 }
139 return port.macAddress();
140 }
141}