blob: 8ae7282f6296e152f67d334c686d2f4a0409a200 [file] [log] [blame]
Daniel Park81a61a12016-02-26 08:24:44 +09001/*
2 * Copyright 2016 Open Networking Laboratory
3 *
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;
21import org.onlab.packet.IPv4;
22import 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;
37import 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;
53 private final OpenstackRoutingConfig config;
54 private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
55
56 /**
57 * Default constructor.
58 *
59 * @param packetService packet service
60 * @param openstackService openstackInterface service
61 * @param config openstackRoutingConfig
62 */
63 OpenstackRoutingArpHandler(PacketService packetService, OpenstackInterfaceService openstackService,
64 OpenstackRoutingConfig config) {
65 this.packetService = packetService;
66 this.openstackService = checkNotNull(openstackService);
67 this.config = checkNotNull(config);
68 }
69
70 /**
71 * Requests ARP packet to GatewayNode.
72 *
73 * @param appId application id
74 */
75 public void requestPacket(ApplicationId appId) {
76
77 TrafficSelector arpSelector = DefaultTrafficSelector.builder()
78 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
79 .build();
80
81 packetService.requestPackets(arpSelector,
82 PacketPriority.CONTROL,
83 appId,
84 Optional.of(DeviceId.deviceId(config.gatewayBridgeId())));
85 }
86
87 /**
88 * Handles ARP packet.
89 *
90 * @param context packet context
91 * @param ethernet ethernet
92 */
93 public void processArpPacketFromRouter(PacketContext context, Ethernet ethernet) {
94 checkNotNull(context, "context can not be null");
95 checkNotNull(ethernet, "ethernet can not be null");
96
97 log.info("arpEvent called from {} to {}",
98 Ip4Address.valueOf(((IPv4) ethernet.getPayload()).getSourceAddress()).toString(),
99 Ip4Address.valueOf(((IPv4) ethernet.getPayload()).getDestinationAddress()).toString());
100 ARP arp = (ARP) ethernet.getPayload();
101
102 if (arp.getOpCode() != ARP.OP_REQUEST) {
103 return;
104 }
105
106 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
107 MacAddress targetMac = getTargetMacForTargetIp(targetIp.getIp4Address());
108
109 if (targetMac == MacAddress.NONE) {
110 return;
111 }
112
113 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
114 targetMac, ethernet);
115
116 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
117 .setOutput(context.inPacket().receivedFrom().port())
118 .build();
119
120 packetService.emit(new DefaultOutboundPacket(
121 context.inPacket().receivedFrom().deviceId(),
122 treatment,
123 ByteBuffer.wrap(ethReply.serialize())));
124 }
125
126 private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
127 OpenstackPort port = openstackService.ports().stream()
128 .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY))
129 .filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
130 .findAny().orElse(null);
131
132 if (port == null) {
133 return MacAddress.NONE;
134 }
135 return port.macAddress();
136 }
137}