blob: e75b9de2571c6a5baf452e4c9c51ed00a98a1c5d [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.onlab.util.Tools;
36import org.onosproject.cfg.ComponentConfigService;
37import 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.Dictionary;
81import java.util.Map;
Hyunsun Moon44aac662017-02-18 02:07:01 +090082import java.util.Objects;
Hyunsun Moon0d457362017-06-27 17:19:41 +090083import java.util.Set;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070084import java.util.concurrent.ExecutorService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090085import java.util.stream.Collectors;
Daniel Park81a61a12016-02-26 08:24:44 +090086
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070087import static java.util.concurrent.Executors.newSingleThreadExecutor;
88import static org.onlab.util.Tools.groupedThreads;
Jian Li60312252018-05-10 18:40:32 +090089import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
90import static org.onosproject.openstacknetworking.api.Constants.ARP_PROXY_MODE;
91import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_ARP_MODE_STR;
92import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
93import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
94import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
Jian Lif96685c2018-05-21 14:14:16 +090095import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_CONTROL_RULE;
Jian Li60312252018-05-10 18:40:32 +090096import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Jian Li24ec59f2018-05-23 19:01:25 +090097import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
98import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
Jian Lia171a432018-06-11 11:52:11 +090099import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort;
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
149 // TODO: need to find a way to unify aprMode and gatewayMac variables with
150 // that in SwitchingArpHandler
151 @Property(name = ARP_MODE, value = DEFAULT_ARP_MODE_STR,
Jian Li1478f292018-05-28 17:10:59 +0900152 label = "ARP processing mode, broadcast (default) | proxy ")
Jian Li60312252018-05-10 18:40:32 +0900153 protected String arpMode = DEFAULT_ARP_MODE_STR;
154
155 protected String gatewayMac = DEFAULT_GATEWAY_MAC_STR;
156
157 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
Jian Lif96685c2018-05-21 14:14:16 +0900158 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
Jian Li24ec59f2018-05-23 19:01:25 +0900159 private final InstancePortListener instPortListener = new InternalInstancePortListener();
Jian Li60312252018-05-10 18:40:32 +0900160
Jian Lie1a39032018-06-19 21:49:36 +0900161 private final OpenstackNetworkListener osNetworkListener = new InternalOpenstackNetworkListener();
162
Jian Li60312252018-05-10 18:40:32 +0900163 private ApplicationId appId;
164 private NodeId localNodeId;
Jian Lie1a39032018-06-19 21:49:36 +0900165 private final Map<String, MacAddress> floatingIpMacMap = Maps.newConcurrentMap();
166 private final Map<String, DeviceId> migrationPool = Maps.newConcurrentMap();
167 private final Map<MacAddress, InstancePort> terminatedInstPorts = Maps.newConcurrentMap();
168 private final Map<MacAddress, InstancePort> tobeRemovedInstPorts = Maps.newConcurrentMap();
169 private final Map<String, NetFloatingIP> pendingInstPortIds = Maps.newConcurrentMap();
Jian Li60312252018-05-10 18:40:32 +0900170
Hyunsun Moon44aac662017-02-18 02:07:01 +0900171 private final ExecutorService eventExecutor = newSingleThreadExecutor(
172 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700173
Hyunsun Moon0d457362017-06-27 17:19:41 +0900174 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700175
176 @Activate
177 protected void activate() {
Jian Li60312252018-05-10 18:40:32 +0900178 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
179 configService.registerProperties(getClass());
180 localNodeId = clusterService.getLocalNode().id();
Jian Lif3a28b02018-06-11 21:29:13 +0900181 osRouterService.addListener(osRouterListener);
Jian Lif96685c2018-05-21 14:14:16 +0900182 osNodeService.addListener(osNodeListener);
Jian Lie1a39032018-06-19 21:49:36 +0900183 osNetworkService.addListener(osNetworkListener);
Jian Li24ec59f2018-05-23 19:01:25 +0900184 instancePortService.addListener(instPortListener);
Jian Li60312252018-05-10 18:40:32 +0900185 leadershipService.runForLeadership(appId.name());
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700186 packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
187 log.info("Started");
Daniel Park81a61a12016-02-26 08:24:44 +0900188 }
189
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700190 @Deactivate
191 protected void deactivate() {
192 packetService.removeProcessor(packetProcessor);
Jian Lie1a39032018-06-19 21:49:36 +0900193 instancePortService.removeListener(instPortListener);
Jian Li60312252018-05-10 18:40:32 +0900194 osRouterService.removeListener(osRouterListener);
Jian Lif96685c2018-05-21 14:14:16 +0900195 osNodeService.removeListener(osNodeListener);
Jian Li24ec59f2018-05-23 19:01:25 +0900196 instancePortService.removeListener(instPortListener);
Jian Lie1a39032018-06-19 21:49:36 +0900197 osNetworkService.removeListener(osNetworkListener);
Jian Li60312252018-05-10 18:40:32 +0900198 leadershipService.withdraw(appId.name());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900199 eventExecutor.shutdown();
Jian Li60312252018-05-10 18:40:32 +0900200 configService.unregisterProperties(getClass(), false);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700201 log.info("Stopped");
Daniel Park81a61a12016-02-26 08:24:44 +0900202 }
203
Jian Li60312252018-05-10 18:40:32 +0900204 // TODO: need to find a way to unify aprMode and gatewayMac variables with
205 // that in SwitchingArpHandler
206 @Modified
207 void modified(ComponentContext context) {
208 Dictionary<?, ?> properties = context.getProperties();
209 String updateArpMode;
210
211 updateArpMode = Tools.get(properties, ARP_MODE);
212 if (!Strings.isNullOrEmpty(updateArpMode) && !updateArpMode.equals(arpMode)) {
213 arpMode = updateArpMode;
214 }
215
216 log.info("Modified");
217 }
218
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700219 private void processArpPacket(PacketContext context, Ethernet ethernet) {
Daniel Park81a61a12016-02-26 08:24:44 +0900220 ARP arp = (ARP) ethernet.getPayload();
Jian Li60312252018-05-10 18:40:32 +0900221
222 if (arp.getOpCode() == ARP.OP_REQUEST && arpMode.equals(ARP_PROXY_MODE)) {
daniel parkb5817102018-02-15 00:18:51 +0900223 if (log.isTraceEnabled()) {
224 log.trace("ARP request received from {} for {}",
225 Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
226 Ip4Address.valueOf(arp.getTargetProtocolAddress()).toString());
227 }
228
229 IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
daniel parkeeb8e042018-02-21 14:06:58 +0900230
231 MacAddress targetMac = null;
232
233 NetFloatingIP floatingIP = osRouterService.floatingIps().stream()
234 .filter(ip -> ip.getFloatingIpAddress().equals(targetIp.toString()))
235 .findAny().orElse(null);
236
daniel park576969a2018-03-09 07:07:41 +0900237 //In case target ip is for associated floating ip, sets target mac to vm's.
daniel parkeeb8e042018-02-21 14:06:58 +0900238 if (floatingIP != null && floatingIP.getPortId() != null) {
Jian Li60312252018-05-10 18:40:32 +0900239 targetMac = MacAddress.valueOf(osNetworkAdminService.port(
240 floatingIP.getPortId()).getMacAddress());
daniel parkeeb8e042018-02-21 14:06:58 +0900241 }
242
243 if (isExternalGatewaySourceIp(targetIp.getIp4Address())) {
244 targetMac = Constants.DEFAULT_GATEWAY_MAC;
245 }
246
247 if (targetMac == null) {
daniel parkb5817102018-02-15 00:18:51 +0900248 log.trace("Unknown target ARP request for {}, ignore it", targetIp);
249 return;
250 }
251
Jian Lia171a432018-06-11 11:52:11 +0900252 InstancePort instPort = instancePortService.instancePort(targetMac);
253
254 OpenstackNode gw = getGwByInstancePort(osNodeService.completeNodes(GATEWAY), instPort);
Jian Li1064e4f2018-05-29 16:16:53 +0900255
256 if (gw == null) {
257 return;
258 }
259
260 // if the ARP packet_in received from non-relevant GWs, we simply ignore it
261 if (!Objects.equals(gw.intgBridge(), context.inPacket().receivedFrom().deviceId())) {
262 return;
263 }
264
daniel parkb5817102018-02-15 00:18:51 +0900265 Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
266 targetMac, ethernet);
267
268 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
daniel park576969a2018-03-09 07:07:41 +0900269 .setOutput(context.inPacket().receivedFrom().port()).build();
daniel parkb5817102018-02-15 00:18:51 +0900270
271 packetService.emit(new DefaultOutboundPacket(
272 context.inPacket().receivedFrom().deviceId(),
273 treatment,
274 ByteBuffer.wrap(ethReply.serialize())));
275
276 context.block();
Jian Li60312252018-05-10 18:40:32 +0900277 }
278
279 if (arp.getOpCode() == ARP.OP_REPLY) {
Jian Li14a79f22018-06-05 03:44:22 +0900280 ConnectPoint cp = context.inPacket().receivedFrom();
281 PortNumber receivedPortNum = cp.port();
282 IpAddress spa = Ip4Address.valueOf(arp.getSenderProtocolAddress());
283 MacAddress sha = MacAddress.valueOf(arp.getSenderHardwareAddress());
284
285 log.debug("ARP reply ip: {}, mac: {}", spa, sha);
286
daniel parkb5817102018-02-15 00:18:51 +0900287 try {
Jian Li14a79f22018-06-05 03:44:22 +0900288
Jian Lid4066ea2018-06-07 01:44:45 +0900289 Set<String> extRouterIps = osNetworkService.externalPeerRouters().
290 stream().map(r -> r.externalPeerRouterIp().toString()).collect(Collectors.toSet());
Jian Li14a79f22018-06-05 03:44:22 +0900291
Jian Lid4066ea2018-06-07 01:44:45 +0900292 // if SPA is NOT contained in existing external router IP set, we ignore it
293 if (!extRouterIps.contains(spa.toString())) {
Jian Li14a79f22018-06-05 03:44:22 +0900294 return;
295 }
296
297 OpenstackNode node = osNodeService.node(cp.deviceId());
298
299 if (node == null) {
300 return;
301 }
302
303 // we only handles the ARP-Reply message received by gateway node
304 if (node.type() != GATEWAY) {
305 return;
306 }
307
308 if (receivedPortNum.equals(node.uplinkPortNum())) {
309 osNetworkAdminService.updateExternalPeerRouterMac(spa, sha);
daniel parkb5817102018-02-15 00:18:51 +0900310 }
311 } catch (Exception e) {
Jian Li14a79f22018-06-05 03:44:22 +0900312 log.error("Exception occurred because of {}", e);
daniel parkb5817102018-02-15 00:18:51 +0900313 }
Daniel Park81a61a12016-02-26 08:24:44 +0900314 }
Daniel Park81a61a12016-02-26 08:24:44 +0900315 }
316
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700317 private class InternalPacketProcessor implements PacketProcessor {
318
319 @Override
320 public void process(PacketContext context) {
321 if (context.isHandled()) {
322 return;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900323 }
324
325 Set<DeviceId> gateways = osNodeService.completeNodes(GATEWAY)
326 .stream().map(OpenstackNode::intgBridge)
327 .collect(Collectors.toSet());
328
329 if (!gateways.contains(context.inPacket().receivedFrom().deviceId())) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700330 // return if the packet is not from gateway nodes
331 return;
332 }
333
334 InboundPacket pkt = context.inPacket();
335 Ethernet ethernet = pkt.parsed();
336 if (ethernet != null &&
337 ethernet.getEtherType() == Ethernet.TYPE_ARP) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900338 eventExecutor.execute(() -> processArpPacket(context, ethernet));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700339 }
340 }
341 }
342
daniel parkeeb8e042018-02-21 14:06:58 +0900343 private boolean isExternalGatewaySourceIp(IpAddress targetIp) {
daniel park32b42202018-03-14 16:53:44 +0900344 return osNetworkAdminService.ports().stream()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900345 .filter(osPort -> Objects.equals(osPort.getDeviceOwner(),
daniel parkeeb8e042018-02-21 14:06:58 +0900346 DEVICE_OWNER_ROUTER_GW))
Hyunsun Moon44aac662017-02-18 02:07:01 +0900347 .flatMap(osPort -> osPort.getFixedIps().stream())
348 .anyMatch(ip -> IpAddress.valueOf(ip.getIpAddress()).equals(targetIp));
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +0900349 }
Jian Li60312252018-05-10 18:40:32 +0900350
Jian Li60312252018-05-10 18:40:32 +0900351 private void initFloatingIpMacMap() {
352 osRouterService.floatingIps().forEach(f -> {
353 if (f.getPortId() != null && f.getFloatingIpAddress() != null) {
354 Port port = osNetworkAdminService.port(f.getPortId());
355 if (port != null && port.getMacAddress() != null) {
Jian Lif3a28b02018-06-11 21:29:13 +0900356 floatingIpMacMap.put(f.getFloatingIpAddress(),
357 MacAddress.valueOf(port.getMacAddress()));
Jian Li60312252018-05-10 18:40:32 +0900358 }
359 }
360 });
361 }
362
Jian Lie1a39032018-06-19 21:49:36 +0900363 private void initPendingInstPorts() {
364 osRouterService.floatingIps().forEach(f -> {
365 if (f.getPortId() != null) {
366 Port port = osNetworkAdminService.port(f.getPortId());
367 if (port != null) {
368 if (!Strings.isNullOrEmpty(port.getDeviceId()) &&
369 instancePortService.instancePort(f.getPortId()) == null) {
370 pendingInstPortIds.put(f.getPortId(), f);
371 }
372 }
373 }
374 });
375 }
376
Jian Li60312252018-05-10 18:40:32 +0900377 /**
378 * Installs static ARP rules used in ARP BROAD_CAST mode.
Jian Li1064e4f2018-05-29 16:16:53 +0900379 *
380 * @param gateway gateway node
381 * @param install flow rule installation flag
382 */
383 private void setFloatingIpArpRuleForGateway(OpenstackNode gateway, boolean install) {
384 if (arpMode.equals(ARP_BROADCAST_MODE)) {
385
386 Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
387 Set<OpenstackNode> finalGws = Sets.newConcurrentHashSet();
388 finalGws.addAll(ImmutableSet.copyOf(completedGws));
389
390 if (install) {
391 if (completedGws.contains(gateway)) {
392 if (completedGws.size() > 1) {
393 finalGws.remove(gateway);
394 osRouterService.floatingIps().forEach(fip -> {
395 if (fip.getPortId() != null) {
396 setFloatingIpArpRule(fip, finalGws, false);
397 finalGws.add(gateway);
398 }
399 });
400 }
401 osRouterService.floatingIps().forEach(fip -> {
402 if (fip.getPortId() != null) {
403 setFloatingIpArpRule(fip, finalGws, true);
404 }
405 });
406 } else {
407 log.warn("Detected node should be included in completed gateway set");
408 }
409 } else {
410 if (!completedGws.contains(gateway)) {
411 finalGws.add(gateway);
412 osRouterService.floatingIps().forEach(fip -> {
413 if (fip.getPortId() != null) {
414 setFloatingIpArpRule(fip, finalGws, false);
415 }
416 });
417 finalGws.remove(gateway);
418 if (completedGws.size() >= 1) {
419 osRouterService.floatingIps().forEach(fip -> {
420 if (fip.getPortId() != null) {
421 setFloatingIpArpRule(fip, finalGws, true);
422 }
423 });
424 }
425 } else {
426 log.warn("Detected node should NOT be included in completed gateway set");
427 }
428 }
429 }
430 }
431
432 /**
Jian Li24ec59f2018-05-23 19:01:25 +0900433 * Installs/uninstalls ARP flow rules to the corresponding gateway by
434 * looking for compute node's device ID.
435 *
436 * @param fip floating IP
437 * @param port instance port
438 * @param gateways a collection of gateways
439 * @param install install flag
440 */
441 private void setFloatingIpArpRuleWithPortEvent(NetFloatingIP fip,
442 InstancePort port,
443 Set<OpenstackNode> gateways,
444 boolean install) {
445 if (arpMode.equals(ARP_BROADCAST_MODE)) {
446
447 OpenstackNode gw = getGwByInstancePort(gateways, port);
448
449 if (gw == null) {
450 return;
451 }
452
453 String macString = osNetworkAdminService.port(fip.getPortId()).getMacAddress();
454
455 setArpRule(fip, MacAddress.valueOf(macString), gw, install);
456 }
457 }
458
459 /**
Jian Li1064e4f2018-05-29 16:16:53 +0900460 * Installs static ARP rules used in ARP BROAD_CAST mode.
Jian Li60312252018-05-10 18:40:32 +0900461 * Note that, those rules will be only matched ARP_REQUEST packets,
462 * used for telling gateway node the mapped MAC address of requested IP,
463 * without the helps from controller.
464 *
465 * @param fip floating IP address
Jian Li1064e4f2018-05-29 16:16:53 +0900466 * @param gateways a set of gateway nodes
Jian Li60312252018-05-10 18:40:32 +0900467 * @param install flow rule installation flag
468 */
Jian Li1064e4f2018-05-29 16:16:53 +0900469 private synchronized void setFloatingIpArpRule(NetFloatingIP fip,
470 Set<OpenstackNode> gateways,
471 boolean install) {
Jian Li60312252018-05-10 18:40:32 +0900472 if (arpMode.equals(ARP_BROADCAST_MODE)) {
473
474 if (fip == null) {
475 log.warn("Failed to set ARP broadcast rule for floating IP");
476 return;
477 }
478
Jian Lif3a28b02018-06-11 21:29:13 +0900479 MacAddress targetMac;
480 InstancePort instPort;
Jian Li60312252018-05-10 18:40:32 +0900481
482 if (install) {
483 if (fip.getPortId() != null) {
Jian Lif3a28b02018-06-11 21:29:13 +0900484 String macString = osNetworkAdminService.port(fip.getPortId()).getMacAddress();
485 targetMac = MacAddress.valueOf(macString);
486 floatingIpMacMap.put(fip.getFloatingIpAddress(), targetMac);
Jian Li60312252018-05-10 18:40:32 +0900487 } else {
488 log.trace("Unknown target ARP request for {}, ignore it",
489 fip.getFloatingIpAddress());
490 return;
491 }
492 } else {
Jian Lif3a28b02018-06-11 21:29:13 +0900493 targetMac = floatingIpMacMap.get(fip.getFloatingIpAddress());
Jian Li60312252018-05-10 18:40:32 +0900494 }
495
Jian Lif3a28b02018-06-11 21:29:13 +0900496 instPort = instancePortService.instancePort(targetMac);
497
498 // in VM purge case, we will have null instance port
499 if (instPort == null) {
Jian Lie1a39032018-06-19 21:49:36 +0900500 instPort = tobeRemovedInstPorts.get(targetMac);
501 tobeRemovedInstPorts.remove(targetMac);
502 }
503
504 if (instPort == null) {
505 instPort = terminatedInstPorts.get(targetMac);
Jian Lif3a28b02018-06-11 21:29:13 +0900506 }
Jian Li60312252018-05-10 18:40:32 +0900507
Jian Lia171a432018-06-11 11:52:11 +0900508 OpenstackNode gw = getGwByInstancePort(gateways, instPort);
Jian Li1064e4f2018-05-29 16:16:53 +0900509
510 if (gw == null) {
511 return;
512 }
513
Jian Li24ec59f2018-05-23 19:01:25 +0900514 setArpRule(fip, targetMac, gw, install);
515 }
516 }
Jian Li60312252018-05-10 18:40:32 +0900517
Jian Li24ec59f2018-05-23 19:01:25 +0900518 private void setArpRule(NetFloatingIP fip, MacAddress targetMac,
519 OpenstackNode gateway, boolean install) {
520 TrafficSelector selector = DefaultTrafficSelector.builder()
521 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
522 .matchArpOp(ARP.OP_REQUEST)
523 .matchArpTpa(Ip4Address.valueOf(fip.getFloatingIpAddress()))
524 .build();
Jian Li60312252018-05-10 18:40:32 +0900525
Jian Li24ec59f2018-05-23 19:01:25 +0900526 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
527 .setArpOp(ARP.OP_REPLY)
528 .setArpSha(targetMac)
529 .setArpSpa(Ip4Address.valueOf(fip.getFloatingIpAddress()))
530 .setOutput(PortNumber.IN_PORT)
531 .build();
Jian Li60312252018-05-10 18:40:32 +0900532
Jian Li24ec59f2018-05-23 19:01:25 +0900533 osFlowRuleService.setRule(
534 appId,
535 gateway.intgBridge(),
536 selector,
537 treatment,
538 PRIORITY_ARP_GATEWAY_RULE,
539 GW_COMMON_TABLE,
540 install
541 );
542
543 if (install) {
544 log.info("Install ARP Rule for Floating IP {}",
545 fip.getFloatingIpAddress());
546 } else {
547 log.info("Uninstall ARP Rule for Floating IP {}",
548 fip.getFloatingIpAddress());
Jian Li60312252018-05-10 18:40:32 +0900549 }
550 }
551
552 /**
553 * An internal router event listener, intended to install/uninstall
554 * ARP rules for forwarding packets created from floating IPs.
555 */
556 private class InternalRouterEventListener implements OpenstackRouterListener {
557
558 @Override
559 public boolean isRelevant(OpenstackRouterEvent event) {
560 // do not allow to proceed without leadership
561 NodeId leader = leadershipService.getLeader(appId.name());
562 return Objects.equals(localNodeId, leader);
563 }
564
565 @Override
566 public void event(OpenstackRouterEvent event) {
Jian Li1064e4f2018-05-29 16:16:53 +0900567
568 Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
569
Jian Li60312252018-05-10 18:40:32 +0900570 switch (event.type()) {
571 case OPENSTACK_ROUTER_CREATED:
572 eventExecutor.execute(() ->
573 // add a router with external gateway
574 setFakeGatewayArpRule(event.subject(), true)
575 );
576 break;
577 case OPENSTACK_ROUTER_REMOVED:
578 eventExecutor.execute(() ->
579 // remove a router with external gateway
580 setFakeGatewayArpRule(event.subject(), false)
581 );
582 break;
583 case OPENSTACK_ROUTER_GATEWAY_ADDED:
584 eventExecutor.execute(() ->
585 // add a gateway manually after adding a router
586 setFakeGatewayArpRule(event.externalGateway(), true)
587 );
588 break;
589 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
590 eventExecutor.execute(() ->
591 // remove a gateway from an existing router
592 setFakeGatewayArpRule(event.externalGateway(), false)
593 );
594 break;
595 case OPENSTACK_FLOATING_IP_ASSOCIATED:
Jian Lie1a39032018-06-19 21:49:36 +0900596
597 if (instancePortService.instancePort(event.portId()) == null) {
598 log.info("Try to associate the fip {} with a terminated VM",
599 event.floatingIp().getFloatingIpAddress());
600 pendingInstPortIds.put(event.portId(), event.floatingIp());
601 return;
602 }
603
Jian Li60312252018-05-10 18:40:32 +0900604 eventExecutor.execute(() ->
605 // associate a floating IP with an existing VM
Jian Li1064e4f2018-05-29 16:16:53 +0900606 setFloatingIpArpRule(event.floatingIp(), completedGws, true)
Jian Li60312252018-05-10 18:40:32 +0900607 );
608 break;
609 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
Jian Lie1a39032018-06-19 21:49:36 +0900610
611 MacAddress mac = floatingIpMacMap.get(event.floatingIp().getFloatingIpAddress());
612
613 if (mac != null && !tobeRemovedInstPorts.containsKey(mac) &&
614 terminatedInstPorts.containsKey(mac)) {
615 tobeRemovedInstPorts.put(mac, terminatedInstPorts.get(mac));
616 }
617
618 if (instancePortService.instancePort(event.portId()) == null) {
619
620 if (pendingInstPortIds.containsKey(event.portId())) {
621 log.info("Try to disassociate the fip {} with a terminated VM",
622 event.floatingIp().getFloatingIpAddress());
623 pendingInstPortIds.remove(event.portId());
624 return;
625 }
626 }
627
Jian Li60312252018-05-10 18:40:32 +0900628 eventExecutor.execute(() ->
629 // disassociate a floating IP with the existing VM
Jian Li1064e4f2018-05-29 16:16:53 +0900630 setFloatingIpArpRule(event.floatingIp(), completedGws, false)
Jian Li60312252018-05-10 18:40:32 +0900631 );
632 break;
633 case OPENSTACK_FLOATING_IP_CREATED:
634 eventExecutor.execute(() -> {
635 NetFloatingIP osFip = event.floatingIp();
636
637 // during floating IP creation, if the floating IP is
638 // associated with any port of VM, then we will set
639 // floating IP related ARP rules to gateway node
640 if (!Strings.isNullOrEmpty(osFip.getPortId())) {
Jian Li1064e4f2018-05-29 16:16:53 +0900641 setFloatingIpArpRule(osFip, completedGws, true);
Jian Li60312252018-05-10 18:40:32 +0900642 }
643 });
644 break;
645 case OPENSTACK_FLOATING_IP_REMOVED:
646 eventExecutor.execute(() -> {
647 NetFloatingIP osFip = event.floatingIp();
648
649 // during floating IP deletion, if the floating IP is
650 // still associated with any port of VM, then we will
651 // remove floating IP related ARP rules from gateway node
652 if (!Strings.isNullOrEmpty(osFip.getPortId())) {
Jian Li1064e4f2018-05-29 16:16:53 +0900653 setFloatingIpArpRule(event.floatingIp(), completedGws, false);
Jian Li60312252018-05-10 18:40:32 +0900654 }
655 });
656 break;
657 default:
658 // do nothing for the other events
659 break;
660 }
661 }
662
Jian Li4df657b2018-05-29 16:39:00 +0900663 private Set<IP> getExternalGatewaySnatIps(ExternalGateway extGw) {
664 return osNetworkAdminService.ports().stream()
665 .filter(port ->
666 Objects.equals(port.getNetworkId(), extGw.getNetworkId()))
667 .filter(port ->
668 Objects.equals(port.getDeviceOwner(), DEVICE_OWNER_ROUTER_GW))
669 .flatMap(port -> port.getFixedIps().stream())
670 .collect(Collectors.toSet());
671 }
672
Jian Li60312252018-05-10 18:40:32 +0900673 private void setFakeGatewayArpRule(ExternalGateway extGw, boolean install) {
674 if (arpMode.equals(ARP_BROADCAST_MODE)) {
675
676 if (extGw == null) {
677 return;
678 }
679
Jian Li4df657b2018-05-29 16:39:00 +0900680 Set<IP> ips = getExternalGatewaySnatIps(extGw);
Jian Li60312252018-05-10 18:40:32 +0900681
Jian Li4df657b2018-05-29 16:39:00 +0900682 ips.forEach(ip -> {
683 TrafficSelector selector = DefaultTrafficSelector.builder()
684 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
685 .matchArpOp(ARP.OP_REQUEST)
686 .matchArpTpa(Ip4Address.valueOf(ip.getIpAddress()))
687 .build();
Jian Li60312252018-05-10 18:40:32 +0900688
Jian Li4df657b2018-05-29 16:39:00 +0900689 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
690 .setArpOp(ARP.OP_REPLY)
691 .setArpSha(MacAddress.valueOf(gatewayMac))
692 .setArpSpa(Ip4Address.valueOf(ip.getIpAddress()))
693 .setOutput(PortNumber.IN_PORT)
694 .build();
Jian Li60312252018-05-10 18:40:32 +0900695
Jian Li4df657b2018-05-29 16:39:00 +0900696 osNodeService.completeNodes(GATEWAY).forEach(n ->
697 osFlowRuleService.setRule(
698 appId,
699 n.intgBridge(),
700 selector,
701 treatment,
702 PRIORITY_ARP_GATEWAY_RULE,
703 GW_COMMON_TABLE,
704 install
705 )
706 );
Jian Li60312252018-05-10 18:40:32 +0900707
Jian Li4df657b2018-05-29 16:39:00 +0900708 if (install) {
709 log.info("Install ARP Rule for Gateway Snat {}", ip.getIpAddress());
710 } else {
711 log.info("Uninstall ARP Rule for Gateway Snat {}", ip.getIpAddress());
712 }
713 });
Jian Li60312252018-05-10 18:40:32 +0900714 }
715 }
716
717 private void setFakeGatewayArpRule(Router router, boolean install) {
718 setFakeGatewayArpRule(router.getExternalGatewayInfo(), install);
719 }
720 }
721
Jian Lie1a39032018-06-19 21:49:36 +0900722 private class InternalInstancePortListener implements InstancePortListener {
Jian Li60312252018-05-10 18:40:32 +0900723
724 @Override
Jian Lie1a39032018-06-19 21:49:36 +0900725 public boolean isRelevant(InstancePortEvent event) {
726 // do not allow to proceed without leadership
727 NodeId leader = leadershipService.getLeader(appId.name());
728 return Objects.equals(localNodeId, leader);
Jian Li60312252018-05-10 18:40:32 +0900729 }
730
731 @Override
Jian Lie1a39032018-06-19 21:49:36 +0900732 public void event(InstancePortEvent event) {
733 InstancePort instPort = event.subject();
734
735 Set<NetFloatingIP> ips = osRouterService.floatingIps();
736 NetFloatingIP fip = associatedFloatingIp(instPort, ips);
737 Set<OpenstackNode> gateways = osNodeService.completeNodes(GATEWAY);
738
Jian Li60312252018-05-10 18:40:32 +0900739 switch (event.type()) {
Jian Lie1a39032018-06-19 21:49:36 +0900740 case OPENSTACK_INSTANCE_PORT_DETECTED:
741 terminatedInstPorts.remove(instPort.macAddress());
742
743 if (pendingInstPortIds.containsKey(instPort.portId())) {
744 Set<OpenstackNode> completedGws =
745 osNodeService.completeNodes(GATEWAY);
746 setFloatingIpArpRule(pendingInstPortIds.get(instPort.portId()),
747 completedGws, true);
748 pendingInstPortIds.remove(instPort.portId());
749 }
750
Jian Li60312252018-05-10 18:40:32 +0900751 break;
Jian Lie1a39032018-06-19 21:49:36 +0900752
753 case OPENSTACK_INSTANCE_PORT_VANISHED:
754 terminatedInstPorts.put(instPort.macAddress(), instPort);
755 break;
756
757 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
758
759 if (gateways.size() == 1) {
760 return;
761 }
762
763 if (fip != null && isAssociatedWithVM(osNetworkService, fip)) {
764 migrationPool.put(fip.getFloatingIpAddress(), event.subject().deviceId());
765
766 eventExecutor.execute(() -> {
767 setFloatingIpArpRuleWithPortEvent(fip, event.subject(),
768 gateways, true);
769 });
770 }
771
772 break;
773 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
774
775 if (gateways.size() == 1) {
776 return;
777 }
778
779 if (fip != null && isAssociatedWithVM(osNetworkService, fip)) {
780 DeviceId newDeviceId = migrationPool.get(fip.getFloatingIpAddress());
781 DeviceId oldDeviceId = event.subject().deviceId();
782 migrationPool.remove(fip.getFloatingIpAddress());
783
784 OpenstackNode oldGw = getGwByComputeDevId(gateways, oldDeviceId);
785 OpenstackNode newGw = getGwByComputeDevId(gateways, newDeviceId);
786
787 if (oldGw != null && oldGw.equals(newGw)) {
788 return;
789 }
790
791 eventExecutor.execute(() ->
792 setFloatingIpArpRuleWithPortEvent(fip, event.subject(),
793 gateways, false));
794 }
795 break;
Jian Li60312252018-05-10 18:40:32 +0900796 default:
797 break;
798 }
799 }
Jian Lie1a39032018-06-19 21:49:36 +0900800 }
Jian Li60312252018-05-10 18:40:32 +0900801
Jian Lie1a39032018-06-19 21:49:36 +0900802 private class InternalOpenstackNetworkListener implements OpenstackNetworkListener {
803
804 @Override
805 public boolean isRelevant(OpenstackNetworkEvent event) {
806 // do not allow to proceed without leadership
807 NodeId leader = leadershipService.getLeader(appId.name());
808 return Objects.equals(localNodeId, leader);
Jian Li60312252018-05-10 18:40:32 +0900809 }
810
Jian Lie1a39032018-06-19 21:49:36 +0900811 @Override
812 public void event(OpenstackNetworkEvent event) {
813 switch (event.type()) {
814 case OPENSTACK_PORT_REMOVED:
815 Port osPort = event.port();
816 MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
817 if (terminatedInstPorts.containsKey(mac)) {
818 tobeRemovedInstPorts.put(mac, terminatedInstPorts.get(mac));
819 terminatedInstPorts.remove(mac);
820 }
821 break;
822 default:
823 break;
824 }
Jian Li60312252018-05-10 18:40:32 +0900825 }
826 }
Jian Lif96685c2018-05-21 14:14:16 +0900827
828 private class InternalNodeEventListener implements OpenstackNodeListener {
829
830 @Override
831 public boolean isRelevant(OpenstackNodeEvent event) {
832 // do not allow to proceed without leadership
833 NodeId leader = leadershipService.getLeader(appId.name());
Jian Li51b844c2018-05-31 10:59:03 +0900834 return Objects.equals(localNodeId, leader) && event.subject().type() == GATEWAY;
Jian Lif96685c2018-05-21 14:14:16 +0900835 }
836
837 @Override
838 public void event(OpenstackNodeEvent event) {
839 OpenstackNode osNode = event.subject();
840 switch (event.type()) {
841 case OPENSTACK_NODE_COMPLETE:
Jian Li51b844c2018-05-31 10:59:03 +0900842 setDefaultArpRule(osNode, true);
843 setFloatingIpArpRuleForGateway(osNode, true);
Jian Li1064e4f2018-05-29 16:16:53 +0900844
Jian Lif3a28b02018-06-11 21:29:13 +0900845 // initialize FloatingIp to Mac map
846 initFloatingIpMacMap();
847
Jian Lie1a39032018-06-19 21:49:36 +0900848 // initialize pendingInstPorts
849 initPendingInstPorts();
850
Jian Lif96685c2018-05-21 14:14:16 +0900851 break;
852 case OPENSTACK_NODE_INCOMPLETE:
Jian Li51b844c2018-05-31 10:59:03 +0900853 setDefaultArpRule(osNode, false);
854 setFloatingIpArpRuleForGateway(osNode, false);
Jian Lif96685c2018-05-21 14:14:16 +0900855 break;
856 default:
857 break;
858 }
859 }
860
861 private void setDefaultArpRule(OpenstackNode osNode, boolean install) {
862 switch (arpMode) {
863 case ARP_PROXY_MODE:
864 setDefaultArpRuleForProxyMode(osNode, install);
865 break;
866 case ARP_BROADCAST_MODE:
867 setDefaultArpRuleForBroadcastMode(osNode, install);
868 break;
869 default:
870 log.warn("Invalid ARP mode {}. Please use either " +
871 "broadcast or proxy mode.", arpMode);
872 break;
873 }
874 }
875
876 private void setDefaultArpRuleForProxyMode(OpenstackNode osNode, boolean install) {
877 TrafficSelector selector = DefaultTrafficSelector.builder()
878 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
879 .build();
880
881 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
882 .punt()
883 .build();
884
885 osFlowRuleService.setRule(
886 appId,
887 osNode.intgBridge(),
888 selector,
889 treatment,
890 PRIORITY_ARP_CONTROL_RULE,
Jian Li8abf2fe2018-06-12 18:42:30 +0900891 GW_COMMON_TABLE,
Jian Lif96685c2018-05-21 14:14:16 +0900892 install
893 );
894 }
895
896 private void setDefaultArpRuleForBroadcastMode(OpenstackNode osNode, boolean install) {
897 // we only match ARP_REPLY in gateway node, because controller
898 // somehow need to process ARP_REPLY which is issued from
899 // external router...
900 TrafficSelector selector = DefaultTrafficSelector.builder()
901 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
902 .matchArpOp(ARP.OP_REPLY)
903 .build();
904
905 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
906 .punt()
907 .build();
908
909 osFlowRuleService.setRule(
910 appId,
911 osNode.intgBridge(),
912 selector,
913 treatment,
914 PRIORITY_ARP_CONTROL_RULE,
Jian Li8abf2fe2018-06-12 18:42:30 +0900915 GW_COMMON_TABLE,
Jian Lif96685c2018-05-21 14:14:16 +0900916 install
917 );
918 }
919 }
Daniel Park81a61a12016-02-26 08:24:44 +0900920}