Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015 Open Networking Laboratory |
| 3 | * |
| 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 | */ |
| 16 | package org.onosproject.reactive.routing; |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 17 | |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 18 | import org.apache.felix.scr.annotations.Activate; |
| 19 | import org.apache.felix.scr.annotations.Component; |
| 20 | import org.apache.felix.scr.annotations.Deactivate; |
| 21 | import org.apache.felix.scr.annotations.Reference; |
| 22 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
Pingping Lin | c9e16bf | 2015-04-10 14:42:41 -0700 | [diff] [blame] | 23 | import org.onlab.packet.ARP; |
Jonathan Hart | 3217d1b | 2015-06-30 16:08:43 -0700 | [diff] [blame] | 24 | import org.onlab.packet.EthType; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 25 | import org.onlab.packet.Ethernet; |
| 26 | import org.onlab.packet.IPv4; |
Pingping Lin | c9e16bf | 2015-04-10 14:42:41 -0700 | [diff] [blame] | 27 | import org.onlab.packet.Ip4Address; |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 28 | import org.onlab.packet.Ip6Address; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 29 | import org.onlab.packet.IpAddress; |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 30 | import org.onlab.packet.IpPrefix; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 31 | import org.onlab.packet.MacAddress; |
| 32 | import org.onosproject.core.ApplicationId; |
| 33 | import org.onosproject.core.CoreService; |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 34 | import org.onosproject.incubator.net.intf.Interface; |
| 35 | import org.onosproject.incubator.net.intf.InterfaceService; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 36 | import org.onosproject.net.ConnectPoint; |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 37 | import org.onosproject.net.Host; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 38 | import org.onosproject.net.flow.DefaultTrafficSelector; |
| 39 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 40 | import org.onosproject.net.flow.TrafficSelector; |
| 41 | import org.onosproject.net.flow.TrafficTreatment; |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 42 | import org.onosproject.net.host.HostService; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 43 | import org.onosproject.net.packet.DefaultOutboundPacket; |
| 44 | import org.onosproject.net.packet.InboundPacket; |
| 45 | import org.onosproject.net.packet.OutboundPacket; |
| 46 | import org.onosproject.net.packet.PacketContext; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 47 | import org.onosproject.net.packet.PacketProcessor; |
| 48 | import org.onosproject.net.packet.PacketService; |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 49 | import org.onosproject.routing.IntentRequestListener; |
| 50 | import org.onosproject.routing.RouteEntry; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 51 | import org.onosproject.routing.RoutingService; |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 52 | import org.onosproject.routing.SdnIpService; |
Pingping Lin | c9e16bf | 2015-04-10 14:42:41 -0700 | [diff] [blame] | 53 | import org.onosproject.routing.config.RoutingConfigurationService; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 54 | import org.slf4j.Logger; |
| 55 | |
Jonathan Hart | 3217d1b | 2015-06-30 16:08:43 -0700 | [diff] [blame] | 56 | import java.nio.ByteBuffer; |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 57 | import java.util.Optional; |
| 58 | import java.util.Set; |
Jonathan Hart | 3217d1b | 2015-06-30 16:08:43 -0700 | [diff] [blame] | 59 | |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 60 | import static com.google.common.base.Preconditions.checkNotNull; |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 61 | import static org.onlab.packet.Ethernet.TYPE_ARP; |
| 62 | import static org.onlab.packet.Ethernet.TYPE_IPV4; |
| 63 | import static org.onosproject.net.packet.PacketPriority.REACTIVE; |
Jonathan Hart | 3217d1b | 2015-06-30 16:08:43 -0700 | [diff] [blame] | 64 | import static org.slf4j.LoggerFactory.getLogger; |
| 65 | |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 66 | /** |
| 67 | * This is reactive routing to handle 3 cases: |
| 68 | * (1) one host wants to talk to another host, both two hosts are in |
| 69 | * SDN network. |
| 70 | * (2) one host in SDN network wants to talk to another host in Internet. |
| 71 | * (3) one host from Internet wants to talk to another host in SDN network. |
| 72 | */ |
| 73 | @Component(immediate = true) |
| 74 | public class SdnIpReactiveRouting { |
| 75 | |
| 76 | private static final String APP_NAME = "org.onosproject.reactive.routing"; |
| 77 | private final Logger log = getLogger(getClass()); |
| 78 | |
| 79 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 80 | protected CoreService coreService; |
| 81 | |
| 82 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 83 | protected PacketService packetService; |
| 84 | |
| 85 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 86 | protected RoutingService routingService; |
| 87 | |
Pingping Lin | c9e16bf | 2015-04-10 14:42:41 -0700 | [diff] [blame] | 88 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 89 | protected SdnIpService sdnIpService; |
| 90 | |
| 91 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
Pingping Lin | c9e16bf | 2015-04-10 14:42:41 -0700 | [diff] [blame] | 92 | protected RoutingConfigurationService config; |
| 93 | |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 94 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 95 | protected InterfaceService interfaceService; |
| 96 | |
| 97 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 98 | protected HostService hostService; |
| 99 | |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 100 | private ApplicationId appId; |
| 101 | |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 102 | private IntentRequestListener intentRequestListener; |
| 103 | |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 104 | private ReactiveRoutingProcessor processor = |
| 105 | new ReactiveRoutingProcessor(); |
| 106 | |
| 107 | @Activate |
| 108 | public void activate() { |
| 109 | appId = coreService.registerApplication(APP_NAME); |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 110 | |
| 111 | intentRequestListener = new ReactiveRoutingFib(appId, hostService, |
| 112 | config, interfaceService, |
| 113 | sdnIpService.getIntentSynchronizationService()); |
| 114 | |
Brian O'Connor | 3b78326 | 2015-07-29 17:49:24 -0700 | [diff] [blame] | 115 | packetService.addProcessor(processor, PacketProcessor.director(2)); |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 116 | requestIntercepts(); |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 117 | log.info("SDN-IP Reactive Routing Started"); |
| 118 | } |
| 119 | |
| 120 | @Deactivate |
| 121 | public void deactivate() { |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 122 | withdrawIntercepts(); |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 123 | packetService.removeProcessor(processor); |
| 124 | processor = null; |
| 125 | log.info("SDN-IP Reactive Routing Stopped"); |
| 126 | } |
| 127 | |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 128 | /** |
| 129 | * Request packet in via the PacketService. |
| 130 | */ |
| 131 | private void requestIntercepts() { |
| 132 | //TODO: to support IPv6 later |
| 133 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
| 134 | selector.matchEthType(TYPE_IPV4); |
Thomas Vachuska | c19d829 | 2015-07-06 14:11:34 -0700 | [diff] [blame] | 135 | packetService.requestPackets(selector.build(), REACTIVE, appId); |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 136 | selector.matchEthType(TYPE_ARP); |
Thomas Vachuska | c19d829 | 2015-07-06 14:11:34 -0700 | [diff] [blame] | 137 | packetService.requestPackets(selector.build(), REACTIVE, appId); |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | /** |
| 141 | * Cancel request for packet in via PacketService. |
| 142 | */ |
| 143 | private void withdrawIntercepts() { |
| 144 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
| 145 | selector.matchEthType(TYPE_IPV4); |
Thomas Vachuska | c19d829 | 2015-07-06 14:11:34 -0700 | [diff] [blame] | 146 | packetService.cancelPackets(selector.build(), REACTIVE, appId); |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 147 | selector = DefaultTrafficSelector.builder(); |
| 148 | selector.matchEthType(TYPE_ARP); |
Thomas Vachuska | c19d829 | 2015-07-06 14:11:34 -0700 | [diff] [blame] | 149 | packetService.cancelPackets(selector.build(), REACTIVE, appId); |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 150 | } |
| 151 | |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 152 | private class ReactiveRoutingProcessor implements PacketProcessor { |
| 153 | @Override |
| 154 | public void process(PacketContext context) { |
| 155 | |
| 156 | InboundPacket pkt = context.inPacket(); |
| 157 | Ethernet ethPkt = pkt.parsed(); |
| 158 | if (ethPkt == null) { |
| 159 | return; |
| 160 | } |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 161 | ConnectPoint srcConnectPoint = pkt.receivedFrom(); |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 162 | |
Jonathan Hart | 3217d1b | 2015-06-30 16:08:43 -0700 | [diff] [blame] | 163 | switch (EthType.EtherType.lookup(ethPkt.getEtherType())) { |
| 164 | case ARP: |
Pingping Lin | c9e16bf | 2015-04-10 14:42:41 -0700 | [diff] [blame] | 165 | ARP arpPacket = (ARP) ethPkt.getPayload(); |
| 166 | Ip4Address targetIpAddress = Ip4Address |
| 167 | .valueOf(arpPacket.getTargetProtocolAddress()); |
| 168 | // Only when it is an ARP request packet and the target IP |
| 169 | // address is a virtual gateway IP address, then it will be |
| 170 | // processed. |
| 171 | if (arpPacket.getOpCode() == ARP.OP_REQUEST |
| 172 | && config.isVirtualGatewayIpAddress(targetIpAddress)) { |
| 173 | MacAddress gatewayMacAddress = |
| 174 | config.getVirtualGatewayMacAddress(); |
| 175 | if (gatewayMacAddress == null) { |
| 176 | break; |
| 177 | } |
| 178 | Ethernet eth = ARP.buildArpReply(targetIpAddress, |
| 179 | gatewayMacAddress, |
| 180 | ethPkt); |
| 181 | |
| 182 | TrafficTreatment.Builder builder = |
| 183 | DefaultTrafficTreatment.builder(); |
| 184 | builder.setOutput(srcConnectPoint.port()); |
| 185 | packetService.emit(new DefaultOutboundPacket( |
| 186 | srcConnectPoint.deviceId(), |
| 187 | builder.build(), |
| 188 | ByteBuffer.wrap(eth.serialize()))); |
| 189 | } |
| 190 | break; |
Jonathan Hart | 3217d1b | 2015-06-30 16:08:43 -0700 | [diff] [blame] | 191 | case IPV4: |
Pingping Lin | c9e16bf | 2015-04-10 14:42:41 -0700 | [diff] [blame] | 192 | // Parse packet |
| 193 | IPv4 ipv4Packet = (IPv4) ethPkt.getPayload(); |
| 194 | IpAddress dstIp = |
| 195 | IpAddress.valueOf(ipv4Packet.getDestinationAddress()); |
| 196 | IpAddress srcIp = |
| 197 | IpAddress.valueOf(ipv4Packet.getSourceAddress()); |
| 198 | MacAddress srcMac = ethPkt.getSourceMAC(); |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 199 | packetReactiveProcessor(dstIp, srcIp, srcConnectPoint, srcMac); |
Pingping Lin | c9e16bf | 2015-04-10 14:42:41 -0700 | [diff] [blame] | 200 | |
| 201 | // TODO emit packet first or packetReactiveProcessor first |
| 202 | ConnectPoint egressConnectPoint = null; |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 203 | egressConnectPoint = getEgressConnectPoint(dstIp); |
Pingping Lin | c9e16bf | 2015-04-10 14:42:41 -0700 | [diff] [blame] | 204 | if (egressConnectPoint != null) { |
| 205 | forwardPacketToDst(context, egressConnectPoint); |
| 206 | } |
| 207 | break; |
| 208 | default: |
| 209 | break; |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 210 | } |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | /** |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 215 | * Routes packet reactively. |
| 216 | * |
| 217 | * @param dstIpAddress the destination IP address of a packet |
| 218 | * @param srcIpAddress the source IP address of a packet |
| 219 | * @param srcConnectPoint the connect point where a packet comes from |
| 220 | * @param srcMacAddress the source MAC address of a packet |
| 221 | */ |
| 222 | private void packetReactiveProcessor(IpAddress dstIpAddress, |
| 223 | IpAddress srcIpAddress, |
| 224 | ConnectPoint srcConnectPoint, |
| 225 | MacAddress srcMacAddress) { |
| 226 | checkNotNull(dstIpAddress); |
| 227 | checkNotNull(srcIpAddress); |
| 228 | checkNotNull(srcConnectPoint); |
| 229 | checkNotNull(srcMacAddress); |
| 230 | |
| 231 | // |
| 232 | // Step1: Try to update the existing intent first if it exists. |
| 233 | // |
| 234 | IpPrefix ipPrefix = null; |
| 235 | RouteEntry routeEntry = null; |
| 236 | if (config.isIpAddressLocal(dstIpAddress)) { |
| 237 | if (dstIpAddress.isIp4()) { |
| 238 | ipPrefix = IpPrefix.valueOf(dstIpAddress, |
| 239 | Ip4Address.BIT_LENGTH); |
| 240 | } else { |
| 241 | ipPrefix = IpPrefix.valueOf(dstIpAddress, |
| 242 | Ip6Address.BIT_LENGTH); |
| 243 | } |
| 244 | } else { |
| 245 | // Get IP prefix from BGP route table |
| 246 | routeEntry = routingService.getLongestMatchableRouteEntry(dstIpAddress); |
| 247 | if (routeEntry != null) { |
| 248 | ipPrefix = routeEntry.prefix(); |
| 249 | } |
| 250 | } |
| 251 | if (ipPrefix != null |
| 252 | && intentRequestListener.mp2pIntentExists(ipPrefix)) { |
| 253 | intentRequestListener.updateExistingMp2pIntent(ipPrefix, |
| 254 | srcConnectPoint); |
| 255 | return; |
| 256 | } |
| 257 | |
| 258 | // |
| 259 | // Step2: There is no existing intent for the destination IP address. |
| 260 | // Check whether it is necessary to create a new one. If necessary then |
| 261 | // create a new one. |
| 262 | // |
| 263 | TrafficType trafficType = |
| 264 | trafficTypeClassifier(srcConnectPoint, dstIpAddress); |
| 265 | |
| 266 | switch (trafficType) { |
| 267 | case HOST_TO_INTERNET: |
| 268 | // If the destination IP address is outside the local SDN network. |
| 269 | // The Step 1 has already handled it. We do not need to do anything here. |
| 270 | intentRequestListener.setUpConnectivityHostToInternet(srcIpAddress, |
| 271 | ipPrefix, routeEntry.nextHop()); |
| 272 | break; |
| 273 | case INTERNET_TO_HOST: |
| 274 | intentRequestListener.setUpConnectivityInternetToHost(dstIpAddress); |
| 275 | break; |
| 276 | case HOST_TO_HOST: |
| 277 | intentRequestListener.setUpConnectivityHostToHost(dstIpAddress, |
| 278 | srcIpAddress, srcMacAddress, srcConnectPoint); |
| 279 | break; |
| 280 | case INTERNET_TO_INTERNET: |
| 281 | log.trace("This is transit traffic, " |
| 282 | + "the intent should be preinstalled already"); |
| 283 | break; |
| 284 | case DROP: |
| 285 | // TODO here should setUpDropPacketIntent(...); |
| 286 | // We need a new type of intent here. |
| 287 | break; |
| 288 | case UNKNOWN: |
| 289 | log.trace("This is unknown traffic, so we do nothing"); |
| 290 | break; |
| 291 | default: |
| 292 | break; |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | /** |
| 297 | * Classifies the traffic and return the traffic type. |
| 298 | * |
| 299 | * @param srcConnectPoint the connect point where the packet comes from |
| 300 | * @param dstIp the destination IP address in packet |
| 301 | * @return the traffic type which this packet belongs to |
| 302 | */ |
| 303 | private TrafficType trafficTypeClassifier(ConnectPoint srcConnectPoint, |
| 304 | IpAddress dstIp) { |
| 305 | LocationType dstIpLocationType = getLocationType(dstIp); |
| 306 | Optional<Interface> srcInterface = |
| 307 | interfaceService.getInterfacesByPort(srcConnectPoint).stream().findFirst(); |
Pingping Lin | 9b85c03 | 2015-10-05 18:16:27 -0700 | [diff] [blame] | 308 | Set<ConnectPoint> ingressPoints = config.getBgpPeerConnectPoints(); |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 309 | |
| 310 | switch (dstIpLocationType) { |
| 311 | case INTERNET: |
Pingping Lin | 9b85c03 | 2015-10-05 18:16:27 -0700 | [diff] [blame] | 312 | if (srcInterface.isPresent() && |
| 313 | (!ingressPoints.contains(srcConnectPoint))) { |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 314 | return TrafficType.HOST_TO_INTERNET; |
| 315 | } else { |
| 316 | return TrafficType.INTERNET_TO_INTERNET; |
| 317 | } |
| 318 | case LOCAL: |
Pingping Lin | 9b85c03 | 2015-10-05 18:16:27 -0700 | [diff] [blame] | 319 | if (srcInterface.isPresent() && |
| 320 | (!ingressPoints.contains(srcConnectPoint))) { |
Jonathan Hart | 9a426f8 | 2015-09-03 15:43:13 +0200 | [diff] [blame] | 321 | return TrafficType.HOST_TO_HOST; |
| 322 | } else { |
| 323 | // TODO Currently we only consider local public prefixes. |
| 324 | // In the future, we will consider the local private prefixes. |
| 325 | // If dstIpLocationType is a local private, we should return |
| 326 | // TrafficType.DROP. |
| 327 | return TrafficType.INTERNET_TO_HOST; |
| 328 | } |
| 329 | case NO_ROUTE: |
| 330 | return TrafficType.DROP; |
| 331 | default: |
| 332 | return TrafficType.UNKNOWN; |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | /** |
| 337 | * Evaluates the location of an IP address and returns the location type. |
| 338 | * |
| 339 | * @param ipAddress the IP address to evaluate |
| 340 | * @return the IP address location type |
| 341 | */ |
| 342 | private LocationType getLocationType(IpAddress ipAddress) { |
| 343 | if (config.isIpAddressLocal(ipAddress)) { |
| 344 | return LocationType.LOCAL; |
| 345 | } else if (routingService.getLongestMatchableRouteEntry(ipAddress) != null) { |
| 346 | return LocationType.INTERNET; |
| 347 | } else { |
| 348 | return LocationType.NO_ROUTE; |
| 349 | } |
| 350 | } |
| 351 | |
| 352 | public ConnectPoint getEgressConnectPoint(IpAddress dstIpAddress) { |
| 353 | LocationType type = getLocationType(dstIpAddress); |
| 354 | if (type == LocationType.LOCAL) { |
| 355 | Set<Host> hosts = hostService.getHostsByIp(dstIpAddress); |
| 356 | if (!hosts.isEmpty()) { |
| 357 | return hosts.iterator().next().location(); |
| 358 | } else { |
| 359 | hostService.startMonitoringIp(dstIpAddress); |
| 360 | return null; |
| 361 | } |
| 362 | } else if (type == LocationType.INTERNET) { |
| 363 | IpAddress nextHopIpAddress = null; |
| 364 | RouteEntry routeEntry = routingService.getLongestMatchableRouteEntry(dstIpAddress); |
| 365 | if (routeEntry != null) { |
| 366 | nextHopIpAddress = routeEntry.nextHop(); |
| 367 | Interface it = interfaceService.getMatchingInterface(nextHopIpAddress); |
| 368 | if (it != null) { |
| 369 | return it.connectPoint(); |
| 370 | } else { |
| 371 | return null; |
| 372 | } |
| 373 | } else { |
| 374 | return null; |
| 375 | } |
| 376 | } else { |
| 377 | return null; |
| 378 | } |
| 379 | } |
| 380 | |
| 381 | /** |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 382 | * Emits the specified packet onto the network. |
| 383 | * |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 384 | * @param context the packet context |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 385 | * @param connectPoint the connect point where the packet should be |
Aaron Kruglikov | 07a923d | 2015-07-03 13:30:57 -0700 | [diff] [blame] | 386 | * sent out |
Pingping Lin | e28ae4c | 2015-03-13 11:37:03 -0700 | [diff] [blame] | 387 | */ |
| 388 | private void forwardPacketToDst(PacketContext context, |
| 389 | ConnectPoint connectPoint) { |
| 390 | TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
| 391 | .setOutput(connectPoint.port()).build(); |
| 392 | OutboundPacket packet = |
| 393 | new DefaultOutboundPacket(connectPoint.deviceId(), treatment, |
| 394 | context.inPacket().unparsed()); |
| 395 | packetService.emit(packet); |
| 396 | log.trace("sending packet: {}", packet); |
| 397 | } |
| 398 | |
| 399 | } |
| 400 | |