blob: 8c45d4c8edfa74759999cd0ef15059db0a1c22ab [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 Lida03ce92018-07-24 21:41:53 +090018import com.google.common.base.Strings;
Jian Li1064e4f2018-05-29 16:16:53 +090019import com.google.common.collect.ImmutableSet;
Jian Li1064e4f2018-05-29 16:16:53 +090020import com.google.common.collect.Sets;
Daniel Park81a61a12016-02-26 08:24:44 +090021import org.onlab.packet.ARP;
Jian Li60312252018-05-10 18:40:32 +090022import org.onlab.packet.EthType;
Daniel Park81a61a12016-02-26 08:24:44 +090023import org.onlab.packet.Ethernet;
Daniel Park81a61a12016-02-26 08:24:44 +090024import org.onlab.packet.Ip4Address;
25import org.onlab.packet.IpAddress;
26import org.onlab.packet.MacAddress;
Jian Li60312252018-05-10 18:40:32 +090027import org.onosproject.cfg.ComponentConfigService;
Jian Li7f70bb72018-07-06 23:35:30 +090028import org.onosproject.cfg.ConfigProperty;
Jian Li60312252018-05-10 18:40:32 +090029import org.onosproject.cluster.ClusterService;
30import org.onosproject.cluster.LeadershipService;
31import org.onosproject.cluster.NodeId;
32import org.onosproject.core.ApplicationId;
33import org.onosproject.core.CoreService;
Jian Li14a79f22018-06-05 03:44:22 +090034import org.onosproject.net.ConnectPoint;
Hyunsun Moon0d457362017-06-27 17:19:41 +090035import org.onosproject.net.DeviceId;
daniel parkb5817102018-02-15 00:18:51 +090036import org.onosproject.net.PortNumber;
Jian Li60312252018-05-10 18:40:32 +090037import org.onosproject.net.flow.DefaultTrafficSelector;
Daniel Park81a61a12016-02-26 08:24:44 +090038import org.onosproject.net.flow.DefaultTrafficTreatment;
Jian Li60312252018-05-10 18:40:32 +090039import org.onosproject.net.flow.TrafficSelector;
Daniel Park81a61a12016-02-26 08:24:44 +090040import org.onosproject.net.flow.TrafficTreatment;
41import org.onosproject.net.packet.DefaultOutboundPacket;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070042import org.onosproject.net.packet.InboundPacket;
Daniel Park81a61a12016-02-26 08:24:44 +090043import org.onosproject.net.packet.PacketContext;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070044import org.onosproject.net.packet.PacketProcessor;
Daniel Park81a61a12016-02-26 08:24:44 +090045import org.onosproject.net.packet.PacketService;
Hyunsun Moon05400872017-02-07 17:11:25 +090046import org.onosproject.openstacknetworking.api.Constants;
Jian Li60312252018-05-10 18:40:32 +090047import org.onosproject.openstacknetworking.api.InstancePort;
Jian Li581f21a2018-10-12 09:33:56 +090048import org.onosproject.openstacknetworking.api.InstancePortAdminService;
Jian Li24ec59f2018-05-23 19:01:25 +090049import org.onosproject.openstacknetworking.api.InstancePortEvent;
50import org.onosproject.openstacknetworking.api.InstancePortListener;
Jian Li60312252018-05-10 18:40:32 +090051import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
daniel park32b42202018-03-14 16:53:44 +090052import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
Jian Li809b3ed2018-10-14 20:49:33 +090053import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
54import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
Jian Li1064e4f2018-05-29 16:16:53 +090055import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
Jian Li60312252018-05-10 18:40:32 +090056import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
57import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
daniel parkeeb8e042018-02-21 14:06:58 +090058import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Jian Li581f21a2018-10-12 09:33:56 +090059import org.onosproject.openstacknetworking.api.PreCommitPortService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090060import org.onosproject.openstacknode.api.OpenstackNode;
Jian Lif96685c2018-05-21 14:14:16 +090061import org.onosproject.openstacknode.api.OpenstackNodeEvent;
62import org.onosproject.openstacknode.api.OpenstackNodeListener;
Hyunsun Moon0d457362017-06-27 17:19:41 +090063import org.onosproject.openstacknode.api.OpenstackNodeService;
Jian Li60312252018-05-10 18:40:32 +090064import org.openstack4j.model.network.ExternalGateway;
Jian Li4df657b2018-05-29 16:39:00 +090065import org.openstack4j.model.network.IP;
daniel parkeeb8e042018-02-21 14:06:58 +090066import org.openstack4j.model.network.NetFloatingIP;
Jian Li809b3ed2018-10-14 20:49:33 +090067import org.openstack4j.model.network.Port;
Jian Li60312252018-05-10 18:40:32 +090068import org.openstack4j.model.network.Router;
Jian Li60312252018-05-10 18:40:32 +090069import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070070import org.osgi.service.component.annotations.Activate;
71import org.osgi.service.component.annotations.Component;
72import org.osgi.service.component.annotations.Deactivate;
73import org.osgi.service.component.annotations.Modified;
74import org.osgi.service.component.annotations.Reference;
75import org.osgi.service.component.annotations.ReferenceCardinality;
Daniel Park81a61a12016-02-26 08:24:44 +090076import org.slf4j.Logger;
77
78import java.nio.ByteBuffer;
Hyunsun Moon44aac662017-02-18 02:07:01 +090079import java.util.Objects;
Hyunsun Moon0d457362017-06-27 17:19:41 +090080import java.util.Set;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070081import java.util.concurrent.ExecutorService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090082import java.util.stream.Collectors;
Daniel Park81a61a12016-02-26 08:24:44 +090083
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070084import static java.util.concurrent.Executors.newSingleThreadExecutor;
85import static org.onlab.util.Tools.groupedThreads;
Jian Li60312252018-05-10 18:40:32 +090086import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
87import static org.onosproject.openstacknetworking.api.Constants.ARP_PROXY_MODE;
88import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_ARP_MODE_STR;
89import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
90import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
91import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
Jian Lif96685c2018-05-21 14:14:16 +090092import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_CONTROL_RULE;
Jian Li60312252018-05-10 18:40:32 +090093import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Jian Li581f21a2018-10-12 09:33:56 +090094import static org.onosproject.openstacknetworking.api.OpenstackNetworkEvent.Type.OPENSTACK_PORT_PRE_REMOVE;
Jian Li24ec59f2018-05-23 19:01:25 +090095import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
96import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
Jian Lia171a432018-06-11 11:52:11 +090097import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort;
Jian Li7f70bb72018-07-06 23:35:30 +090098import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
Jian Li24ec59f2018-05-23 19:01:25 +090099import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM;
Jian Liec5c32b2018-07-13 14:28:58 +0900100import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
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
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700116 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li60312252018-05-10 18:40:32 +0900117 protected CoreService coreService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900118
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700119 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700120 protected PacketService packetService;
Daniel Park81a61a12016-02-26 08:24:44 +0900121
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700122 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel park32b42202018-03-14 16:53:44 +0900123 protected OpenstackNetworkAdminService osNetworkAdminService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700124
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700125 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parkeeb8e042018-02-21 14:06:58 +0900126 protected OpenstackRouterService osRouterService;
127
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700128 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel parke49eb382017-04-05 16:48:28 +0900129 protected OpenstackNodeService osNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900130
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700131 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li581f21a2018-10-12 09:33:56 +0900132 protected InstancePortAdminService instancePortService;
Jian Li1064e4f2018-05-29 16:16:53 +0900133
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700134 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li60312252018-05-10 18:40:32 +0900135 protected ClusterService clusterService;
136
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700137 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li60312252018-05-10 18:40:32 +0900138 protected LeadershipService leadershipService;
139
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700140 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li60312252018-05-10 18:40:32 +0900141 protected OpenstackFlowRuleService osFlowRuleService;
142
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700143 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li1064e4f2018-05-29 16:16:53 +0900144 protected OpenstackNetworkService osNetworkService;
145
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700146 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lif3a28b02018-06-11 21:29:13 +0900147 protected ComponentConfigService configService;
Jian Li60312252018-05-10 18:40:32 +0900148
Ray Milkey0b18b722018-10-16 13:19:15 -0700149 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li581f21a2018-10-12 09:33:56 +0900150 protected PreCommitPortService preCommitPortService;
151
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700152 //@Property(name = ARP_MODE, value = DEFAULT_ARP_MODE_STR,
153 // label = "ARP processing mode, broadcast | proxy (default)")
Jian Li60312252018-05-10 18:40:32 +0900154 protected String arpMode = DEFAULT_ARP_MODE_STR;
155
156 protected String gatewayMac = DEFAULT_GATEWAY_MAC_STR;
157
158 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
Jian Lif96685c2018-05-21 14:14:16 +0900159 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
Jian Li24ec59f2018-05-23 19:01:25 +0900160 private final InstancePortListener instPortListener = new InternalInstancePortListener();
Jian Li809b3ed2018-10-14 20:49:33 +0900161 private final OpenstackNetworkListener osNetworkListener = new InternalNetworkEventListener();
Jian Li60312252018-05-10 18:40:32 +0900162
163 private ApplicationId appId;
164 private NodeId localNodeId;
Jian Liec5c32b2018-07-13 14:28:58 +0900165
Hyunsun Moon44aac662017-02-18 02:07:01 +0900166 private final ExecutorService eventExecutor = newSingleThreadExecutor(
167 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700168
Hyunsun Moon0d457362017-06-27 17:19:41 +0900169 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700170
171 @Activate
172 protected void activate() {
Jian Li60312252018-05-10 18:40:32 +0900173 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
174 configService.registerProperties(getClass());
175 localNodeId = clusterService.getLocalNode().id();
Jian Lif3a28b02018-06-11 21:29:13 +0900176 osRouterService.addListener(osRouterListener);
Jian Lif96685c2018-05-21 14:14:16 +0900177 osNodeService.addListener(osNodeListener);
Jian Li809b3ed2018-10-14 20:49:33 +0900178 osNetworkService.addListener(osNetworkListener);
Jian Li24ec59f2018-05-23 19:01:25 +0900179 instancePortService.addListener(instPortListener);
Jian Li60312252018-05-10 18:40:32 +0900180 leadershipService.runForLeadership(appId.name());
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700181 packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
182 log.info("Started");
Daniel Park81a61a12016-02-26 08:24:44 +0900183 }
184
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700185 @Deactivate
186 protected void deactivate() {
187 packetService.removeProcessor(packetProcessor);
Jian Lie1a39032018-06-19 21:49:36 +0900188 instancePortService.removeListener(instPortListener);
Jian Li60312252018-05-10 18:40:32 +0900189 osRouterService.removeListener(osRouterListener);
Jian Lif96685c2018-05-21 14:14:16 +0900190 osNodeService.removeListener(osNodeListener);
Jian Li809b3ed2018-10-14 20:49:33 +0900191 osNetworkService.removeListener(osNetworkListener);
Jian Li24ec59f2018-05-23 19:01:25 +0900192 instancePortService.removeListener(instPortListener);
Jian Li60312252018-05-10 18:40:32 +0900193 leadershipService.withdraw(appId.name());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900194 eventExecutor.shutdown();
Jian Li60312252018-05-10 18:40:32 +0900195 configService.unregisterProperties(getClass(), false);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700196 log.info("Stopped");
Daniel Park81a61a12016-02-26 08:24:44 +0900197 }
198
Jian Li60312252018-05-10 18:40:32 +0900199 @Modified
200 void modified(ComponentContext context) {
Jian Li60312252018-05-10 18:40:32 +0900201 log.info("Modified");
202 }
203
Jian Li7f70bb72018-07-06 23:35:30 +0900204 private String getArpMode() {
205 Set<ConfigProperty> properties = configService.getProperties(this.getClass().getName());
206 return getPropertyValue(properties, ARP_MODE);
207 }
208
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700209 private void processArpPacket(PacketContext context, Ethernet ethernet) {
Daniel Park81a61a12016-02-26 08:24:44 +0900210 ARP arp = (ARP) ethernet.getPayload();
Jian Li60312252018-05-10 18:40:32 +0900211
Jian Li7f70bb72018-07-06 23:35:30 +0900212 if (arp.getOpCode() == ARP.OP_REQUEST && ARP_PROXY_MODE.equals(getArpMode())) {
daniel parkb5817102018-02-15 00:18:51 +0900213 if (log.isTraceEnabled()) {
214 log.trace("ARP request received from {} for {}",
215 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
216 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
217 }
218
219 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
daniel parkeeb8e042018-02-21 14:06:58 +0900220
221 MacAddress targetMac = null;
222
223 NetFloatingIP floatingIP = osRouterService.floatingIps().stream()
224 .filter(ip -> ip.getFloatingIpAddress().equals(targetIp.toString()))
225 .findAny().orElse(null);
226
daniel park576969a2018-03-09 07:07:41 +0900227 //In case target ip is for associated floating ip, sets target mac to vm's.
daniel parkeeb8e042018-02-21 14:06:58 +0900228 if (floatingIP != null && floatingIP.getPortId() != null) {
Daniel Park96f1e032018-08-09 13:30:57 +0900229 InstancePort instPort = instancePortService.instancePort(floatingIP.getPortId());
230 if (instPort == null) {
231 log.trace("Unknown target ARP request for {}, ignore it", targetIp);
232 return;
233 } else {
234 targetMac = instPort.macAddress();
235 }
236
237 OpenstackNode gw = getGwByInstancePort(osNodeService.completeNodes(GATEWAY), instPort);
238
239 if (gw == null) {
240 return;
241 }
242
243 // if the ARP packet_in received from non-relevant GWs, we simply ignore it
244 if (!Objects.equals(gw.intgBridge(), context.inPacket().receivedFrom().deviceId())) {
245 return;
246 }
daniel parkeeb8e042018-02-21 14:06:58 +0900247 }
248
Daniel Park96f1e032018-08-09 13:30:57 +0900249 if (isExternalGatewaySourceIp(targetIp)) {
daniel parkeeb8e042018-02-21 14:06:58 +0900250 targetMac = Constants.DEFAULT_GATEWAY_MAC;
251 }
252
253 if (targetMac == null) {
daniel parkb5817102018-02-15 00:18:51 +0900254 log.trace("Unknown target ARP request for {}, ignore it", targetIp);
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().
Jian Li5e2ad4a2018-07-16 13:40:53 +0900283 stream().map(r -> r.ipAddress().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 /**
345 * Installs static ARP rules used in ARP BROAD_CAST mode.
Jian Li1064e4f2018-05-29 16:16:53 +0900346 *
347 * @param gateway gateway node
348 * @param install flow rule installation flag
349 */
350 private void setFloatingIpArpRuleForGateway(OpenstackNode gateway, boolean install) {
Jian Li7f70bb72018-07-06 23:35:30 +0900351 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
Jian Li1064e4f2018-05-29 16:16:53 +0900352
353 Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
354 Set<OpenstackNode> finalGws = Sets.newConcurrentHashSet();
355 finalGws.addAll(ImmutableSet.copyOf(completedGws));
356
357 if (install) {
358 if (completedGws.contains(gateway)) {
359 if (completedGws.size() > 1) {
360 finalGws.remove(gateway);
361 osRouterService.floatingIps().forEach(fip -> {
362 if (fip.getPortId() != null) {
Jian Li8f64feb2018-07-24 13:20:16 +0900363 setFloatingIpArpRule(fip, fip.getPortId(), finalGws, false);
Jian Li1064e4f2018-05-29 16:16:53 +0900364 finalGws.add(gateway);
365 }
366 });
367 }
368 osRouterService.floatingIps().forEach(fip -> {
369 if (fip.getPortId() != null) {
Jian Li8f64feb2018-07-24 13:20:16 +0900370 setFloatingIpArpRule(fip, fip.getPortId(), finalGws, true);
Jian Li1064e4f2018-05-29 16:16:53 +0900371 }
372 });
373 } else {
374 log.warn("Detected node should be included in completed gateway set");
375 }
376 } else {
377 if (!completedGws.contains(gateway)) {
378 finalGws.add(gateway);
379 osRouterService.floatingIps().forEach(fip -> {
380 if (fip.getPortId() != null) {
Jian Li8f64feb2018-07-24 13:20:16 +0900381 setFloatingIpArpRule(fip, fip.getPortId(), finalGws, false);
Jian Li1064e4f2018-05-29 16:16:53 +0900382 }
383 });
384 finalGws.remove(gateway);
385 if (completedGws.size() >= 1) {
386 osRouterService.floatingIps().forEach(fip -> {
387 if (fip.getPortId() != null) {
Jian Li8f64feb2018-07-24 13:20:16 +0900388 setFloatingIpArpRule(fip, fip.getPortId(), finalGws, true);
Jian Li1064e4f2018-05-29 16:16:53 +0900389 }
390 });
391 }
392 } else {
393 log.warn("Detected node should NOT be included in completed gateway set");
394 }
395 }
396 }
397 }
398
399 /**
Jian Li24ec59f2018-05-23 19:01:25 +0900400 * Installs/uninstalls ARP flow rules to the corresponding gateway by
401 * looking for compute node's device ID.
402 *
403 * @param fip floating IP
404 * @param port instance port
405 * @param gateways a collection of gateways
406 * @param install install flag
407 */
408 private void setFloatingIpArpRuleWithPortEvent(NetFloatingIP fip,
409 InstancePort port,
410 Set<OpenstackNode> gateways,
411 boolean install) {
Jian Li7f70bb72018-07-06 23:35:30 +0900412 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
Jian Li24ec59f2018-05-23 19:01:25 +0900413
414 OpenstackNode gw = getGwByInstancePort(gateways, port);
415
416 if (gw == null) {
417 return;
418 }
419
420 String macString = osNetworkAdminService.port(fip.getPortId()).getMacAddress();
421
422 setArpRule(fip, MacAddress.valueOf(macString), gw, install);
423 }
424 }
425
426 /**
Jian Li1064e4f2018-05-29 16:16:53 +0900427 * Installs static ARP rules used in ARP BROAD_CAST mode.
Jian Li60312252018-05-10 18:40:32 +0900428 * Note that, those rules will be only matched ARP_REQUEST packets,
429 * used for telling gateway node the mapped MAC address of requested IP,
430 * without the helps from controller.
431 *
432 * @param fip floating IP address
Jian Li8f64feb2018-07-24 13:20:16 +0900433 * @param portId port identifier
Jian Li1064e4f2018-05-29 16:16:53 +0900434 * @param gateways a set of gateway nodes
Jian Li60312252018-05-10 18:40:32 +0900435 * @param install flow rule installation flag
436 */
Jian Li8f64feb2018-07-24 13:20:16 +0900437 private synchronized void setFloatingIpArpRule(NetFloatingIP fip, String portId,
Jian Li1064e4f2018-05-29 16:16:53 +0900438 Set<OpenstackNode> gateways,
439 boolean install) {
Jian Li7f70bb72018-07-06 23:35:30 +0900440 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
Jian Li60312252018-05-10 18:40:32 +0900441
442 if (fip == null) {
443 log.warn("Failed to set ARP broadcast rule for floating IP");
444 return;
445 }
446
Jian Li581f21a2018-10-12 09:33:56 +0900447 if (portId == null || (install && fip.getPortId() == null)) {
Jian Lida03ce92018-07-24 21:41:53 +0900448 log.trace("Unknown target ARP request for {}, ignore it",
Jian Li581f21a2018-10-12 09:33:56 +0900449 fip.getFloatingIpAddress());
Jian Lida03ce92018-07-24 21:41:53 +0900450 return;
451 }
452
Jian Li8f64feb2018-07-24 13:20:16 +0900453 InstancePort instPort = instancePortService.instancePort(portId);
Jian Li46b74002018-07-15 18:39:08 +0900454 MacAddress targetMac = instPort.macAddress();
Jian Lif3a28b02018-06-11 21:29:13 +0900455
Jian Lia171a432018-06-11 11:52:11 +0900456 OpenstackNode gw = getGwByInstancePort(gateways, instPort);
Jian Li1064e4f2018-05-29 16:16:53 +0900457
458 if (gw == null) {
459 return;
460 }
461
Jian Li581f21a2018-10-12 09:33:56 +0900462 if (install) {
463 preCommitPortService.subscribePreCommit(instPort.portId(),
464 OPENSTACK_PORT_PRE_REMOVE, this.getClass().getName());
465 log.info("Subscribed the port {} on listening pre-remove event", instPort.portId());
466 } else {
467 preCommitPortService.unsubscribePreCommit(instPort.portId(),
468 OPENSTACK_PORT_PRE_REMOVE, instancePortService, this.getClass().getName());
469 log.info("Unsubscribed the port {} on listening pre-remove event", instPort.portId());
470 }
471
Jian Li24ec59f2018-05-23 19:01:25 +0900472 setArpRule(fip, targetMac, gw, install);
473 }
474 }
Jian Li60312252018-05-10 18:40:32 +0900475
Jian Li24ec59f2018-05-23 19:01:25 +0900476 private void setArpRule(NetFloatingIP fip, MacAddress targetMac,
477 OpenstackNode gateway, boolean install) {
478 TrafficSelector selector = DefaultTrafficSelector.builder()
479 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
480 .matchArpOp(ARP.OP_REQUEST)
481 .matchArpTpa(Ip4Address.valueOf(fip.getFloatingIpAddress()))
482 .build();
Jian Li60312252018-05-10 18:40:32 +0900483
Jian Li24ec59f2018-05-23 19:01:25 +0900484 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
485 .setArpOp(ARP.OP_REPLY)
486 .setArpSha(targetMac)
487 .setArpSpa(Ip4Address.valueOf(fip.getFloatingIpAddress()))
488 .setOutput(PortNumber.IN_PORT)
489 .build();
Jian Li60312252018-05-10 18:40:32 +0900490
Jian Li24ec59f2018-05-23 19:01:25 +0900491 osFlowRuleService.setRule(
492 appId,
493 gateway.intgBridge(),
494 selector,
495 treatment,
496 PRIORITY_ARP_GATEWAY_RULE,
497 GW_COMMON_TABLE,
498 install
499 );
500
501 if (install) {
502 log.info("Install ARP Rule for Floating IP {}",
503 fip.getFloatingIpAddress());
504 } else {
505 log.info("Uninstall ARP Rule for Floating IP {}",
506 fip.getFloatingIpAddress());
Jian Li60312252018-05-10 18:40:32 +0900507 }
508 }
509
Jian Li809b3ed2018-10-14 20:49:33 +0900510 private void setFakeGatewayArpRuleByRouter(Router router, boolean install) {
511 setFakeGatewayArpRuleByGateway(router.getExternalGatewayInfo(), install);
Daniel Park96f1e032018-08-09 13:30:57 +0900512 }
513
514 private Set<IP> getExternalGatewaySnatIps(ExternalGateway extGw) {
515 return osNetworkAdminService.ports().stream()
516 .filter(port ->
517 Objects.equals(port.getNetworkId(), extGw.getNetworkId()))
518 .filter(port ->
519 Objects.equals(port.getDeviceOwner(), DEVICE_OWNER_ROUTER_GW))
520 .flatMap(port -> port.getFixedIps().stream())
521 .collect(Collectors.toSet());
522 }
523
Jian Li809b3ed2018-10-14 20:49:33 +0900524 private void setFakeGatewayArpRuleByGateway(ExternalGateway extGw, boolean install) {
Daniel Park96f1e032018-08-09 13:30:57 +0900525 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
526
527 if (extGw == null) {
528 return;
529 }
530
Jian Li809b3ed2018-10-14 20:49:33 +0900531 setFakeGatewayArpRuleByIps(getExternalGatewaySnatIps(extGw), install);
532 }
533 }
Daniel Park96f1e032018-08-09 13:30:57 +0900534
Jian Li809b3ed2018-10-14 20:49:33 +0900535 private void setFakeGatewayArpRuleByIps(Set<IP> ips, boolean install) {
536 ips.forEach(ip -> {
537 TrafficSelector selector = DefaultTrafficSelector.builder()
538 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
539 .matchArpOp(ARP.OP_REQUEST)
540 .matchArpTpa(Ip4Address.valueOf(ip.getIpAddress()))
541 .build();
Daniel Park96f1e032018-08-09 13:30:57 +0900542
Jian Li809b3ed2018-10-14 20:49:33 +0900543 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
544 .setArpOp(ARP.OP_REPLY)
545 .setArpSha(MacAddress.valueOf(gatewayMac))
546 .setArpSpa(Ip4Address.valueOf(ip.getIpAddress()))
547 .setOutput(PortNumber.IN_PORT)
548 .build();
Daniel Park96f1e032018-08-09 13:30:57 +0900549
Jian Li809b3ed2018-10-14 20:49:33 +0900550 osNodeService.completeNodes(GATEWAY).forEach(n ->
551 osFlowRuleService.setRule(
552 appId,
553 n.intgBridge(),
554 selector,
555 treatment,
556 PRIORITY_ARP_GATEWAY_RULE,
557 GW_COMMON_TABLE,
558 install
559 )
560 );
Daniel Park96f1e032018-08-09 13:30:57 +0900561
Jian Li809b3ed2018-10-14 20:49:33 +0900562 if (install) {
563 log.info("Install ARP Rule for Gateway Snat {}", ip.getIpAddress());
564 } else {
565 log.info("Uninstall ARP Rule for Gateway Snat {}", ip.getIpAddress());
566 }
567 });
568 }
569
570 /**
571 * An internal network event listener, intended to uninstall ARP rules for
572 * routing the packets destined to external gateway.
573 */
574 private class InternalNetworkEventListener implements OpenstackNetworkListener {
575
576 @Override
577 public boolean isRelevant(OpenstackNetworkEvent event) {
578 Port osPort = event.port();
579 if (osPort == null || osPort.getFixedIps() == null) {
580 return false;
581 }
582
583 // do not allow to proceed without leadership
584 NodeId leader = leadershipService.getLeader(appId.name());
585 return Objects.equals(localNodeId, leader) &&
586 DEVICE_OWNER_ROUTER_GW.equals(osPort.getDeviceOwner());
587 }
588
589 @Override
590 public void event(OpenstackNetworkEvent event) {
591 switch (event.type()) {
592 case OPENSTACK_PORT_CREATED:
593 case OPENSTACK_PORT_UPDATED:
594 eventExecutor.execute(() ->
595 setFakeGatewayArpRuleByIps((Set<IP>) event.port().getFixedIps(), true)
596 );
597 break;
598 case OPENSTACK_PORT_REMOVED:
599 eventExecutor.execute(() ->
600 setFakeGatewayArpRuleByIps((Set<IP>) event.port().getFixedIps(), false)
601 );
602 break;
603 default:
604 // do nothing
605 break;
606 }
Daniel Park96f1e032018-08-09 13:30:57 +0900607 }
608 }
609
Jian Li60312252018-05-10 18:40:32 +0900610 /**
611 * An internal router event listener, intended to install/uninstall
612 * ARP rules for forwarding packets created from floating IPs.
613 */
614 private class InternalRouterEventListener implements OpenstackRouterListener {
615
616 @Override
617 public boolean isRelevant(OpenstackRouterEvent event) {
618 // do not allow to proceed without leadership
619 NodeId leader = leadershipService.getLeader(appId.name());
620 return Objects.equals(localNodeId, leader);
621 }
622
623 @Override
624 public void event(OpenstackRouterEvent event) {
Jian Li1064e4f2018-05-29 16:16:53 +0900625
626 Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
627
Jian Li60312252018-05-10 18:40:32 +0900628 switch (event.type()) {
629 case OPENSTACK_ROUTER_CREATED:
630 eventExecutor.execute(() ->
631 // add a router with external gateway
Jian Li809b3ed2018-10-14 20:49:33 +0900632 setFakeGatewayArpRuleByRouter(event.subject(), true)
Jian Li60312252018-05-10 18:40:32 +0900633 );
634 break;
635 case OPENSTACK_ROUTER_REMOVED:
636 eventExecutor.execute(() ->
637 // remove a router with external gateway
Jian Li809b3ed2018-10-14 20:49:33 +0900638 setFakeGatewayArpRuleByRouter(event.subject(), false)
Jian Li60312252018-05-10 18:40:32 +0900639 );
640 break;
641 case OPENSTACK_ROUTER_GATEWAY_ADDED:
642 eventExecutor.execute(() ->
643 // add a gateway manually after adding a router
Jian Li809b3ed2018-10-14 20:49:33 +0900644 setFakeGatewayArpRuleByGateway(event.externalGateway(), true)
Jian Li60312252018-05-10 18:40:32 +0900645 );
646 break;
647 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
648 eventExecutor.execute(() ->
649 // remove a gateway from an existing router
Jian Li809b3ed2018-10-14 20:49:33 +0900650 setFakeGatewayArpRuleByGateway(event.externalGateway(), false)
Jian Li60312252018-05-10 18:40:32 +0900651 );
652 break;
653 case OPENSTACK_FLOATING_IP_ASSOCIATED:
Jian Lida03ce92018-07-24 21:41:53 +0900654 if (getValidPortId(event) != null) {
655 eventExecutor.execute(() -> {
656 // associate a floating IP with an existing VM
657 setFloatingIpArpRule(event.floatingIp(), getValidPortId(event),
658 completedGws, true);
659 });
660 }
Jian Li60312252018-05-10 18:40:32 +0900661 break;
662 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
Jian Lida03ce92018-07-24 21:41:53 +0900663 if (getValidPortId(event) != null) {
664 eventExecutor.execute(() -> {
665 // disassociate a floating IP with an existing VM
666 setFloatingIpArpRule(event.floatingIp(), getValidPortId(event),
667 completedGws, false);
668 });
669 }
Jian Li60312252018-05-10 18:40:32 +0900670 break;
671 case OPENSTACK_FLOATING_IP_CREATED:
Jian Lida03ce92018-07-24 21:41:53 +0900672 // during floating IP creation, if the floating IP is
673 // associated with any port of VM, then we will set
674 // floating IP related ARP rules to gateway node
675 if (getValidPortId(event) != null) {
676 eventExecutor.execute(() -> {
677 // associate a floating IP with an existing VM
678 setFloatingIpArpRule(event.floatingIp(), getValidPortId(event),
679 completedGws, true);
680 });
681 }
Jian Li60312252018-05-10 18:40:32 +0900682 break;
683 case OPENSTACK_FLOATING_IP_REMOVED:
Jian Lida03ce92018-07-24 21:41:53 +0900684 // during floating IP deletion, if the floating IP is
685 // still associated with any port of VM, then we will
686 // remove floating IP related ARP rules from gateway node
687 if (getValidPortId(event) != null) {
688 eventExecutor.execute(() -> {
689 // associate a floating IP with an existing VM
690 setFloatingIpArpRule(event.floatingIp(), getValidPortId(event),
691 completedGws, false);
692 });
693 }
Jian Li60312252018-05-10 18:40:32 +0900694 break;
695 default:
696 // do nothing for the other events
697 break;
698 }
699 }
700
Jian Lida03ce92018-07-24 21:41:53 +0900701 private String getValidPortId(OpenstackRouterEvent event) {
702 NetFloatingIP osFip = event.floatingIp();
703 String portId = osFip.getPortId();
704
705 if (Strings.isNullOrEmpty(portId)) {
706 portId = event.portId();
707 }
708
709 if (portId != null && instancePortService.instancePort(portId) != null) {
710 return portId;
711 }
712
713 return null;
714 }
Jian Li60312252018-05-10 18:40:32 +0900715 }
716
Jian Lie1a39032018-06-19 21:49:36 +0900717 private class InternalInstancePortListener implements InstancePortListener {
Jian Li60312252018-05-10 18:40:32 +0900718
719 @Override
Jian Lie1a39032018-06-19 21:49:36 +0900720 public boolean isRelevant(InstancePortEvent event) {
721 // do not allow to proceed without leadership
722 NodeId leader = leadershipService.getLeader(appId.name());
723 return Objects.equals(localNodeId, leader);
Jian Li60312252018-05-10 18:40:32 +0900724 }
725
726 @Override
Jian Lie1a39032018-06-19 21:49:36 +0900727 public void event(InstancePortEvent event) {
728 InstancePort instPort = event.subject();
729
730 Set<NetFloatingIP> ips = osRouterService.floatingIps();
731 NetFloatingIP fip = associatedFloatingIp(instPort, ips);
732 Set<OpenstackNode> gateways = osNodeService.completeNodes(GATEWAY);
733
Jian Li60312252018-05-10 18:40:32 +0900734 switch (event.type()) {
Jian Lie1a39032018-06-19 21:49:36 +0900735 case OPENSTACK_INSTANCE_PORT_DETECTED:
Jian Lie1a39032018-06-19 21:49:36 +0900736
Jian Li46b74002018-07-15 18:39:08 +0900737 osRouterService.floatingIps().stream()
738 .filter(f -> f.getPortId() != null)
739 .filter(f -> f.getPortId().equals(instPort.portId()))
Jian Li8f64feb2018-07-24 13:20:16 +0900740 .forEach(f -> setFloatingIpArpRule(f, instPort.portId(), gateways, true));
Jian Lie1a39032018-06-19 21:49:36 +0900741
Jian Li60312252018-05-10 18:40:32 +0900742 break;
Jian Lie1a39032018-06-19 21:49:36 +0900743 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
744
745 if (gateways.size() == 1) {
746 return;
747 }
748
749 if (fip != null && isAssociatedWithVM(osNetworkService, fip)) {
Jian Liec5c32b2018-07-13 14:28:58 +0900750 eventExecutor.execute(() ->
Jian Lie1a39032018-06-19 21:49:36 +0900751 setFloatingIpArpRuleWithPortEvent(fip, event.subject(),
Jian Liec5c32b2018-07-13 14:28:58 +0900752 gateways, true)
753 );
Jian Lie1a39032018-06-19 21:49:36 +0900754 }
755
756 break;
757 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
758
Jian Liec5c32b2018-07-13 14:28:58 +0900759 InstancePort revisedInstPort = swapStaleLocation(event.subject());
760
Jian Lie1a39032018-06-19 21:49:36 +0900761 if (gateways.size() == 1) {
762 return;
763 }
764
765 if (fip != null && isAssociatedWithVM(osNetworkService, fip)) {
Jian Liec5c32b2018-07-13 14:28:58 +0900766 DeviceId newDeviceId = event.subject().deviceId();
767 DeviceId oldDeviceId = revisedInstPort.deviceId();
Jian Lie1a39032018-06-19 21:49:36 +0900768
769 OpenstackNode oldGw = getGwByComputeDevId(gateways, oldDeviceId);
770 OpenstackNode newGw = getGwByComputeDevId(gateways, newDeviceId);
771
772 if (oldGw != null && oldGw.equals(newGw)) {
773 return;
774 }
775
776 eventExecutor.execute(() ->
Jian Liec5c32b2018-07-13 14:28:58 +0900777 setFloatingIpArpRuleWithPortEvent(fip,
778 revisedInstPort, gateways, false));
Jian Lie1a39032018-06-19 21:49:36 +0900779 }
780 break;
781 default:
782 break;
783 }
Jian Li60312252018-05-10 18:40:32 +0900784 }
785 }
Jian Lif96685c2018-05-21 14:14:16 +0900786
787 private class InternalNodeEventListener implements OpenstackNodeListener {
788
789 @Override
790 public boolean isRelevant(OpenstackNodeEvent event) {
791 // do not allow to proceed without leadership
792 NodeId leader = leadershipService.getLeader(appId.name());
Jian Li51b844c2018-05-31 10:59:03 +0900793 return Objects.equals(localNodeId, leader) && event.subject().type() == GATEWAY;
Jian Lif96685c2018-05-21 14:14:16 +0900794 }
795
796 @Override
797 public void event(OpenstackNodeEvent event) {
798 OpenstackNode osNode = event.subject();
799 switch (event.type()) {
800 case OPENSTACK_NODE_COMPLETE:
Jian Li51b844c2018-05-31 10:59:03 +0900801 setDefaultArpRule(osNode, true);
802 setFloatingIpArpRuleForGateway(osNode, true);
Jian Lif96685c2018-05-21 14:14:16 +0900803 break;
804 case OPENSTACK_NODE_INCOMPLETE:
Jian Li51b844c2018-05-31 10:59:03 +0900805 setDefaultArpRule(osNode, false);
806 setFloatingIpArpRuleForGateway(osNode, false);
Jian Lif96685c2018-05-21 14:14:16 +0900807 break;
808 default:
809 break;
810 }
811 }
812
813 private void setDefaultArpRule(OpenstackNode osNode, boolean install) {
Jian Li7f70bb72018-07-06 23:35:30 +0900814 switch (getArpMode()) {
Jian Lif96685c2018-05-21 14:14:16 +0900815 case ARP_PROXY_MODE:
816 setDefaultArpRuleForProxyMode(osNode, install);
817 break;
818 case ARP_BROADCAST_MODE:
819 setDefaultArpRuleForBroadcastMode(osNode, install);
820 break;
821 default:
822 log.warn("Invalid ARP mode {}. Please use either " +
Jian Li7f70bb72018-07-06 23:35:30 +0900823 "broadcast or proxy mode.", getArpMode());
Jian Lif96685c2018-05-21 14:14:16 +0900824 break;
825 }
826 }
827
828 private void setDefaultArpRuleForProxyMode(OpenstackNode osNode, boolean install) {
829 TrafficSelector selector = DefaultTrafficSelector.builder()
830 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
831 .build();
832
833 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
834 .punt()
835 .build();
836
837 osFlowRuleService.setRule(
838 appId,
839 osNode.intgBridge(),
840 selector,
841 treatment,
842 PRIORITY_ARP_CONTROL_RULE,
Jian Li8abf2fe2018-06-12 18:42:30 +0900843 GW_COMMON_TABLE,
Jian Lif96685c2018-05-21 14:14:16 +0900844 install
845 );
846 }
847
848 private void setDefaultArpRuleForBroadcastMode(OpenstackNode osNode, boolean install) {
849 // we only match ARP_REPLY in gateway node, because controller
850 // somehow need to process ARP_REPLY which is issued from
851 // external router...
852 TrafficSelector selector = DefaultTrafficSelector.builder()
853 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
854 .matchArpOp(ARP.OP_REPLY)
855 .build();
856
857 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
858 .punt()
859 .build();
860
861 osFlowRuleService.setRule(
862 appId,
863 osNode.intgBridge(),
864 selector,
865 treatment,
866 PRIORITY_ARP_CONTROL_RULE,
Jian Li8abf2fe2018-06-12 18:42:30 +0900867 GW_COMMON_TABLE,
Jian Lif96685c2018-05-21 14:14:16 +0900868 install
869 );
Daniel Park96f1e032018-08-09 13:30:57 +0900870
871 osRouterService.routers().stream()
872 .filter(router -> router.getExternalGatewayInfo() != null)
Jian Li809b3ed2018-10-14 20:49:33 +0900873 .forEach(router -> setFakeGatewayArpRuleByRouter(router, install));
Jian Lif96685c2018-05-21 14:14:16 +0900874 }
875 }
Daniel Park81a61a12016-02-26 08:24:44 +0900876}