blob: 0a916d8c20f82cb008d87e15b0b10c852e78c1ca [file] [log] [blame]
Daniel Park81a61a12016-02-26 08:24:44 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
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 */
Hyunsun Moon05400872017-02-07 17:11:25 +090016package org.onosproject.openstacknetworking.impl;
Daniel Park81a61a12016-02-26 08:24:44 +090017
Jian Li60312252018-05-10 18:40:32 +090018import com.google.common.base.Strings;
Jian Li1064e4f2018-05-29 16:16:53 +090019import com.google.common.collect.ImmutableSet;
Jian Li60312252018-05-10 18:40:32 +090020import com.google.common.collect.Maps;
Jian Li1064e4f2018-05-29 16:16:53 +090021import com.google.common.collect.Sets;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070022import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
24import org.apache.felix.scr.annotations.Deactivate;
Jian Li60312252018-05-10 18:40:32 +090025import org.apache.felix.scr.annotations.Modified;
26import org.apache.felix.scr.annotations.Property;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070027import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
Daniel Park81a61a12016-02-26 08:24:44 +090029import org.onlab.packet.ARP;
Jian Li60312252018-05-10 18:40:32 +090030import org.onlab.packet.EthType;
Daniel Park81a61a12016-02-26 08:24:44 +090031import org.onlab.packet.Ethernet;
Daniel Park81a61a12016-02-26 08:24:44 +090032import org.onlab.packet.Ip4Address;
33import org.onlab.packet.IpAddress;
34import org.onlab.packet.MacAddress;
Jian Li60312252018-05-10 18:40:32 +090035import org.onosproject.cfg.ComponentConfigService;
Jian Li7f70bb72018-07-06 23:35:30 +090036import org.onosproject.cfg.ConfigProperty;
Jian Li60312252018-05-10 18:40:32 +090037import org.onosproject.cluster.ClusterService;
38import org.onosproject.cluster.LeadershipService;
39import org.onosproject.cluster.NodeId;
40import org.onosproject.core.ApplicationId;
41import org.onosproject.core.CoreService;
Jian Li14a79f22018-06-05 03:44:22 +090042import org.onosproject.net.ConnectPoint;
Hyunsun Moon0d457362017-06-27 17:19:41 +090043import org.onosproject.net.DeviceId;
daniel parkb5817102018-02-15 00:18:51 +090044import org.onosproject.net.PortNumber;
Jian Li60312252018-05-10 18:40:32 +090045import org.onosproject.net.flow.DefaultTrafficSelector;
Daniel Park81a61a12016-02-26 08:24:44 +090046import org.onosproject.net.flow.DefaultTrafficTreatment;
Jian Li60312252018-05-10 18:40:32 +090047import org.onosproject.net.flow.TrafficSelector;
Daniel Park81a61a12016-02-26 08:24:44 +090048import org.onosproject.net.flow.TrafficTreatment;
49import org.onosproject.net.packet.DefaultOutboundPacket;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070050import org.onosproject.net.packet.InboundPacket;
Daniel Park81a61a12016-02-26 08:24:44 +090051import org.onosproject.net.packet.PacketContext;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070052import org.onosproject.net.packet.PacketProcessor;
Daniel Park81a61a12016-02-26 08:24:44 +090053import org.onosproject.net.packet.PacketService;
Hyunsun Moon05400872017-02-07 17:11:25 +090054import org.onosproject.openstacknetworking.api.Constants;
Jian Li60312252018-05-10 18:40:32 +090055import org.onosproject.openstacknetworking.api.InstancePort;
Jian Li24ec59f2018-05-23 19:01:25 +090056import org.onosproject.openstacknetworking.api.InstancePortEvent;
57import org.onosproject.openstacknetworking.api.InstancePortListener;
Jian Li1064e4f2018-05-29 16:16:53 +090058import org.onosproject.openstacknetworking.api.InstancePortService;
Jian Li60312252018-05-10 18:40:32 +090059import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
daniel park32b42202018-03-14 16:53:44 +090060import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
Jian Lie1a39032018-06-19 21:49:36 +090061import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
62import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
Jian Li1064e4f2018-05-29 16:16:53 +090063import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
Jian Li60312252018-05-10 18:40:32 +090064import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
65import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
daniel parkeeb8e042018-02-21 14:06:58 +090066import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090067import org.onosproject.openstacknode.api.OpenstackNode;
Jian Lif96685c2018-05-21 14:14:16 +090068import org.onosproject.openstacknode.api.OpenstackNodeEvent;
69import org.onosproject.openstacknode.api.OpenstackNodeListener;
Hyunsun Moon0d457362017-06-27 17:19:41 +090070import org.onosproject.openstacknode.api.OpenstackNodeService;
Jian Li60312252018-05-10 18:40:32 +090071import org.openstack4j.model.network.ExternalGateway;
Jian Li4df657b2018-05-29 16:39:00 +090072import org.openstack4j.model.network.IP;
daniel parkeeb8e042018-02-21 14:06:58 +090073import org.openstack4j.model.network.NetFloatingIP;
Jian Li60312252018-05-10 18:40:32 +090074import org.openstack4j.model.network.Port;
75import org.openstack4j.model.network.Router;
Jian Li60312252018-05-10 18:40:32 +090076import org.osgi.service.component.ComponentContext;
Daniel Park81a61a12016-02-26 08:24:44 +090077import org.slf4j.Logger;
78
79import java.nio.ByteBuffer;
Jian Li60312252018-05-10 18:40:32 +090080import java.util.Map;
Hyunsun Moon44aac662017-02-18 02:07:01 +090081import java.util.Objects;
Hyunsun Moon0d457362017-06-27 17:19:41 +090082import java.util.Set;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070083import java.util.concurrent.ExecutorService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090084import java.util.stream.Collectors;
Daniel Park81a61a12016-02-26 08:24:44 +090085
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070086import static java.util.concurrent.Executors.newSingleThreadExecutor;
87import static org.onlab.util.Tools.groupedThreads;
Jian Li60312252018-05-10 18:40:32 +090088import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
89import static org.onosproject.openstacknetworking.api.Constants.ARP_PROXY_MODE;
90import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_ARP_MODE_STR;
91import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
92import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
93import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
Jian Lif96685c2018-05-21 14:14:16 +090094import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_CONTROL_RULE;
Jian Li60312252018-05-10 18:40:32 +090095import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Jian Li24ec59f2018-05-23 19:01:25 +090096import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
97import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
Jian Lia171a432018-06-11 11:52:11 +090098import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort;
Jian Li7f70bb72018-07-06 23:35:30 +090099import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
Jian Li24ec59f2018-05-23 19:01:25 +0900100import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900101import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Daniel Park81a61a12016-02-26 08:24:44 +0900102import static org.slf4j.LoggerFactory.getLogger;
103
104/**
Hyunsun Moon44aac662017-02-18 02:07:01 +0900105 * Handle ARP requests from gateway nodes.
Daniel Park81a61a12016-02-26 08:24:44 +0900106 */
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700107@Component(immediate = true)
Daniel Park81a61a12016-02-26 08:24:44 +0900108public class OpenstackRoutingArpHandler {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900109
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700110 private final Logger log = getLogger(getClass());
Daniel Park81a61a12016-02-26 08:24:44 +0900111
Hyunsun Moon44aac662017-02-18 02:07:01 +0900112 private static final String DEVICE_OWNER_ROUTER_GW = "network:router_gateway";
113 private static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip";
Jian Li60312252018-05-10 18:40:32 +0900114 private static final String ARP_MODE = "arpMode";
115
116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 protected CoreService coreService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900118
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 protected PacketService packetService;
Daniel Park81a61a12016-02-26 08:24:44 +0900121
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
daniel park32b42202018-03-14 16:53:44 +0900123 protected OpenstackNetworkAdminService osNetworkAdminService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700124
Hyunsun Moon44aac662017-02-18 02:07:01 +0900125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
daniel parkeeb8e042018-02-21 14:06:58 +0900126 protected OpenstackRouterService osRouterService;
127
daniel parkeeb8e042018-02-21 14:06:58 +0900128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
daniel parke49eb382017-04-05 16:48:28 +0900129 protected OpenstackNodeService osNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900130
Jian Li60312252018-05-10 18:40:32 +0900131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Li1064e4f2018-05-29 16:16:53 +0900132 protected InstancePortService instancePortService;
133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Li60312252018-05-10 18:40:32 +0900135 protected ClusterService clusterService;
136
137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
138 protected LeadershipService leadershipService;
139
140 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
141 protected OpenstackFlowRuleService osFlowRuleService;
142
143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Li1064e4f2018-05-29 16:16:53 +0900144 protected OpenstackNetworkService osNetworkService;
145
146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Lif3a28b02018-06-11 21:29:13 +0900147 protected ComponentConfigService configService;
Jian Li60312252018-05-10 18:40:32 +0900148
Jian Li60312252018-05-10 18:40:32 +0900149 @Property(name = ARP_MODE, value = DEFAULT_ARP_MODE_STR,
Daniel Park6041f102018-07-06 18:49:45 +0900150 label = "ARP processing mode, broadcast | proxy (default)")
Jian Li60312252018-05-10 18:40:32 +0900151 protected String arpMode = DEFAULT_ARP_MODE_STR;
152
153 protected String gatewayMac = DEFAULT_GATEWAY_MAC_STR;
154
155 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
Jian Lif96685c2018-05-21 14:14:16 +0900156 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
Jian Li24ec59f2018-05-23 19:01:25 +0900157 private final InstancePortListener instPortListener = new InternalInstancePortListener();
Jian Li60312252018-05-10 18:40:32 +0900158
Jian Lie1a39032018-06-19 21:49:36 +0900159 private final OpenstackNetworkListener osNetworkListener = new InternalOpenstackNetworkListener();
160
Jian Li60312252018-05-10 18:40:32 +0900161 private ApplicationId appId;
162 private NodeId localNodeId;
Jian Lie1a39032018-06-19 21:49:36 +0900163 private final Map<String, MacAddress> floatingIpMacMap = Maps.newConcurrentMap();
164 private final Map<String, DeviceId> migrationPool = Maps.newConcurrentMap();
165 private final Map<MacAddress, InstancePort> terminatedInstPorts = Maps.newConcurrentMap();
166 private final Map<MacAddress, InstancePort> tobeRemovedInstPorts = Maps.newConcurrentMap();
167 private final Map<String, NetFloatingIP> pendingInstPortIds = Maps.newConcurrentMap();
Jian Li60312252018-05-10 18:40:32 +0900168
Hyunsun Moon44aac662017-02-18 02:07:01 +0900169 private final ExecutorService eventExecutor = newSingleThreadExecutor(
170 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700171
Hyunsun Moon0d457362017-06-27 17:19:41 +0900172 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700173
174 @Activate
175 protected void activate() {
Jian Li60312252018-05-10 18:40:32 +0900176 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
177 configService.registerProperties(getClass());
178 localNodeId = clusterService.getLocalNode().id();
Jian Lif3a28b02018-06-11 21:29:13 +0900179 osRouterService.addListener(osRouterListener);
Jian Lif96685c2018-05-21 14:14:16 +0900180 osNodeService.addListener(osNodeListener);
Jian Lie1a39032018-06-19 21:49:36 +0900181 osNetworkService.addListener(osNetworkListener);
Jian Li24ec59f2018-05-23 19:01:25 +0900182 instancePortService.addListener(instPortListener);
Jian Li60312252018-05-10 18:40:32 +0900183 leadershipService.runForLeadership(appId.name());
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700184 packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
185 log.info("Started");
Daniel Park81a61a12016-02-26 08:24:44 +0900186 }
187
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700188 @Deactivate
189 protected void deactivate() {
190 packetService.removeProcessor(packetProcessor);
Jian Lie1a39032018-06-19 21:49:36 +0900191 instancePortService.removeListener(instPortListener);
Jian Li60312252018-05-10 18:40:32 +0900192 osRouterService.removeListener(osRouterListener);
Jian Lif96685c2018-05-21 14:14:16 +0900193 osNodeService.removeListener(osNodeListener);
Jian Li24ec59f2018-05-23 19:01:25 +0900194 instancePortService.removeListener(instPortListener);
Jian Lie1a39032018-06-19 21:49:36 +0900195 osNetworkService.removeListener(osNetworkListener);
Jian Li60312252018-05-10 18:40:32 +0900196 leadershipService.withdraw(appId.name());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900197 eventExecutor.shutdown();
Jian Li60312252018-05-10 18:40:32 +0900198 configService.unregisterProperties(getClass(), false);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700199 log.info("Stopped");
Daniel Park81a61a12016-02-26 08:24:44 +0900200 }
201
Jian Li60312252018-05-10 18:40:32 +0900202 @Modified
203 void modified(ComponentContext context) {
Jian Li60312252018-05-10 18:40:32 +0900204 log.info("Modified");
205 }
206
Jian Li7f70bb72018-07-06 23:35:30 +0900207 private String getArpMode() {
208 Set<ConfigProperty> properties = configService.getProperties(this.getClass().getName());
209 return getPropertyValue(properties, ARP_MODE);
210 }
211
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700212 private void processArpPacket(PacketContext context, Ethernet ethernet) {
Daniel Park81a61a12016-02-26 08:24:44 +0900213 ARP arp = (ARP) ethernet.getPayload();
Jian Li60312252018-05-10 18:40:32 +0900214
Jian Li7f70bb72018-07-06 23:35:30 +0900215 if (arp.getOpCode() == ARP.OP_REQUEST && ARP_PROXY_MODE.equals(getArpMode())) {
daniel parkb5817102018-02-15 00:18:51 +0900216 if (log.isTraceEnabled()) {
217 log.trace("ARP request received from {} for {}",
218 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
219 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
220 }
221
222 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
daniel parkeeb8e042018-02-21 14:06:58 +0900223
224 MacAddress targetMac = null;
225
226 NetFloatingIP floatingIP = osRouterService.floatingIps().stream()
227 .filter(ip -> ip.getFloatingIpAddress().equals(targetIp.toString()))
228 .findAny().orElse(null);
229
daniel park576969a2018-03-09 07:07:41 +0900230 //In case target ip is for associated floating ip, sets target mac to vm's.
daniel parkeeb8e042018-02-21 14:06:58 +0900231 if (floatingIP != null && floatingIP.getPortId() != null) {
Jian Li60312252018-05-10 18:40:32 +0900232 targetMac = MacAddress.valueOf(osNetworkAdminService.port(
233 floatingIP.getPortId()).getMacAddress());
daniel parkeeb8e042018-02-21 14:06:58 +0900234 }
235
236 if (isExternalGatewaySourceIp(targetIp.getIp4Address())) {
237 targetMac = Constants.DEFAULT_GATEWAY_MAC;
238 }
239
240 if (targetMac == null) {
daniel parkb5817102018-02-15 00:18:51 +0900241 log.trace("Unknown target ARP request for {}, ignore it", targetIp);
242 return;
243 }
244
Jian Lia171a432018-06-11 11:52:11 +0900245 InstancePort instPort = instancePortService.instancePort(targetMac);
246
247 OpenstackNode gw = getGwByInstancePort(osNodeService.completeNodes(GATEWAY), instPort);
Jian Li1064e4f2018-05-29 16:16:53 +0900248
249 if (gw == null) {
250 return;
251 }
252
253 // if the ARP packet_in received from non-relevant GWs, we simply ignore it
254 if (!Objects.equals(gw.intgBridge(), context.inPacket().receivedFrom().deviceId())) {
255 return;
256 }
257
daniel parkb5817102018-02-15 00:18:51 +0900258 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
259 targetMac, ethernet);
260
261 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
daniel park576969a2018-03-09 07:07:41 +0900262 .setOutput(context.inPacket().receivedFrom().port()).build();
daniel parkb5817102018-02-15 00:18:51 +0900263
264 packetService.emit(new DefaultOutboundPacket(
265 context.inPacket().receivedFrom().deviceId(),
266 treatment,
267 ByteBuffer.wrap(ethReply.serialize())));
268
269 context.block();
Jian Li60312252018-05-10 18:40:32 +0900270 }
271
272 if (arp.getOpCode() == ARP.OP_REPLY) {
Jian Li14a79f22018-06-05 03:44:22 +0900273 ConnectPoint cp = context.inPacket().receivedFrom();
274 PortNumber receivedPortNum = cp.port();
275 IpAddress spa = Ip4Address.valueOf(arp.getSenderProtocolAddress());
276 MacAddress sha = MacAddress.valueOf(arp.getSenderHardwareAddress());
277
278 log.debug("ARP reply ip: {}, mac: {}", spa, sha);
279
daniel parkb5817102018-02-15 00:18:51 +0900280 try {
Jian Li14a79f22018-06-05 03:44:22 +0900281
Jian Lid4066ea2018-06-07 01:44:45 +0900282 Set<String> extRouterIps = osNetworkService.externalPeerRouters().
283 stream().map(r -> r.externalPeerRouterIp().toString()).collect(Collectors.toSet());
Jian Li14a79f22018-06-05 03:44:22 +0900284
Jian Lid4066ea2018-06-07 01:44:45 +0900285 // if SPA is NOT contained in existing external router IP set, we ignore it
286 if (!extRouterIps.contains(spa.toString())) {
Jian Li14a79f22018-06-05 03:44:22 +0900287 return;
288 }
289
290 OpenstackNode node = osNodeService.node(cp.deviceId());
291
292 if (node == null) {
293 return;
294 }
295
296 // we only handles the ARP-Reply message received by gateway node
297 if (node.type() != GATEWAY) {
298 return;
299 }
300
301 if (receivedPortNum.equals(node.uplinkPortNum())) {
302 osNetworkAdminService.updateExternalPeerRouterMac(spa, sha);
daniel parkb5817102018-02-15 00:18:51 +0900303 }
304 } catch (Exception e) {
Jian Li14a79f22018-06-05 03:44:22 +0900305 log.error("Exception occurred because of {}", e);
daniel parkb5817102018-02-15 00:18:51 +0900306 }
Daniel Park81a61a12016-02-26 08:24:44 +0900307 }
Daniel Park81a61a12016-02-26 08:24:44 +0900308 }
309
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700310 private class InternalPacketProcessor implements PacketProcessor {
311
312 @Override
313 public void process(PacketContext context) {
314 if (context.isHandled()) {
315 return;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900316 }
317
318 Set<DeviceId> gateways = osNodeService.completeNodes(GATEWAY)
319 .stream().map(OpenstackNode::intgBridge)
320 .collect(Collectors.toSet());
321
322 if (!gateways.contains(context.inPacket().receivedFrom().deviceId())) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700323 // return if the packet is not from gateway nodes
324 return;
325 }
326
327 InboundPacket pkt = context.inPacket();
328 Ethernet ethernet = pkt.parsed();
329 if (ethernet != null &&
330 ethernet.getEtherType() == Ethernet.TYPE_ARP) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900331 eventExecutor.execute(() -> processArpPacket(context, ethernet));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700332 }
333 }
334 }
335
daniel parkeeb8e042018-02-21 14:06:58 +0900336 private boolean isExternalGatewaySourceIp(IpAddress targetIp) {
daniel park32b42202018-03-14 16:53:44 +0900337 return osNetworkAdminService.ports().stream()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900338 .filter(osPort -> Objects.equals(osPort.getDeviceOwner(),
daniel parkeeb8e042018-02-21 14:06:58 +0900339 DEVICE_OWNER_ROUTER_GW))
Hyunsun Moon44aac662017-02-18 02:07:01 +0900340 .flatMap(osPort -> osPort.getFixedIps().stream())
341 .anyMatch(ip -> IpAddress.valueOf(ip.getIpAddress()).equals(targetIp));
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +0900342 }
Jian Li60312252018-05-10 18:40:32 +0900343
Jian Li60312252018-05-10 18:40:32 +0900344 private void initFloatingIpMacMap() {
345 osRouterService.floatingIps().forEach(f -> {
346 if (f.getPortId() != null && f.getFloatingIpAddress() != null) {
347 Port port = osNetworkAdminService.port(f.getPortId());
348 if (port != null && port.getMacAddress() != null) {
Jian Lif3a28b02018-06-11 21:29:13 +0900349 floatingIpMacMap.put(f.getFloatingIpAddress(),
350 MacAddress.valueOf(port.getMacAddress()));
Jian Li60312252018-05-10 18:40:32 +0900351 }
352 }
353 });
354 }
355
Jian Lie1a39032018-06-19 21:49:36 +0900356 private void initPendingInstPorts() {
357 osRouterService.floatingIps().forEach(f -> {
358 if (f.getPortId() != null) {
359 Port port = osNetworkAdminService.port(f.getPortId());
360 if (port != null) {
361 if (!Strings.isNullOrEmpty(port.getDeviceId()) &&
362 instancePortService.instancePort(f.getPortId()) == null) {
363 pendingInstPortIds.put(f.getPortId(), f);
364 }
365 }
366 }
367 });
368 }
369
Jian Li60312252018-05-10 18:40:32 +0900370 /**
371 * Installs static ARP rules used in ARP BROAD_CAST mode.
Jian Li1064e4f2018-05-29 16:16:53 +0900372 *
373 * @param gateway gateway node
374 * @param install flow rule installation flag
375 */
376 private void setFloatingIpArpRuleForGateway(OpenstackNode gateway, boolean install) {
Jian Li7f70bb72018-07-06 23:35:30 +0900377 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
Jian Li1064e4f2018-05-29 16:16:53 +0900378
379 Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
380 Set<OpenstackNode> finalGws = Sets.newConcurrentHashSet();
381 finalGws.addAll(ImmutableSet.copyOf(completedGws));
382
383 if (install) {
384 if (completedGws.contains(gateway)) {
385 if (completedGws.size() > 1) {
386 finalGws.remove(gateway);
387 osRouterService.floatingIps().forEach(fip -> {
388 if (fip.getPortId() != null) {
389 setFloatingIpArpRule(fip, finalGws, false);
390 finalGws.add(gateway);
391 }
392 });
393 }
394 osRouterService.floatingIps().forEach(fip -> {
395 if (fip.getPortId() != null) {
396 setFloatingIpArpRule(fip, finalGws, true);
397 }
398 });
399 } else {
400 log.warn("Detected node should be included in completed gateway set");
401 }
402 } else {
403 if (!completedGws.contains(gateway)) {
404 finalGws.add(gateway);
405 osRouterService.floatingIps().forEach(fip -> {
406 if (fip.getPortId() != null) {
407 setFloatingIpArpRule(fip, finalGws, false);
408 }
409 });
410 finalGws.remove(gateway);
411 if (completedGws.size() >= 1) {
412 osRouterService.floatingIps().forEach(fip -> {
413 if (fip.getPortId() != null) {
414 setFloatingIpArpRule(fip, finalGws, true);
415 }
416 });
417 }
418 } else {
419 log.warn("Detected node should NOT be included in completed gateway set");
420 }
421 }
422 }
423 }
424
425 /**
Jian Li24ec59f2018-05-23 19:01:25 +0900426 * Installs/uninstalls ARP flow rules to the corresponding gateway by
427 * looking for compute node's device ID.
428 *
429 * @param fip floating IP
430 * @param port instance port
431 * @param gateways a collection of gateways
432 * @param install install flag
433 */
434 private void setFloatingIpArpRuleWithPortEvent(NetFloatingIP fip,
435 InstancePort port,
436 Set<OpenstackNode> gateways,
437 boolean install) {
Jian Li7f70bb72018-07-06 23:35:30 +0900438 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
Jian Li24ec59f2018-05-23 19:01:25 +0900439
440 OpenstackNode gw = getGwByInstancePort(gateways, port);
441
442 if (gw == null) {
443 return;
444 }
445
446 String macString = osNetworkAdminService.port(fip.getPortId()).getMacAddress();
447
448 setArpRule(fip, MacAddress.valueOf(macString), gw, install);
449 }
450 }
451
452 /**
Jian Li1064e4f2018-05-29 16:16:53 +0900453 * Installs static ARP rules used in ARP BROAD_CAST mode.
Jian Li60312252018-05-10 18:40:32 +0900454 * Note that, those rules will be only matched ARP_REQUEST packets,
455 * used for telling gateway node the mapped MAC address of requested IP,
456 * without the helps from controller.
457 *
458 * @param fip floating IP address
Jian Li1064e4f2018-05-29 16:16:53 +0900459 * @param gateways a set of gateway nodes
Jian Li60312252018-05-10 18:40:32 +0900460 * @param install flow rule installation flag
461 */
Jian Li1064e4f2018-05-29 16:16:53 +0900462 private synchronized void setFloatingIpArpRule(NetFloatingIP fip,
463 Set<OpenstackNode> gateways,
464 boolean install) {
Jian Li7f70bb72018-07-06 23:35:30 +0900465 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
Jian Li60312252018-05-10 18:40:32 +0900466
467 if (fip == null) {
468 log.warn("Failed to set ARP broadcast rule for floating IP");
469 return;
470 }
471
Jian Lif3a28b02018-06-11 21:29:13 +0900472 MacAddress targetMac;
473 InstancePort instPort;
Jian Li60312252018-05-10 18:40:32 +0900474
475 if (install) {
476 if (fip.getPortId() != null) {
Jian Lif3a28b02018-06-11 21:29:13 +0900477 String macString = osNetworkAdminService.port(fip.getPortId()).getMacAddress();
478 targetMac = MacAddress.valueOf(macString);
479 floatingIpMacMap.put(fip.getFloatingIpAddress(), targetMac);
Jian Li60312252018-05-10 18:40:32 +0900480 } else {
481 log.trace("Unknown target ARP request for {}, ignore it",
482 fip.getFloatingIpAddress());
483 return;
484 }
485 } else {
Jian Lif3a28b02018-06-11 21:29:13 +0900486 targetMac = floatingIpMacMap.get(fip.getFloatingIpAddress());
Jian Li60312252018-05-10 18:40:32 +0900487 }
488
Jian Lif3a28b02018-06-11 21:29:13 +0900489 instPort = instancePortService.instancePort(targetMac);
490
491 // in VM purge case, we will have null instance port
492 if (instPort == null) {
Jian Lie1a39032018-06-19 21:49:36 +0900493 instPort = tobeRemovedInstPorts.get(targetMac);
494 tobeRemovedInstPorts.remove(targetMac);
495 }
496
497 if (instPort == null) {
498 instPort = terminatedInstPorts.get(targetMac);
Jian Lif3a28b02018-06-11 21:29:13 +0900499 }
Jian Li60312252018-05-10 18:40:32 +0900500
Jian Lia171a432018-06-11 11:52:11 +0900501 OpenstackNode gw = getGwByInstancePort(gateways, instPort);
Jian Li1064e4f2018-05-29 16:16:53 +0900502
503 if (gw == null) {
504 return;
505 }
506
Jian Li24ec59f2018-05-23 19:01:25 +0900507 setArpRule(fip, targetMac, gw, install);
508 }
509 }
Jian Li60312252018-05-10 18:40:32 +0900510
Jian Li24ec59f2018-05-23 19:01:25 +0900511 private void setArpRule(NetFloatingIP fip, MacAddress targetMac,
512 OpenstackNode gateway, boolean install) {
513 TrafficSelector selector = DefaultTrafficSelector.builder()
514 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
515 .matchArpOp(ARP.OP_REQUEST)
516 .matchArpTpa(Ip4Address.valueOf(fip.getFloatingIpAddress()))
517 .build();
Jian Li60312252018-05-10 18:40:32 +0900518
Jian Li24ec59f2018-05-23 19:01:25 +0900519 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
520 .setArpOp(ARP.OP_REPLY)
521 .setArpSha(targetMac)
522 .setArpSpa(Ip4Address.valueOf(fip.getFloatingIpAddress()))
523 .setOutput(PortNumber.IN_PORT)
524 .build();
Jian Li60312252018-05-10 18:40:32 +0900525
Jian Li24ec59f2018-05-23 19:01:25 +0900526 osFlowRuleService.setRule(
527 appId,
528 gateway.intgBridge(),
529 selector,
530 treatment,
531 PRIORITY_ARP_GATEWAY_RULE,
532 GW_COMMON_TABLE,
533 install
534 );
535
536 if (install) {
537 log.info("Install ARP Rule for Floating IP {}",
538 fip.getFloatingIpAddress());
539 } else {
540 log.info("Uninstall ARP Rule for Floating IP {}",
541 fip.getFloatingIpAddress());
Jian Li60312252018-05-10 18:40:32 +0900542 }
543 }
544
545 /**
546 * An internal router event listener, intended to install/uninstall
547 * ARP rules for forwarding packets created from floating IPs.
548 */
549 private class InternalRouterEventListener implements OpenstackRouterListener {
550
551 @Override
552 public boolean isRelevant(OpenstackRouterEvent event) {
553 // do not allow to proceed without leadership
554 NodeId leader = leadershipService.getLeader(appId.name());
555 return Objects.equals(localNodeId, leader);
556 }
557
558 @Override
559 public void event(OpenstackRouterEvent event) {
Jian Li1064e4f2018-05-29 16:16:53 +0900560
561 Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
562
Jian Li60312252018-05-10 18:40:32 +0900563 switch (event.type()) {
564 case OPENSTACK_ROUTER_CREATED:
565 eventExecutor.execute(() ->
566 // add a router with external gateway
567 setFakeGatewayArpRule(event.subject(), true)
568 );
569 break;
570 case OPENSTACK_ROUTER_REMOVED:
571 eventExecutor.execute(() ->
572 // remove a router with external gateway
573 setFakeGatewayArpRule(event.subject(), false)
574 );
575 break;
576 case OPENSTACK_ROUTER_GATEWAY_ADDED:
577 eventExecutor.execute(() ->
578 // add a gateway manually after adding a router
579 setFakeGatewayArpRule(event.externalGateway(), true)
580 );
581 break;
582 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
583 eventExecutor.execute(() ->
584 // remove a gateway from an existing router
585 setFakeGatewayArpRule(event.externalGateway(), false)
586 );
587 break;
588 case OPENSTACK_FLOATING_IP_ASSOCIATED:
Jian Lie1a39032018-06-19 21:49:36 +0900589
590 if (instancePortService.instancePort(event.portId()) == null) {
591 log.info("Try to associate the fip {} with a terminated VM",
592 event.floatingIp().getFloatingIpAddress());
593 pendingInstPortIds.put(event.portId(), event.floatingIp());
594 return;
595 }
596
Jian Li60312252018-05-10 18:40:32 +0900597 eventExecutor.execute(() ->
598 // associate a floating IP with an existing VM
Jian Li1064e4f2018-05-29 16:16:53 +0900599 setFloatingIpArpRule(event.floatingIp(), completedGws, true)
Jian Li60312252018-05-10 18:40:32 +0900600 );
601 break;
602 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
Jian Lie1a39032018-06-19 21:49:36 +0900603
604 MacAddress mac = floatingIpMacMap.get(event.floatingIp().getFloatingIpAddress());
605
606 if (mac != null && !tobeRemovedInstPorts.containsKey(mac) &&
607 terminatedInstPorts.containsKey(mac)) {
608 tobeRemovedInstPorts.put(mac, terminatedInstPorts.get(mac));
609 }
610
611 if (instancePortService.instancePort(event.portId()) == null) {
612
613 if (pendingInstPortIds.containsKey(event.portId())) {
614 log.info("Try to disassociate the fip {} with a terminated VM",
615 event.floatingIp().getFloatingIpAddress());
616 pendingInstPortIds.remove(event.portId());
617 return;
618 }
619 }
620
Jian Li60312252018-05-10 18:40:32 +0900621 eventExecutor.execute(() ->
622 // disassociate a floating IP with the existing VM
Jian Li1064e4f2018-05-29 16:16:53 +0900623 setFloatingIpArpRule(event.floatingIp(), completedGws, false)
Jian Li60312252018-05-10 18:40:32 +0900624 );
625 break;
626 case OPENSTACK_FLOATING_IP_CREATED:
627 eventExecutor.execute(() -> {
628 NetFloatingIP osFip = event.floatingIp();
629
630 // during floating IP creation, if the floating IP is
631 // associated with any port of VM, then we will set
632 // floating IP related ARP rules to gateway node
633 if (!Strings.isNullOrEmpty(osFip.getPortId())) {
Jian Li1064e4f2018-05-29 16:16:53 +0900634 setFloatingIpArpRule(osFip, completedGws, true);
Jian Li60312252018-05-10 18:40:32 +0900635 }
636 });
637 break;
638 case OPENSTACK_FLOATING_IP_REMOVED:
639 eventExecutor.execute(() -> {
640 NetFloatingIP osFip = event.floatingIp();
641
642 // during floating IP deletion, if the floating IP is
643 // still associated with any port of VM, then we will
644 // remove floating IP related ARP rules from gateway node
645 if (!Strings.isNullOrEmpty(osFip.getPortId())) {
Jian Li1064e4f2018-05-29 16:16:53 +0900646 setFloatingIpArpRule(event.floatingIp(), completedGws, false);
Jian Li60312252018-05-10 18:40:32 +0900647 }
648 });
649 break;
650 default:
651 // do nothing for the other events
652 break;
653 }
654 }
655
Jian Li4df657b2018-05-29 16:39:00 +0900656 private Set<IP> getExternalGatewaySnatIps(ExternalGateway extGw) {
657 return osNetworkAdminService.ports().stream()
658 .filter(port ->
659 Objects.equals(port.getNetworkId(), extGw.getNetworkId()))
660 .filter(port ->
661 Objects.equals(port.getDeviceOwner(), DEVICE_OWNER_ROUTER_GW))
662 .flatMap(port -> port.getFixedIps().stream())
663 .collect(Collectors.toSet());
664 }
665
Jian Li60312252018-05-10 18:40:32 +0900666 private void setFakeGatewayArpRule(ExternalGateway extGw, boolean install) {
Jian Li7f70bb72018-07-06 23:35:30 +0900667 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
Jian Li60312252018-05-10 18:40:32 +0900668
669 if (extGw == null) {
670 return;
671 }
672
Jian Li4df657b2018-05-29 16:39:00 +0900673 Set<IP> ips = getExternalGatewaySnatIps(extGw);
Jian Li60312252018-05-10 18:40:32 +0900674
Jian Li4df657b2018-05-29 16:39:00 +0900675 ips.forEach(ip -> {
676 TrafficSelector selector = DefaultTrafficSelector.builder()
677 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
678 .matchArpOp(ARP.OP_REQUEST)
679 .matchArpTpa(Ip4Address.valueOf(ip.getIpAddress()))
680 .build();
Jian Li60312252018-05-10 18:40:32 +0900681
Jian Li4df657b2018-05-29 16:39:00 +0900682 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
683 .setArpOp(ARP.OP_REPLY)
684 .setArpSha(MacAddress.valueOf(gatewayMac))
685 .setArpSpa(Ip4Address.valueOf(ip.getIpAddress()))
686 .setOutput(PortNumber.IN_PORT)
687 .build();
Jian Li60312252018-05-10 18:40:32 +0900688
Jian Li4df657b2018-05-29 16:39:00 +0900689 osNodeService.completeNodes(GATEWAY).forEach(n ->
690 osFlowRuleService.setRule(
691 appId,
692 n.intgBridge(),
693 selector,
694 treatment,
695 PRIORITY_ARP_GATEWAY_RULE,
696 GW_COMMON_TABLE,
697 install
698 )
699 );
Jian Li60312252018-05-10 18:40:32 +0900700
Jian Li4df657b2018-05-29 16:39:00 +0900701 if (install) {
702 log.info("Install ARP Rule for Gateway Snat {}", ip.getIpAddress());
703 } else {
704 log.info("Uninstall ARP Rule for Gateway Snat {}", ip.getIpAddress());
705 }
706 });
Jian Li60312252018-05-10 18:40:32 +0900707 }
708 }
709
710 private void setFakeGatewayArpRule(Router router, boolean install) {
711 setFakeGatewayArpRule(router.getExternalGatewayInfo(), install);
712 }
713 }
714
Jian Lie1a39032018-06-19 21:49:36 +0900715 private class InternalInstancePortListener implements InstancePortListener {
Jian Li60312252018-05-10 18:40:32 +0900716
717 @Override
Jian Lie1a39032018-06-19 21:49:36 +0900718 public boolean isRelevant(InstancePortEvent event) {
719 // do not allow to proceed without leadership
720 NodeId leader = leadershipService.getLeader(appId.name());
721 return Objects.equals(localNodeId, leader);
Jian Li60312252018-05-10 18:40:32 +0900722 }
723
724 @Override
Jian Lie1a39032018-06-19 21:49:36 +0900725 public void event(InstancePortEvent event) {
726 InstancePort instPort = event.subject();
727
728 Set<NetFloatingIP> ips = osRouterService.floatingIps();
729 NetFloatingIP fip = associatedFloatingIp(instPort, ips);
730 Set<OpenstackNode> gateways = osNodeService.completeNodes(GATEWAY);
731
Jian Li60312252018-05-10 18:40:32 +0900732 switch (event.type()) {
Jian Lie1a39032018-06-19 21:49:36 +0900733 case OPENSTACK_INSTANCE_PORT_DETECTED:
734 terminatedInstPorts.remove(instPort.macAddress());
735
736 if (pendingInstPortIds.containsKey(instPort.portId())) {
737 Set<OpenstackNode> completedGws =
738 osNodeService.completeNodes(GATEWAY);
739 setFloatingIpArpRule(pendingInstPortIds.get(instPort.portId()),
740 completedGws, true);
741 pendingInstPortIds.remove(instPort.portId());
742 }
743
Jian Li60312252018-05-10 18:40:32 +0900744 break;
Jian Lie1a39032018-06-19 21:49:36 +0900745
746 case OPENSTACK_INSTANCE_PORT_VANISHED:
747 terminatedInstPorts.put(instPort.macAddress(), instPort);
748 break;
749
750 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
751
752 if (gateways.size() == 1) {
753 return;
754 }
755
756 if (fip != null && isAssociatedWithVM(osNetworkService, fip)) {
757 migrationPool.put(fip.getFloatingIpAddress(), event.subject().deviceId());
758
759 eventExecutor.execute(() -> {
760 setFloatingIpArpRuleWithPortEvent(fip, event.subject(),
761 gateways, true);
762 });
763 }
764
765 break;
766 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
767
768 if (gateways.size() == 1) {
769 return;
770 }
771
772 if (fip != null && isAssociatedWithVM(osNetworkService, fip)) {
773 DeviceId newDeviceId = migrationPool.get(fip.getFloatingIpAddress());
774 DeviceId oldDeviceId = event.subject().deviceId();
775 migrationPool.remove(fip.getFloatingIpAddress());
776
777 OpenstackNode oldGw = getGwByComputeDevId(gateways, oldDeviceId);
778 OpenstackNode newGw = getGwByComputeDevId(gateways, newDeviceId);
779
780 if (oldGw != null && oldGw.equals(newGw)) {
781 return;
782 }
783
784 eventExecutor.execute(() ->
785 setFloatingIpArpRuleWithPortEvent(fip, event.subject(),
786 gateways, false));
787 }
788 break;
Jian Li60312252018-05-10 18:40:32 +0900789 default:
790 break;
791 }
792 }
Jian Lie1a39032018-06-19 21:49:36 +0900793 }
Jian Li60312252018-05-10 18:40:32 +0900794
Jian Lie1a39032018-06-19 21:49:36 +0900795 private class InternalOpenstackNetworkListener implements OpenstackNetworkListener {
796
797 @Override
798 public boolean isRelevant(OpenstackNetworkEvent event) {
799 // do not allow to proceed without leadership
800 NodeId leader = leadershipService.getLeader(appId.name());
801 return Objects.equals(localNodeId, leader);
Jian Li60312252018-05-10 18:40:32 +0900802 }
803
Jian Lie1a39032018-06-19 21:49:36 +0900804 @Override
805 public void event(OpenstackNetworkEvent event) {
806 switch (event.type()) {
807 case OPENSTACK_PORT_REMOVED:
808 Port osPort = event.port();
809 MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
810 if (terminatedInstPorts.containsKey(mac)) {
811 tobeRemovedInstPorts.put(mac, terminatedInstPorts.get(mac));
812 terminatedInstPorts.remove(mac);
813 }
814 break;
815 default:
816 break;
817 }
Jian Li60312252018-05-10 18:40:32 +0900818 }
819 }
Jian Lif96685c2018-05-21 14:14:16 +0900820
821 private class InternalNodeEventListener implements OpenstackNodeListener {
822
823 @Override
824 public boolean isRelevant(OpenstackNodeEvent event) {
825 // do not allow to proceed without leadership
826 NodeId leader = leadershipService.getLeader(appId.name());
Jian Li51b844c2018-05-31 10:59:03 +0900827 return Objects.equals(localNodeId, leader) && event.subject().type() == GATEWAY;
Jian Lif96685c2018-05-21 14:14:16 +0900828 }
829
830 @Override
831 public void event(OpenstackNodeEvent event) {
832 OpenstackNode osNode = event.subject();
833 switch (event.type()) {
834 case OPENSTACK_NODE_COMPLETE:
Jian Li51b844c2018-05-31 10:59:03 +0900835 setDefaultArpRule(osNode, true);
836 setFloatingIpArpRuleForGateway(osNode, true);
Jian Li1064e4f2018-05-29 16:16:53 +0900837
Jian Lif3a28b02018-06-11 21:29:13 +0900838 // initialize FloatingIp to Mac map
839 initFloatingIpMacMap();
840
Jian Lie1a39032018-06-19 21:49:36 +0900841 // initialize pendingInstPorts
842 initPendingInstPorts();
843
Jian Lif96685c2018-05-21 14:14:16 +0900844 break;
845 case OPENSTACK_NODE_INCOMPLETE:
Jian Li51b844c2018-05-31 10:59:03 +0900846 setDefaultArpRule(osNode, false);
847 setFloatingIpArpRuleForGateway(osNode, false);
Jian Lif96685c2018-05-21 14:14:16 +0900848 break;
849 default:
850 break;
851 }
852 }
853
854 private void setDefaultArpRule(OpenstackNode osNode, boolean install) {
Jian Li7f70bb72018-07-06 23:35:30 +0900855 switch (getArpMode()) {
Jian Lif96685c2018-05-21 14:14:16 +0900856 case ARP_PROXY_MODE:
857 setDefaultArpRuleForProxyMode(osNode, install);
858 break;
859 case ARP_BROADCAST_MODE:
860 setDefaultArpRuleForBroadcastMode(osNode, install);
861 break;
862 default:
863 log.warn("Invalid ARP mode {}. Please use either " +
Jian Li7f70bb72018-07-06 23:35:30 +0900864 "broadcast or proxy mode.", getArpMode());
Jian Lif96685c2018-05-21 14:14:16 +0900865 break;
866 }
867 }
868
869 private void setDefaultArpRuleForProxyMode(OpenstackNode osNode, boolean install) {
870 TrafficSelector selector = DefaultTrafficSelector.builder()
871 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
872 .build();
873
874 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
875 .punt()
876 .build();
877
878 osFlowRuleService.setRule(
879 appId,
880 osNode.intgBridge(),
881 selector,
882 treatment,
883 PRIORITY_ARP_CONTROL_RULE,
Jian Li8abf2fe2018-06-12 18:42:30 +0900884 GW_COMMON_TABLE,
Jian Lif96685c2018-05-21 14:14:16 +0900885 install
886 );
887 }
888
889 private void setDefaultArpRuleForBroadcastMode(OpenstackNode osNode, boolean install) {
890 // we only match ARP_REPLY in gateway node, because controller
891 // somehow need to process ARP_REPLY which is issued from
892 // external router...
893 TrafficSelector selector = DefaultTrafficSelector.builder()
894 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
895 .matchArpOp(ARP.OP_REPLY)
896 .build();
897
898 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
899 .punt()
900 .build();
901
902 osFlowRuleService.setRule(
903 appId,
904 osNode.intgBridge(),
905 selector,
906 treatment,
907 PRIORITY_ARP_CONTROL_RULE,
Jian Li8abf2fe2018-06-12 18:42:30 +0900908 GW_COMMON_TABLE,
Jian Lif96685c2018-05-21 14:14:16 +0900909 install
910 );
911 }
912 }
Daniel Park81a61a12016-02-26 08:24:44 +0900913}