blob: ff0a4efe6b64c10487605dfafa48dfcc7681a944 [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;
36import org.slf4j.Logger;
37
38import java.nio.ByteBuffer;
39import java.util.Optional;
40
41import static com.google.common.base.Preconditions.checkNotNull;
42import static org.slf4j.LoggerFactory.getLogger;
43
44/**
45 * Handle ARP packet sent from Openstack Gateway nodes.
46 */
47public class OpenstackRoutingArpHandler {
48 protected final Logger log = getLogger(getClass());
49
50 private final PacketService packetService;
51 private final OpenstackInterfaceService openstackService;
52 private final OpenstackRoutingConfig config;
53 private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
54
55 /**
56 * Default constructor.
57 *
58 * @param packetService packet service
59 * @param openstackService openstackInterface service
60 * @param config openstackRoutingConfig
61 */
62 OpenstackRoutingArpHandler(PacketService packetService, OpenstackInterfaceService openstackService,
63 OpenstackRoutingConfig config) {
64 this.packetService = packetService;
65 this.openstackService = checkNotNull(openstackService);
66 this.config = checkNotNull(config);
67 }
68
69 /**
70 * Requests ARP packet to GatewayNode.
71 *
72 * @param appId application id
73 */
74 public void requestPacket(ApplicationId appId) {
75
76 TrafficSelector arpSelector = DefaultTrafficSelector.builder()
77 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
78 .build();
79
80 packetService.requestPackets(arpSelector,
81 PacketPriority.CONTROL,
82 appId,
83 Optional.of(DeviceId.deviceId(config.gatewayBridgeId())));
84 }
85
86 /**
87 * Handles ARP packet.
88 *
89 * @param context packet context
90 * @param ethernet ethernet
91 */
92 public void processArpPacketFromRouter(PacketContext context, Ethernet ethernet) {
93 checkNotNull(context, "context can not be null");
94 checkNotNull(ethernet, "ethernet can not be null");
95
Daniel Parkf78306f2016-04-06 17:57:48 +090096
Daniel Park81a61a12016-02-26 08:24:44 +090097 ARP arp = (ARP) ethernet.getPayload();
98
Daniel Parkf78306f2016-04-06 17:57:48 +090099 log.debug("arpEvent called from {} to {}",
100 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
101 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
102
Daniel Park81a61a12016-02-26 08:24:44 +0900103 if (arp.getOpCode() != ARP.OP_REQUEST) {
104 return;
105 }
106
107 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
108 MacAddress targetMac = getTargetMacForTargetIp(targetIp.getIp4Address());
109
110 if (targetMac == MacAddress.NONE) {
111 return;
112 }
113
114 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
115 targetMac, ethernet);
116
117 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
118 .setOutput(context.inPacket().receivedFrom().port())
119 .build();
120
121 packetService.emit(new DefaultOutboundPacket(
122 context.inPacket().receivedFrom().deviceId(),
123 treatment,
124 ByteBuffer.wrap(ethReply.serialize())));
125 }
126
127 private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
128 OpenstackPort port = openstackService.ports().stream()
129 .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY))
130 .filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
131 .findAny().orElse(null);
132
133 if (port == null) {
134 return MacAddress.NONE;
135 }
136 return port.macAddress();
137 }
138}