blob: ee90e0d8f5d140c72154b650905b1db368e810ca [file] [log] [blame]
Hyunsun Moon44aac662017-02-18 02:07:01 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Hyunsun Moon44aac662017-02-18 02:07:01 +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 */
16package org.onosproject.openstacknetworking.impl;
17
18import com.google.common.base.Strings;
Hyunsun Moon44aac662017-02-18 02:07:01 +090019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.onlab.packet.Ethernet;
25import org.onlab.packet.ICMP;
26import org.onlab.packet.IPv4;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.MacAddress;
daniel park576969a2018-03-09 07:07:41 +090029import org.onlab.packet.VlanId;
sangho247232c2017-08-24 17:22:08 +090030import org.onlab.util.KryoNamespace;
Hyunsun Moon44aac662017-02-18 02:07:01 +090031import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090033import org.onosproject.net.DeviceId;
Hyunsun Moon44aac662017-02-18 02:07:01 +090034import org.onosproject.net.flow.DefaultTrafficTreatment;
Hyunsun Moon44aac662017-02-18 02:07:01 +090035import org.onosproject.net.flow.TrafficTreatment;
36import org.onosproject.net.packet.DefaultOutboundPacket;
37import org.onosproject.net.packet.InboundPacket;
38import org.onosproject.net.packet.OutboundPacket;
39import org.onosproject.net.packet.PacketContext;
Hyunsun Moon44aac662017-02-18 02:07:01 +090040import org.onosproject.net.packet.PacketProcessor;
41import org.onosproject.net.packet.PacketService;
42import org.onosproject.openstacknetworking.api.Constants;
daniel park576969a2018-03-09 07:07:41 +090043import org.onosproject.openstacknetworking.api.ExternalPeerRouter;
Hyunsun Moon44aac662017-02-18 02:07:01 +090044import org.onosproject.openstacknetworking.api.InstancePort;
45import org.onosproject.openstacknetworking.api.InstancePortService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090046import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
sangho36721992017-08-03 11:13:17 +090047import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090048import org.onosproject.openstacknode.api.OpenstackNode;
Hyunsun Moon0d457362017-06-27 17:19:41 +090049import org.onosproject.openstacknode.api.OpenstackNodeService;
sangho247232c2017-08-24 17:22:08 +090050import org.onosproject.store.serializers.KryoNamespaces;
51import org.onosproject.store.service.ConsistentMap;
52import org.onosproject.store.service.Serializer;
53import org.onosproject.store.service.StorageService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090054import org.openstack4j.model.network.ExternalGateway;
55import org.openstack4j.model.network.IP;
56import org.openstack4j.model.network.Port;
57import org.openstack4j.model.network.Router;
58import org.openstack4j.model.network.RouterInterface;
59import org.openstack4j.model.network.Subnet;
sangho36721992017-08-03 11:13:17 +090060import org.openstack4j.openstack.networking.domain.NeutronIP;
Hyunsun Moon44aac662017-02-18 02:07:01 +090061import org.slf4j.Logger;
62
63import java.nio.ByteBuffer;
Hyunsun Moon44aac662017-02-18 02:07:01 +090064import java.util.Objects;
sangho36721992017-08-03 11:13:17 +090065import java.util.Optional;
Hyunsun Moon44aac662017-02-18 02:07:01 +090066import java.util.Set;
67import java.util.concurrent.ExecutorService;
68import java.util.stream.Collectors;
69
sangho247232c2017-08-24 17:22:08 +090070import static com.google.common.base.Preconditions.checkArgument;
Hyunsun Moon44aac662017-02-18 02:07:01 +090071import static java.util.concurrent.Executors.newSingleThreadExecutor;
72import static org.onlab.util.Tools.groupedThreads;
sangho36721992017-08-03 11:13:17 +090073import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC;
74import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
Hyunsun Moon0d457362017-06-27 17:19:41 +090075import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Hyunsun Moon44aac662017-02-18 02:07:01 +090076import static org.slf4j.LoggerFactory.getLogger;
77
78
79/**
80 * Handles ICMP packet received from a gateway node.
81 * For a request for virtual network subnet gateway, it generates fake ICMP reply.
82 * For a request for the external network, it does source NAT with the public IP and
83 * forward the request to the external only if the requested virtual subnet has
84 * external connectivity.
85 */
86@Component(immediate = true)
87public class OpenstackRoutingIcmpHandler {
88
89 protected final Logger log = getLogger(getClass());
90
91 private static final String ERR_REQ = "Failed to handle ICMP request: ";
sangho247232c2017-08-24 17:22:08 +090092 private static final String ERR_DUPLICATE = " already exists";
Hyunsun Moon44aac662017-02-18 02:07:01 +090093
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected CoreService coreService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected PacketService packetService;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho247232c2017-08-24 17:22:08 +0900101 protected StorageService storageService;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900104 protected OpenstackNodeService osNodeService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected InstancePortService instancePortService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected OpenstackNetworkService osNetworkService;
111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected OpenstackRouterService osRouterService;
114
115 private final ExecutorService eventExecutor = newSingleThreadExecutor(
116 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
sangho072c4dd2017-05-17 10:45:21 +0900117 private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
sangho247232c2017-08-24 17:22:08 +0900118 private ConsistentMap<String, InstancePort> icmpInfoMap;
119
120 private static final KryoNamespace SERIALIZER_ICMP_MAP = KryoNamespace.newBuilder()
121 .register(KryoNamespaces.API)
122 .register(InstancePort.class)
Jian Liec5c32b2018-07-13 14:28:58 +0900123 .register(DefaultInstancePort.class)
124 .register(InstancePort.State.class)
sangho247232c2017-08-24 17:22:08 +0900125 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900126
127 private ApplicationId appId;
128
129 @Activate
130 protected void activate() {
131 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
132 packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900133
sangho247232c2017-08-24 17:22:08 +0900134 icmpInfoMap = storageService.<String, InstancePort>consistentMapBuilder()
135 .withSerializer(Serializer.using(SERIALIZER_ICMP_MAP))
136 .withName("openstack-icmpmap")
137 .withApplicationId(appId)
138 .build();
139
Hyunsun Moon44aac662017-02-18 02:07:01 +0900140 log.info("Started");
141 }
142
143 @Deactivate
144 protected void deactivate() {
145 packetService.removeProcessor(packetProcessor);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900146 eventExecutor.shutdown();
147
148 log.info("Stopped");
149 }
150
Hyunsun Moon44aac662017-02-18 02:07:01 +0900151 private void processIcmpPacket(PacketContext context, Ethernet ethernet) {
152 IPv4 ipPacket = (IPv4) ethernet.getPayload();
153 ICMP icmp = (ICMP) ipPacket.getPayload();
154 log.trace("Processing ICMP packet source MAC:{}, source IP:{}," +
155 "dest MAC:{}, dest IP:{}",
156 ethernet.getSourceMAC(),
157 IpAddress.valueOf(ipPacket.getSourceAddress()),
158 ethernet.getDestinationMAC(),
159 IpAddress.valueOf(ipPacket.getDestinationAddress()));
160
161 switch (icmp.getIcmpType()) {
162 case ICMP.TYPE_ECHO_REQUEST:
163 handleEchoRequest(
164 context.inPacket().receivedFrom().deviceId(),
165 ethernet.getSourceMAC(),
166 ipPacket,
167 icmp);
168 context.block();
169 break;
170 case ICMP.TYPE_ECHO_REPLY:
171 handleEchoReply(ipPacket, icmp);
172 context.block();
173 break;
174 default:
175 break;
176 }
177 }
178
179 private void handleEchoRequest(DeviceId srcDevice, MacAddress srcMac, IPv4 ipPacket,
180 ICMP icmp) {
181 InstancePort instPort = instancePortService.instancePort(srcMac);
182 if (instPort == null) {
daniel park576969a2018-03-09 07:07:41 +0900183 log.info(ERR_REQ + "unknown source host(MAC:{})", srcMac);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900184 return;
185 }
186
187 IpAddress srcIp = IpAddress.valueOf(ipPacket.getSourceAddress());
188 Subnet srcSubnet = getSourceSubnet(instPort, srcIp);
189 if (srcSubnet == null) {
daniel park576969a2018-03-09 07:07:41 +0900190 log.info(ERR_REQ + "unknown source subnet(IP:{})", srcIp);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900191 return;
192 }
193 if (Strings.isNullOrEmpty(srcSubnet.getGateway())) {
daniel park576969a2018-03-09 07:07:41 +0900194 log.info(ERR_REQ + "source subnet(ID:{}, CIDR:{}) has no gateway",
Hyunsun Moon44aac662017-02-18 02:07:01 +0900195 srcSubnet.getId(), srcSubnet.getCidr());
196 return;
197 }
198
199 if (isForSubnetGateway(IpAddress.valueOf(ipPacket.getDestinationAddress()),
200 srcSubnet)) {
201 // this is a request for the subnet gateway
202 processRequestForGateway(ipPacket, instPort);
203 } else {
daniel park859db252018-04-18 16:00:51 +0900204 ExternalPeerRouter externalPeerRouter = externalPeerRouter(srcSubnet);
205 if (externalPeerRouter == null) {
206 log.info(ERR_REQ + "failed to get external peer router");
207 return;
208 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900209 // this is a request for the external network
210 IpAddress externalIp = getExternalIp(srcSubnet);
211 if (externalIp == null) {
212 return;
213 }
daniel parkeeb8e042018-02-21 14:06:58 +0900214
daniel park576969a2018-03-09 07:07:41 +0900215 sendRequestForExternal(ipPacket, srcDevice, externalIp, externalPeerRouter);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900216 String icmpInfoKey = String.valueOf(getIcmpId(icmp))
217 .concat(String.valueOf(externalIp.getIp4Address().toInt()))
218 .concat(String.valueOf(ipPacket.getDestinationAddress()));
daniel parkeeb8e042018-02-21 14:06:58 +0900219 try {
220 icmpInfoMap.compute(icmpInfoKey, (id, existing) -> {
221 checkArgument(existing == null, ERR_DUPLICATE);
222 return instPort;
223 });
224 } catch (IllegalArgumentException e) {
225 log.warn("Exception occurred because of {}", e.toString());
226 }
227
Hyunsun Moon44aac662017-02-18 02:07:01 +0900228 }
229 }
230
daniel park576969a2018-03-09 07:07:41 +0900231 private ExternalPeerRouter externalPeerRouter(Subnet subnet) {
daniel parkeeb8e042018-02-21 14:06:58 +0900232 RouterInterface osRouterIface = osRouterService.routerInterfaces().stream()
233 .filter(i -> Objects.equals(i.getSubnetId(), subnet.getId()))
234 .findAny().orElse(null);
235 if (osRouterIface == null) {
236 return null;
237 }
238
239 Router osRouter = osRouterService.router(osRouterIface.getId());
240 if (osRouter == null) {
241 return null;
242 }
243 if (osRouter.getExternalGatewayInfo() == null) {
244 return null;
245 }
246
247 ExternalGateway exGatewayInfo = osRouter.getExternalGatewayInfo();
248
daniel park576969a2018-03-09 07:07:41 +0900249 return osNetworkService.externalPeerRouter(exGatewayInfo);
daniel parkeeb8e042018-02-21 14:06:58 +0900250 }
251
Hyunsun Moon44aac662017-02-18 02:07:01 +0900252 private void handleEchoReply(IPv4 ipPacket, ICMP icmp) {
253 String icmpInfoKey = String.valueOf(getIcmpId(icmp))
254 .concat(String.valueOf(ipPacket.getDestinationAddress()))
255 .concat(String.valueOf(ipPacket.getSourceAddress()));
256
sangho247232c2017-08-24 17:22:08 +0900257 if (icmpInfoMap.get(icmpInfoKey) != null) {
258 processReplyFromExternal(ipPacket, icmpInfoMap.get(icmpInfoKey).value());
259 icmpInfoMap.remove(icmpInfoKey);
260 } else {
261 log.warn("No ICMP Info for ICMP packet");
262 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900263 }
264
265 private Subnet getSourceSubnet(InstancePort instance, IpAddress srcIp) {
266 Port osPort = osNetworkService.port(instance.portId());
267 IP fixedIp = osPort.getFixedIps().stream()
268 .filter(ip -> IpAddress.valueOf(ip.getIpAddress()).equals(srcIp))
269 .findAny().orElse(null);
270 if (fixedIp == null) {
271 return null;
272 }
273 return osNetworkService.subnet(fixedIp.getSubnetId());
274 }
275
276 private boolean isForSubnetGateway(IpAddress dstIp, Subnet srcSubnet) {
277 RouterInterface osRouterIface = osRouterService.routerInterfaces().stream()
278 .filter(i -> Objects.equals(i.getSubnetId(), srcSubnet.getId()))
279 .findAny().orElse(null);
280 if (osRouterIface == null) {
281 log.trace(ERR_REQ + "source subnet(ID:{}, CIDR:{}) has no router",
282 srcSubnet.getId(), srcSubnet.getCidr());
283 return false;
284 }
285
286 Router osRouter = osRouterService.router(osRouterIface.getId());
287 Set<IpAddress> routableGateways = osRouterService.routerInterfaces(osRouter.getId())
288 .stream()
289 .map(iface -> osNetworkService.subnet(iface.getSubnetId()).getGateway())
290 .map(IpAddress::valueOf)
291 .collect(Collectors.toSet());
292
293 return routableGateways.contains(dstIp);
294 }
295
296 private IpAddress getExternalIp(Subnet srcSubnet) {
297 RouterInterface osRouterIface = osRouterService.routerInterfaces().stream()
298 .filter(i -> Objects.equals(i.getSubnetId(), srcSubnet.getId()))
299 .findAny().orElse(null);
300 if (osRouterIface == null) {
301 final String error = String.format(ERR_REQ +
302 "subnet(ID:%s, CIDR:%s) is not connected to any router",
303 srcSubnet.getId(), srcSubnet.getCidr());
304 throw new IllegalStateException(error);
305 }
306
307 Router osRouter = osRouterService.router(osRouterIface.getId());
308 if (osRouter.getExternalGatewayInfo() == null) {
309 final String error = String.format(ERR_REQ +
310 "router(ID:%s, name:%s) does not have external gateway",
311 osRouter.getId(), osRouter.getName());
312 throw new IllegalStateException(error);
313 }
314
315 // TODO fix openstack4j for ExternalGateway provides external fixed IP list
316 ExternalGateway exGatewayInfo = osRouter.getExternalGatewayInfo();
317 Port exGatewayPort = osNetworkService.ports(exGatewayInfo.getNetworkId())
318 .stream()
319 .filter(port -> Objects.equals(port.getDeviceId(), osRouter.getId()))
320 .findAny().orElse(null);
321 if (exGatewayPort == null) {
322 final String error = String.format(ERR_REQ +
323 "no external gateway port for router (ID:%s, name:%s)",
324 osRouter.getId(), osRouter.getName());
325 throw new IllegalStateException(error);
326 }
sangho36721992017-08-03 11:13:17 +0900327 Optional<NeutronIP> externalIpAddress = (Optional<NeutronIP>) exGatewayPort.getFixedIps().stream().findFirst();
328 if (!externalIpAddress.isPresent() || externalIpAddress.get().getIpAddress() == null) {
329 final String error = String.format(ERR_REQ +
330 "no external gateway IP address for router (ID:%s, name:%s)",
331 osRouter.getId(), osRouter.getName());
332 throw new IllegalStateException(error);
333 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900334
sangho36721992017-08-03 11:13:17 +0900335 return IpAddress.valueOf(externalIpAddress.get().getIpAddress());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900336 }
337
338 private void processRequestForGateway(IPv4 ipPacket, InstancePort instPort) {
339 ICMP icmpReq = (ICMP) ipPacket.getPayload();
340 icmpReq.setChecksum((short) 0);
341 icmpReq.setIcmpType(ICMP.TYPE_ECHO_REPLY).resetChecksum();
342
343 int destinationAddress = ipPacket.getSourceAddress();
344
345 ipPacket.setSourceAddress(ipPacket.getDestinationAddress())
346 .setDestinationAddress(destinationAddress)
347 .resetChecksum();
348
349 ipPacket.setPayload(icmpReq);
350 Ethernet icmpReply = new Ethernet();
351 icmpReply.setEtherType(Ethernet.TYPE_IPV4)
352 .setSourceMACAddress(Constants.DEFAULT_GATEWAY_MAC)
353 .setDestinationMACAddress(instPort.macAddress())
354 .setPayload(ipPacket);
355
356 sendReply(icmpReply, instPort);
357 }
358
daniel parkeeb8e042018-02-21 14:06:58 +0900359 private void sendRequestForExternal(IPv4 ipPacket, DeviceId srcDevice,
daniel park576969a2018-03-09 07:07:41 +0900360 IpAddress srcNatIp, ExternalPeerRouter externalPeerRouter) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900361 ICMP icmpReq = (ICMP) ipPacket.getPayload();
362 icmpReq.resetChecksum();
363 ipPacket.setSourceAddress(srcNatIp.getIp4Address().toInt()).resetChecksum();
364 ipPacket.setPayload(icmpReq);
365
366 Ethernet icmpRequestEth = new Ethernet();
367 icmpRequestEth.setEtherType(Ethernet.TYPE_IPV4)
368 .setSourceMACAddress(DEFAULT_GATEWAY_MAC)
Jian Li5e2ad4a2018-07-16 13:40:53 +0900369 .setDestinationMACAddress(externalPeerRouter.macAddress());
daniel park576969a2018-03-09 07:07:41 +0900370
Jian Li5e2ad4a2018-07-16 13:40:53 +0900371 if (!externalPeerRouter.vlanId().equals(VlanId.NONE)) {
372 icmpRequestEth.setVlanID(externalPeerRouter.vlanId().toShort());
daniel park576969a2018-03-09 07:07:41 +0900373 }
374
375 icmpRequestEth.setPayload(ipPacket);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900376
Hyunsun Moon0d457362017-06-27 17:19:41 +0900377 OpenstackNode osNode = osNodeService.node(srcDevice);
378 if (osNode == null) {
379 final String error = String.format("Cannot find openstack node for %s",
380 srcDevice);
381 throw new IllegalStateException(error);
382 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900383 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
daniel parkeeb8e042018-02-21 14:06:58 +0900384 .setOutput(osNode.uplinkPortNum())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900385 .build();
386
387 OutboundPacket packet = new DefaultOutboundPacket(
388 srcDevice,
389 treatment,
390 ByteBuffer.wrap(icmpRequestEth.serialize()));
391
392 packetService.emit(packet);
393 }
394
395 private void processReplyFromExternal(IPv4 ipPacket, InstancePort instPort) {
daniel park576969a2018-03-09 07:07:41 +0900396
397 if (instPort.networkId() == null) {
398 return;
399 }
400
Hyunsun Moon44aac662017-02-18 02:07:01 +0900401 ICMP icmpReply = (ICMP) ipPacket.getPayload();
daniel park576969a2018-03-09 07:07:41 +0900402
Hyunsun Moon44aac662017-02-18 02:07:01 +0900403 icmpReply.resetChecksum();
404
405 ipPacket.setDestinationAddress(instPort.ipAddress().getIp4Address().toInt())
406 .resetChecksum();
407 ipPacket.setPayload(icmpReply);
408
409 Ethernet icmpResponseEth = new Ethernet();
410 icmpResponseEth.setEtherType(Ethernet.TYPE_IPV4)
411 .setSourceMACAddress(Constants.DEFAULT_GATEWAY_MAC)
412 .setDestinationMACAddress(instPort.macAddress())
413 .setPayload(ipPacket);
414
415 sendReply(icmpResponseEth, instPort);
416 }
417
418 private void sendReply(Ethernet icmpReply, InstancePort instPort) {
419 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
420 .setOutput(instPort.portNumber())
421 .build();
422
423 OutboundPacket packet = new DefaultOutboundPacket(
424 instPort.deviceId(),
425 treatment,
426 ByteBuffer.wrap(icmpReply.serialize()));
427
428 packetService.emit(packet);
429 }
430
431 private short getIcmpId(ICMP icmp) {
432 return ByteBuffer.wrap(icmp.serialize(), 4, 2).getShort();
433 }
434
435 private class InternalPacketProcessor implements PacketProcessor {
436
437 @Override
438 public void process(PacketContext context) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900439 Set<DeviceId> gateways = osNodeService.completeNodes(GATEWAY)
440 .stream().map(OpenstackNode::intgBridge)
441 .collect(Collectors.toSet());
442
Hyunsun Moon44aac662017-02-18 02:07:01 +0900443 if (context.isHandled()) {
444 return;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900445 } else if (!gateways.contains(context.inPacket().receivedFrom().deviceId())) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900446 // return if the packet is not from gateway nodes
447 return;
448 }
449
450 InboundPacket pkt = context.inPacket();
451 Ethernet ethernet = pkt.parsed();
452 if (ethernet == null || ethernet.getEtherType() == Ethernet.TYPE_ARP) {
453 return;
454 }
455
456 IPv4 iPacket = (IPv4) ethernet.getPayload();
457 if (iPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
458 eventExecutor.execute(() -> processIcmpPacket(context, ethernet));
459 }
460 }
461 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900462}