blob: 917bd6c19fcf4ef7393d7198bc9dc531eee845e0 [file] [log] [blame]
Hyunsun Moon022272f2016-01-11 15:30:42 -08001/*
2 * Copyright 2014-2015 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.cordvtn;
17
18import com.google.common.collect.Sets;
19import org.onlab.packet.ARP;
20import org.onlab.packet.EthType;
21import org.onlab.packet.Ethernet;
22import org.onlab.packet.Ip4Address;
23import org.onlab.packet.IpAddress;
24import org.onlab.packet.MacAddress;
25import org.onosproject.core.ApplicationId;
Hyunsun Moon3fc17f72016-01-24 21:47:06 -080026import org.onosproject.net.Host;
Hyunsun Moon022272f2016-01-11 15:30:42 -080027import 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.slf4j.Logger;
36
37import java.nio.ByteBuffer;
38import java.util.Optional;
39import java.util.Set;
40
Hyunsun Moon3fc17f72016-01-24 21:47:06 -080041import static com.google.common.base.Preconditions.checkArgument;
Hyunsun Moon022272f2016-01-11 15:30:42 -080042import static com.google.common.base.Preconditions.checkNotNull;
43import static org.slf4j.LoggerFactory.getLogger;
44
45/**
46 * Handles ARP requests for virtual network service IPs.
47 */
48public class CordVtnArpProxy {
49 protected final Logger log = getLogger(getClass());
Hyunsun Moon022272f2016-01-11 15:30:42 -080050
51 private final ApplicationId appId;
52 private final PacketService packetService;
53
54 private Set<Ip4Address> serviceIPs = Sets.newHashSet();
55
56 /**
57 * Default constructor.
58 *
59 * @param appId application id
60 * @param packetService packet service
61 */
62 public CordVtnArpProxy(ApplicationId appId, PacketService packetService) {
63 this.appId = appId;
64 this.packetService = packetService;
65 }
66
67 /**
68 * Requests ARP packet.
69 */
70 public void requestPacket() {
71 TrafficSelector selector = DefaultTrafficSelector.builder()
72 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
73 .build();
74
75 packetService.requestPackets(selector,
76 PacketPriority.CONTROL,
77 appId,
78 Optional.empty());
79 }
80
81 /**
82 * Cancels ARP packet.
83 */
84 public void cancelPacket() {
85 TrafficSelector selector = DefaultTrafficSelector.builder()
86 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
87 .build();
88
89 packetService.cancelPackets(selector,
90 PacketPriority.CONTROL,
91 appId,
92 Optional.empty());
93 }
94
95 /**
96 * Adds a given service IP address to be served.
97 *
98 * @param serviceIp service ip
99 */
100 public void addServiceIp(IpAddress serviceIp) {
101 checkNotNull(serviceIp);
102 serviceIPs.add(serviceIp.getIp4Address());
103 }
104
105 /**
106 * Removes a given service IP address from this ARP proxy.
107 *
108 * @param serviceIp service ip
109 */
110 public void removeServiceIp(IpAddress serviceIp) {
111 checkNotNull(serviceIp);
112 serviceIPs.remove(serviceIp.getIp4Address());
113 }
114
115 /**
116 * Emits ARP reply with fake MAC address for a given ARP request.
117 * It only handles requests for the registered service IPs, and the other
118 * requests can be handled by other ARP handlers like openstackSwitching or
119 * proxyArp, for example.
120 *
121 * @param context packet context
122 * @param ethPacket ethernet packet
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800123 * @param gatewayMac gateway mac address
Hyunsun Moon022272f2016-01-11 15:30:42 -0800124 */
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800125 public void processArpPacket(PacketContext context, Ethernet ethPacket, MacAddress gatewayMac) {
126 checkArgument(!gatewayMac.equals(MacAddress.NONE));
127
Hyunsun Moon022272f2016-01-11 15:30:42 -0800128 ARP arpPacket = (ARP) ethPacket.getPayload();
129 Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
130
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800131 if (arpPacket.getOpCode() != ARP.OP_REQUEST || !serviceIPs.contains(targetIp)) {
Hyunsun Moon022272f2016-01-11 15:30:42 -0800132 return;
133 }
134
Hyunsun Moon022272f2016-01-11 15:30:42 -0800135 Ethernet ethReply = ARP.buildArpReply(
136 targetIp,
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800137 gatewayMac,
Hyunsun Moon022272f2016-01-11 15:30:42 -0800138 ethPacket);
139
140 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
141 .setOutput(context.inPacket().receivedFrom().port())
142 .build();
143
144 packetService.emit(new DefaultOutboundPacket(
145 context.inPacket().receivedFrom().deviceId(),
146 treatment,
147 ByteBuffer.wrap(ethReply.serialize())));
148
149 context.block();
150 }
Hyunsun Moon3fc17f72016-01-24 21:47:06 -0800151
152 /**
153 * Emits gratuitous ARP when a gateway mac address has been changed.
154 *
155 * @param ip ip address to update MAC
156 * @param mac new mac address
157 * @param hosts set of hosts to send gratuitous ARP packet
158 */
159 public void sendGratuitousArp(IpAddress ip, MacAddress mac, Set<Host> hosts) {
160 checkArgument(!mac.equals(MacAddress.NONE));
161
162 Ethernet ethArp = buildGratuitousArp(ip.getIp4Address(), mac);
163 hosts.stream().forEach(host -> {
164 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
165 .setOutput(host.location().port())
166 .build();
167
168 packetService.emit(new DefaultOutboundPacket(
169 host.location().deviceId(),
170 treatment,
171 ByteBuffer.wrap(ethArp.serialize())));
172 });
173 }
174
175 /**
176 * Builds gratuitous ARP packet with a given IP and MAC address.
177 *
178 * @param ip ip address for TPA and SPA
179 * @param mac new mac address
180 * @return ethernet packet
181 */
182 private Ethernet buildGratuitousArp(IpAddress ip, MacAddress mac) {
183 Ethernet eth = new Ethernet();
184
185 eth.setEtherType(Ethernet.TYPE_ARP);
186 eth.setSourceMACAddress(mac);
187 eth.setDestinationMACAddress(MacAddress.BROADCAST);
188
189 ARP arp = new ARP();
190 arp.setOpCode(ARP.OP_REQUEST);
191 arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
192 arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
193 arp.setProtocolType(ARP.PROTO_TYPE_IP);
194 arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
195
196 arp.setSenderHardwareAddress(mac.toBytes());
197 arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
198 arp.setSenderProtocolAddress(ip.getIp4Address().toOctets());
199 arp.setTargetProtocolAddress(ip.getIp4Address().toOctets());
200
201 eth.setPayload(arp);
202 return eth;
203 }
Hyunsun Moon022272f2016-01-11 15:30:42 -0800204}