blob: 4cef1488306ee202c16d04262c086bfac2b9ca76 [file] [log] [blame]
Hyunsun Moon42c7b4e2016-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;
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.slf4j.Logger;
35
36import java.nio.ByteBuffer;
37import java.util.Optional;
38import java.util.Set;
39
40import static com.google.common.base.Preconditions.checkNotNull;
41import static org.slf4j.LoggerFactory.getLogger;
42
43/**
44 * Handles ARP requests for virtual network service IPs.
45 */
46public class CordVtnArpProxy {
47 protected final Logger log = getLogger(getClass());
48 // TODO make gateway MAC address configurable
49 private static final MacAddress DEFAULT_GATEWAY_MAC = MacAddress.valueOf("00:00:00:00:00:01");
50
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
123 */
124 public void processArpPacket(PacketContext context, Ethernet ethPacket) {
125 ARP arpPacket = (ARP) ethPacket.getPayload();
126 Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
127
128 if (arpPacket.getOpCode() != ARP.OP_REQUEST) {
129 return;
130 }
131
132 if (!serviceIPs.contains(targetIp)) {
133 return;
134 }
135
136 Ethernet ethReply = ARP.buildArpReply(
137 targetIp,
138 DEFAULT_GATEWAY_MAC,
139 ethPacket);
140
141 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
142 .setOutput(context.inPacket().receivedFrom().port())
143 .build();
144
145 packetService.emit(new DefaultOutboundPacket(
146 context.inPacket().receivedFrom().deviceId(),
147 treatment,
148 ByteBuffer.wrap(ethReply.serialize())));
149
150 context.block();
151 }
152}