blob: 7dee2c16680062c90cfc0c842559d114f2c59b2d [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";
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,
sangho48907542016-03-28 16:07:07 +090064 OpenstackNetworkingConfig config) {
Daniel Park81a61a12016-02-26 08:24:44 +090065 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
Daniel Parkf78306f2016-04-06 17:57:48 +090097
Daniel Park81a61a12016-02-26 08:24:44 +090098 ARP arp = (ARP) ethernet.getPayload();
99
Daniel Parkf78306f2016-04-06 17:57:48 +0900100 log.debug("arpEvent called from {} to {}",
101 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
102 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
103
Daniel Park81a61a12016-02-26 08:24:44 +0900104 if (arp.getOpCode() != ARP.OP_REQUEST) {
105 return;
106 }
107
108 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
109 MacAddress targetMac = getTargetMacForTargetIp(targetIp.getIp4Address());
110
111 if (targetMac == MacAddress.NONE) {
112 return;
113 }
114
115 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
116 targetMac, ethernet);
117
118 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
119 .setOutput(context.inPacket().receivedFrom().port())
120 .build();
121
122 packetService.emit(new DefaultOutboundPacket(
123 context.inPacket().receivedFrom().deviceId(),
124 treatment,
125 ByteBuffer.wrap(ethReply.serialize())));
126 }
127
128 private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
129 OpenstackPort port = openstackService.ports().stream()
130 .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY))
131 .filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
132 .findAny().orElse(null);
133
134 if (port == null) {
135 return MacAddress.NONE;
136 }
137 return port.macAddress();
138 }
139}