blob: 87496a59a808be08b4c177c7241f9b0d405cf2a2 [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;
Jian Li2fa3ded2018-08-10 02:22:47 +000026import org.onlab.packet.ICMPEcho;
Hyunsun Moon44aac662017-02-18 02:07:01 +090027import org.onlab.packet.IPv4;
28import org.onlab.packet.IpAddress;
29import org.onlab.packet.MacAddress;
daniel park576969a2018-03-09 07:07:41 +090030import org.onlab.packet.VlanId;
sangho247232c2017-08-24 17:22:08 +090031import org.onlab.util.KryoNamespace;
Daniel Park6a2d95e2018-11-05 18:50:16 +090032import org.onosproject.cluster.ClusterService;
33import org.onosproject.cluster.LeadershipService;
34import org.onosproject.cluster.NodeId;
Hyunsun Moon44aac662017-02-18 02:07:01 +090035import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090037import org.onosproject.net.DeviceId;
Daniel Park6a2d95e2018-11-05 18:50:16 +090038import org.onosproject.net.flow.DefaultTrafficSelector;
Hyunsun Moon44aac662017-02-18 02:07:01 +090039import org.onosproject.net.flow.DefaultTrafficTreatment;
Daniel Park6a2d95e2018-11-05 18:50:16 +090040import org.onosproject.net.flow.TrafficSelector;
Hyunsun Moon44aac662017-02-18 02:07:01 +090041import org.onosproject.net.flow.TrafficTreatment;
42import org.onosproject.net.packet.DefaultOutboundPacket;
43import org.onosproject.net.packet.InboundPacket;
44import org.onosproject.net.packet.OutboundPacket;
45import org.onosproject.net.packet.PacketContext;
Hyunsun Moon44aac662017-02-18 02:07:01 +090046import org.onosproject.net.packet.PacketProcessor;
47import org.onosproject.net.packet.PacketService;
48import org.onosproject.openstacknetworking.api.Constants;
daniel park576969a2018-03-09 07:07:41 +090049import org.onosproject.openstacknetworking.api.ExternalPeerRouter;
Hyunsun Moon44aac662017-02-18 02:07:01 +090050import org.onosproject.openstacknetworking.api.InstancePort;
51import org.onosproject.openstacknetworking.api.InstancePortService;
Daniel Park6a2d95e2018-11-05 18:50:16 +090052import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090053import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
sangho36721992017-08-03 11:13:17 +090054import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090055import org.onosproject.openstacknode.api.OpenstackNode;
Daniel Park6a2d95e2018-11-05 18:50:16 +090056import org.onosproject.openstacknode.api.OpenstackNodeEvent;
57import org.onosproject.openstacknode.api.OpenstackNodeListener;
Hyunsun Moon0d457362017-06-27 17:19:41 +090058import org.onosproject.openstacknode.api.OpenstackNodeService;
sangho247232c2017-08-24 17:22:08 +090059import org.onosproject.store.serializers.KryoNamespaces;
60import org.onosproject.store.service.ConsistentMap;
61import org.onosproject.store.service.Serializer;
62import org.onosproject.store.service.StorageService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090063import org.openstack4j.model.network.Port;
64import org.openstack4j.model.network.Router;
65import org.openstack4j.model.network.RouterInterface;
66import org.openstack4j.model.network.Subnet;
67import org.slf4j.Logger;
68
69import java.nio.ByteBuffer;
Hyunsun Moon44aac662017-02-18 02:07:01 +090070import java.util.Objects;
Hyunsun Moon44aac662017-02-18 02:07:01 +090071import java.util.Set;
72import java.util.concurrent.ExecutorService;
73import java.util.stream.Collectors;
74
sangho247232c2017-08-24 17:22:08 +090075import static com.google.common.base.Preconditions.checkArgument;
Daniel Park4d486842018-07-24 17:06:43 +090076import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moon44aac662017-02-18 02:07:01 +090077import static java.util.concurrent.Executors.newSingleThreadExecutor;
Daniel Park4d486842018-07-24 17:06:43 +090078import static org.onlab.packet.ICMP.TYPE_ECHO_REPLY;
79import static org.onlab.packet.ICMP.TYPE_ECHO_REQUEST;
Hyunsun Moon44aac662017-02-18 02:07:01 +090080import static org.onlab.util.Tools.groupedThreads;
sangho36721992017-08-03 11:13:17 +090081import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC;
Daniel Park6a2d95e2018-11-05 18:50:16 +090082import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
sangho36721992017-08-03 11:13:17 +090083import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
Daniel Park6a2d95e2018-11-05 18:50:16 +090084import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_INTERNAL_ROUTING_RULE;
Daniel Park0fe961b2018-11-12 18:47:55 +090085import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalPeerRouterFromSubnet;
86import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getExternalIpFromSubnet;
Hyunsun Moon0d457362017-06-27 17:19:41 +090087import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Hyunsun Moon44aac662017-02-18 02:07:01 +090088import static org.slf4j.LoggerFactory.getLogger;
89
Hyunsun Moon44aac662017-02-18 02:07:01 +090090/**
91 * Handles ICMP packet received from a gateway node.
92 * For a request for virtual network subnet gateway, it generates fake ICMP reply.
93 * For a request for the external network, it does source NAT with the public IP and
94 * forward the request to the external only if the requested virtual subnet has
95 * external connectivity.
96 */
97@Component(immediate = true)
98public class OpenstackRoutingIcmpHandler {
99
100 protected final Logger log = getLogger(getClass());
101
102 private static final String ERR_REQ = "Failed to handle ICMP request: ";
sangho247232c2017-08-24 17:22:08 +0900103 private static final String ERR_DUPLICATE = " already exists";
Hyunsun Moon44aac662017-02-18 02:07:01 +0900104
Jian Li28ec77f2018-10-31 07:07:25 +0900105 private static final String VXLAN = "VXLAN";
106 private static final String VLAN = "VLAN";
107
Hyunsun Moon44aac662017-02-18 02:07:01 +0900108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected CoreService coreService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected PacketService packetService;
113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho247232c2017-08-24 17:22:08 +0900115 protected StorageService storageService;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900118 protected OpenstackNodeService osNodeService;
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected InstancePortService instancePortService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 protected OpenstackNetworkService osNetworkService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected OpenstackRouterService osRouterService;
128
Daniel Park6a2d95e2018-11-05 18:50:16 +0900129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
130 protected LeadershipService leadershipService;
131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
133 protected OpenstackFlowRuleService osFlowRuleService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
136 protected ClusterService clusterService;
137
Hyunsun Moon44aac662017-02-18 02:07:01 +0900138 private final ExecutorService eventExecutor = newSingleThreadExecutor(
139 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
sangho072c4dd2017-05-17 10:45:21 +0900140 private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
sangho247232c2017-08-24 17:22:08 +0900141 private ConsistentMap<String, InstancePort> icmpInfoMap;
Daniel Park6a2d95e2018-11-05 18:50:16 +0900142 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
sangho247232c2017-08-24 17:22:08 +0900143
144 private static final KryoNamespace SERIALIZER_ICMP_MAP = KryoNamespace.newBuilder()
145 .register(KryoNamespaces.API)
146 .register(InstancePort.class)
Jian Liec5c32b2018-07-13 14:28:58 +0900147 .register(DefaultInstancePort.class)
148 .register(InstancePort.State.class)
sangho247232c2017-08-24 17:22:08 +0900149 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900150
151 private ApplicationId appId;
Daniel Park6a2d95e2018-11-05 18:50:16 +0900152 private NodeId localNodeId;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900153
154 @Activate
155 protected void activate() {
156 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
157 packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
Daniel Park6a2d95e2018-11-05 18:50:16 +0900158 localNodeId = clusterService.getLocalNode().id();
159 leadershipService.runForLeadership(appId.name());
160 osNodeService.addListener(osNodeListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900161
sangho247232c2017-08-24 17:22:08 +0900162 icmpInfoMap = storageService.<String, InstancePort>consistentMapBuilder()
163 .withSerializer(Serializer.using(SERIALIZER_ICMP_MAP))
164 .withName("openstack-icmpmap")
165 .withApplicationId(appId)
166 .build();
167
Hyunsun Moon44aac662017-02-18 02:07:01 +0900168 log.info("Started");
169 }
170
171 @Deactivate
172 protected void deactivate() {
173 packetService.removeProcessor(packetProcessor);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900174 eventExecutor.shutdown();
Daniel Park6a2d95e2018-11-05 18:50:16 +0900175 leadershipService.withdraw(appId.name());
176 osNodeService.removeListener(osNodeListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900177
178 log.info("Stopped");
179 }
180
Daniel Park6a2d95e2018-11-05 18:50:16 +0900181 private class InternalNodeEventListener implements OpenstackNodeListener {
182 @Override
183 public boolean isRelevant(OpenstackNodeEvent event) {
184 // do not allow to proceed without leadership
185 NodeId leader = leadershipService.getLeader(appId.name());
186 return Objects.equals(localNodeId, leader) && event.subject().type() == GATEWAY;
187 }
188
189 @Override
190 public void event(OpenstackNodeEvent event) {
191 OpenstackNode osNode = event.subject();
192 switch (event.type()) {
193 case OPENSTACK_NODE_COMPLETE:
194 eventExecutor.execute(() -> setIcmpReplyRules(osNode.intgBridge(), true));
195 break;
196 case OPENSTACK_NODE_INCOMPLETE:
197 eventExecutor.execute(() -> setIcmpReplyRules(osNode.intgBridge(), false));
198 break;
199 default:
200 break;
201 }
202 }
203
204 private void setIcmpReplyRules(DeviceId deviceId, boolean install) {
205 // Sends ICMP response to controller for SNATing ingress traffic
206 TrafficSelector selector = DefaultTrafficSelector.builder()
207 .matchEthType(Ethernet.TYPE_IPV4)
208 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
209 .matchIcmpType(ICMP.TYPE_ECHO_REPLY)
210 .build();
211
212 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
213 .punt()
214 .build();
215
216 osFlowRuleService.setRule(
217 appId,
218 deviceId,
219 selector,
220 treatment,
221 PRIORITY_INTERNAL_ROUTING_RULE,
222 GW_COMMON_TABLE,
223 install);
224 }
225 }
Daniel Park4fd94e0d2018-11-09 11:34:20 +0900226
227 private class InternalPacketProcessor implements PacketProcessor {
228
229 @Override
230 public void process(PacketContext context) {
231 if (context.isHandled()) {
232 return;
233 }
234
235 eventExecutor.execute(() -> {
236 Set<DeviceId> gateways = osNodeService.completeNodes(GATEWAY)
237 .stream().map(OpenstackNode::intgBridge)
238 .collect(Collectors.toSet());
239
240 if (!gateways.isEmpty() &&
241 !gateways.contains(context.inPacket().receivedFrom().deviceId())) {
242 return;
243 }
244
245 InboundPacket pkt = context.inPacket();
246 Ethernet ethernet = pkt.parsed();
247 if (ethernet == null || ethernet.getEtherType() != Ethernet.TYPE_IPV4) {
248 return;
249 }
250
251 IPv4 iPacket = (IPv4) ethernet.getPayload();
252
253 if (iPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
254 processIcmpPacket(context, ethernet);
255 }
256 });
257 }
258
259 private void processIcmpPacket(PacketContext context, Ethernet ethernet) {
260 IPv4 ipPacket = (IPv4) ethernet.getPayload();
261 ICMP icmp = (ICMP) ipPacket.getPayload();
262 log.trace("Processing ICMP packet source MAC:{}, source IP:{}," +
263 "dest MAC:{}, dest IP:{}",
264 ethernet.getSourceMAC(),
265 IpAddress.valueOf(ipPacket.getSourceAddress()),
266 ethernet.getDestinationMAC(),
267 IpAddress.valueOf(ipPacket.getDestinationAddress()));
268
269 switch (icmp.getIcmpType()) {
270 case TYPE_ECHO_REQUEST:
271 if (handleEchoRequest(context.inPacket().receivedFrom().deviceId(),
272 ethernet.getSourceMAC(),
273 ipPacket,
274 icmp)) {
275 context.block();
276 }
277 break;
278 case TYPE_ECHO_REPLY:
279 if (handleEchoReply(ipPacket, icmp)) {
280 context.block();
281 }
282 break;
283 default:
284 break;
285 }
286 }
287
288 private boolean handleEchoRequest(DeviceId srcDevice, MacAddress srcMac, IPv4 ipPacket,
289 ICMP icmp) {
290 //We only handles a request from an instance port
291 //In case of ehco request to SNAT ip address from an external router, we intentionally ignore it
292 InstancePort instPort = instancePortService.instancePort(srcMac);
293 if (instPort == null) {
294 log.warn(ERR_REQ + "unknown source host(MAC:{})", srcMac);
295 return false;
296 }
297
298 IpAddress srcIp = IpAddress.valueOf(ipPacket.getSourceAddress());
299 IpAddress dstIp = IpAddress.valueOf(ipPacket.getDestinationAddress());
300
301 Subnet srcSubnet = getSourceSubnet(instPort);
302 if (srcSubnet == null) {
303 log.warn(ERR_REQ + "unknown source subnet(IP:{})", srcIp);
304 return false;
305 }
306
307 if (Strings.isNullOrEmpty(srcSubnet.getGateway())) {
308 log.warn(ERR_REQ + "source subnet(ID:{}, CIDR:{}) has no gateway",
309 srcSubnet.getId(), srcSubnet.getCidr());
310 return false;
311 }
312
313 if (isForSubnetGateway(IpAddress.valueOf(ipPacket.getDestinationAddress()),
314 srcSubnet)) {
315 // this is a request to a subnet gateway
316 log.trace("Icmp request to gateway {} from {}", dstIp, srcIp);
317 processRequestForGateway(ipPacket, instPort);
318 } else {
319 // this is a request to an external network
320 log.trace("Icmp request to external {} from {}", dstIp, srcIp);
321
Daniel Park4fd94e0d2018-11-09 11:34:20 +0900322
Daniel Park0fe961b2018-11-12 18:47:55 +0900323 IpAddress externalIp = getExternalIpFromSubnet(srcSubnet, osRouterService, osNetworkService);
Daniel Park4fd94e0d2018-11-09 11:34:20 +0900324 if (externalIp == null) {
325 log.warn(ERR_REQ + "failed to get external ip");
326 return false;
327 }
328
Daniel Park0fe961b2018-11-12 18:47:55 +0900329 ExternalPeerRouter externalPeerRouter =
330 externalPeerRouterFromSubnet(srcSubnet, osRouterService, osNetworkService);
331 if (externalPeerRouter == null) {
332 log.warn(ERR_REQ + "failed to get external peer router");
333 return false;
334 }
335
Daniel Park4fd94e0d2018-11-09 11:34:20 +0900336 String icmpInfoKey = icmpInfoKey(icmp,
337 externalIp.toString(),
338 IPv4.fromIPv4Address(ipPacket.getDestinationAddress()));
339 log.trace("Created icmpInfo key is {}", icmpInfoKey);
340
341 sendRequestForExternal(ipPacket, srcDevice, externalIp, externalPeerRouter);
342
343 try {
344 icmpInfoMap.compute(icmpInfoKey, (id, existing) -> {
345 checkArgument(existing == null, ERR_DUPLICATE);
346 return instPort;
347 });
348 } catch (IllegalArgumentException e) {
349 log.warn("IllegalArgumentException occurred because of {}", e.toString());
350 return false;
351 }
352 }
353 return true;
354 }
355
356 private String icmpInfoKey(ICMP icmp, String srcIp, String dstIp) {
357 return String.valueOf(getIcmpId(icmp))
358 .concat(srcIp)
359 .concat(dstIp);
360 }
Daniel Park4fd94e0d2018-11-09 11:34:20 +0900361
362 private boolean handleEchoReply(IPv4 ipPacket, ICMP icmp) {
363 String icmpInfoKey = icmpInfoKey(icmp,
364 IPv4.fromIPv4Address(ipPacket.getDestinationAddress()),
365 IPv4.fromIPv4Address(ipPacket.getSourceAddress()));
366 log.trace("Retrieved icmpInfo key is {}", icmpInfoKey);
367
368 if (icmpInfoMap.get(icmpInfoKey) != null) {
369 processReplyFromExternal(ipPacket, icmpInfoMap.get(icmpInfoKey).value());
370 icmpInfoMap.remove(icmpInfoKey);
371 return true;
372 } else {
373 log.debug("No ICMP Info for ICMP packet");
374 return false;
375 }
376 }
377
378 private Subnet getSourceSubnet(InstancePort instance) {
379 checkNotNull(instance);
380
381 Port osPort = osNetworkService.port(instance.portId());
382 return osNetworkService.subnets(osPort.getNetworkId())
383 .stream().findAny().orElse(null);
384 }
385
386 private boolean isForSubnetGateway(IpAddress dstIp, Subnet srcSubnet) {
387 RouterInterface osRouterIface = osRouterService.routerInterfaces().stream()
388 .filter(i -> Objects.equals(i.getSubnetId(), srcSubnet.getId()))
389 .findAny().orElse(null);
390 if (osRouterIface == null) {
391 log.trace(ERR_REQ + "source subnet(ID:{}, CIDR:{}) has no router",
392 srcSubnet.getId(), srcSubnet.getCidr());
393 return false;
394 }
395
396 Router osRouter = osRouterService.router(osRouterIface.getId());
397 Set<IpAddress> routableGateways = osRouterService.routerInterfaces(osRouter.getId())
398 .stream()
399 .map(iface -> osNetworkService.subnet(iface.getSubnetId()).getGateway())
400 .map(IpAddress::valueOf)
401 .collect(Collectors.toSet());
402
403 return routableGateways.contains(dstIp);
404 }
405
Daniel Park4fd94e0d2018-11-09 11:34:20 +0900406 private void processRequestForGateway(IPv4 ipPacket, InstancePort instPort) {
407 ICMP icmpReq = (ICMP) ipPacket.getPayload();
408 icmpReq.setChecksum((short) 0);
409 icmpReq.setIcmpType(TYPE_ECHO_REPLY);
410
411 int destinationAddress = ipPacket.getSourceAddress();
412
413 ipPacket.setSourceAddress(ipPacket.getDestinationAddress())
414 .setDestinationAddress(destinationAddress)
415 .resetChecksum();
416
417 ipPacket.setPayload(icmpReq);
418 Ethernet icmpReply = new Ethernet();
419 icmpReply.setEtherType(Ethernet.TYPE_IPV4)
420 .setSourceMACAddress(Constants.DEFAULT_GATEWAY_MAC)
421 .setDestinationMACAddress(instPort.macAddress())
422 .setPayload(ipPacket);
423
424 sendReply(icmpReply, instPort);
425 }
426
427 private void sendRequestForExternal(IPv4 ipPacket, DeviceId srcDevice,
428 IpAddress srcNatIp, ExternalPeerRouter externalPeerRouter) {
429 ICMP icmpReq = (ICMP) ipPacket.getPayload();
430 icmpReq.resetChecksum();
431 ipPacket.setSourceAddress(srcNatIp.getIp4Address().toInt()).resetChecksum();
432 ipPacket.setPayload(icmpReq);
433
434 Ethernet icmpRequestEth = new Ethernet();
435 icmpRequestEth.setEtherType(Ethernet.TYPE_IPV4)
436 .setSourceMACAddress(DEFAULT_GATEWAY_MAC)
437 .setDestinationMACAddress(externalPeerRouter.macAddress());
438
439 if (!externalPeerRouter.vlanId().equals(VlanId.NONE)) {
440 icmpRequestEth.setVlanID(externalPeerRouter.vlanId().toShort());
441 }
442
443 icmpRequestEth.setPayload(ipPacket);
444
445 OpenstackNode osNode = osNodeService.node(srcDevice);
446 if (osNode == null) {
447 final String error = String.format("Cannot find openstack node for %s",
448 srcDevice);
449 throw new IllegalStateException(error);
450 }
451 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
452 .setOutput(osNode.uplinkPortNum())
453 .build();
454
455 OutboundPacket packet = new DefaultOutboundPacket(
456 srcDevice,
457 treatment,
458 ByteBuffer.wrap(icmpRequestEth.serialize()));
459
460 packetService.emit(packet);
461 }
462
463 private void processReplyFromExternal(IPv4 ipPacket, InstancePort instPort) {
464
465 if (instPort.networkId() == null) {
466 return;
467 }
468
469 ICMP icmpReply = (ICMP) ipPacket.getPayload();
470
471 icmpReply.resetChecksum();
472
473 ipPacket.setDestinationAddress(instPort.ipAddress().getIp4Address().toInt())
474 .resetChecksum();
475 ipPacket.setPayload(icmpReply);
476
477 Ethernet icmpResponseEth = new Ethernet();
478 icmpResponseEth.setEtherType(Ethernet.TYPE_IPV4)
479 .setSourceMACAddress(Constants.DEFAULT_GATEWAY_MAC)
480 .setDestinationMACAddress(instPort.macAddress())
481 .setPayload(ipPacket);
482
483 sendReply(icmpResponseEth, instPort);
484 }
485
486 private void sendReply(Ethernet icmpReply, InstancePort instPort) {
487 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
488 .setOutput(instPort.portNumber());
489
490 String netId = instPort.networkId();
491 String segId = osNetworkService.segmentId(netId);
492
493 switch (osNetworkService.networkType(netId)) {
494 case VXLAN:
495 tBuilder.setTunnelId(Long.valueOf(segId));
496 break;
497 case VLAN:
498 tBuilder.setVlanId(VlanId.vlanId(segId));
499 break;
500 default:
501 break;
502 }
503
504 OutboundPacket packet = new DefaultOutboundPacket(
505 instPort.deviceId(),
506 tBuilder.build(),
507 ByteBuffer.wrap(icmpReply.serialize()));
508
509 packetService.emit(packet);
510 }
511
512 private short getIcmpId(ICMP icmp) {
513 return ((ICMPEcho) icmp.getPayload()).getIdentifier();
514 }
515 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900516}