2 * Copyright 2015 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.onosproject.reactive.routing;
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;
23 import org.onlab.packet.ARP;
24 import org.onlab.packet.EthType;
25 import org.onlab.packet.Ethernet;
26 import org.onlab.packet.IPv4;
27 import org.onlab.packet.Ip4Address;
28 import org.onlab.packet.IpAddress;
29 import org.onlab.packet.MacAddress;
30 import org.onosproject.core.ApplicationId;
31 import org.onosproject.core.CoreService;
32 import org.onosproject.net.ConnectPoint;
33 import org.onosproject.net.flow.DefaultTrafficSelector;
34 import org.onosproject.net.flow.DefaultTrafficTreatment;
35 import org.onosproject.net.flow.TrafficSelector;
36 import org.onosproject.net.flow.TrafficTreatment;
37 import org.onosproject.net.packet.DefaultOutboundPacket;
38 import org.onosproject.net.packet.InboundPacket;
39 import org.onosproject.net.packet.OutboundPacket;
40 import org.onosproject.net.packet.PacketContext;
41 import org.onosproject.net.packet.PacketProcessor;
42 import org.onosproject.net.packet.PacketService;
43 import org.onosproject.routing.RoutingService;
44 import org.onosproject.routing.config.RoutingConfigurationService;
45 import org.slf4j.Logger;
47 import java.nio.ByteBuffer;
49 import static org.onlab.packet.Ethernet.TYPE_ARP;
50 import static org.onlab.packet.Ethernet.TYPE_IPV4;
51 import static org.onosproject.net.packet.PacketPriority.REACTIVE;
52 import static org.slf4j.LoggerFactory.getLogger;
55 * This is reactive routing to handle 3 cases:
56 * (1) one host wants to talk to another host, both two hosts are in
58 * (2) one host in SDN network wants to talk to another host in Internet.
59 * (3) one host from Internet wants to talk to another host in SDN network.
61 @Component(immediate = true)
62 public class SdnIpReactiveRouting {
64 private static final String APP_NAME = "org.onosproject.reactive.routing";
65 private final Logger log = getLogger(getClass());
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected CoreService coreService;
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected PacketService packetService;
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected RoutingService routingService;
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected RoutingConfigurationService config;
79 private ApplicationId appId;
81 private ReactiveRoutingProcessor processor =
82 new ReactiveRoutingProcessor();
85 public void activate() {
86 appId = coreService.registerApplication(APP_NAME);
87 packetService.addProcessor(processor, PacketProcessor.director(2));
89 log.info("SDN-IP Reactive Routing Started");
93 public void deactivate() {
95 packetService.removeProcessor(processor);
97 log.info("SDN-IP Reactive Routing Stopped");
101 * Request packet in via the PacketService.
103 private void requestIntercepts() {
104 //TODO: to support IPv6 later
105 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
106 selector.matchEthType(TYPE_IPV4);
107 packetService.requestPackets(selector.build(), REACTIVE, appId);
108 selector.matchEthType(TYPE_ARP);
109 packetService.requestPackets(selector.build(), REACTIVE, appId);
113 * Cancel request for packet in via PacketService.
115 private void withdrawIntercepts() {
116 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
117 selector.matchEthType(TYPE_IPV4);
118 packetService.cancelPackets(selector.build(), REACTIVE, appId);
119 selector = DefaultTrafficSelector.builder();
120 selector.matchEthType(TYPE_ARP);
121 packetService.cancelPackets(selector.build(), REACTIVE, appId);
124 private class ReactiveRoutingProcessor implements PacketProcessor {
126 public void process(PacketContext context) {
128 InboundPacket pkt = context.inPacket();
129 Ethernet ethPkt = pkt.parsed();
130 if (ethPkt == null) {
133 ConnectPoint srcConnectPoint = pkt.receivedFrom();
135 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
137 ARP arpPacket = (ARP) ethPkt.getPayload();
138 Ip4Address targetIpAddress = Ip4Address
139 .valueOf(arpPacket.getTargetProtocolAddress());
140 // Only when it is an ARP request packet and the target IP
141 // address is a virtual gateway IP address, then it will be
143 if (arpPacket.getOpCode() == ARP.OP_REQUEST
144 && config.isVirtualGatewayIpAddress(targetIpAddress)) {
145 MacAddress gatewayMacAddress =
146 config.getVirtualGatewayMacAddress();
147 if (gatewayMacAddress == null) {
150 Ethernet eth = ARP.buildArpReply(targetIpAddress,
154 TrafficTreatment.Builder builder =
155 DefaultTrafficTreatment.builder();
156 builder.setOutput(srcConnectPoint.port());
157 packetService.emit(new DefaultOutboundPacket(
158 srcConnectPoint.deviceId(),
160 ByteBuffer.wrap(eth.serialize())));
165 IPv4 ipv4Packet = (IPv4) ethPkt.getPayload();
167 IpAddress.valueOf(ipv4Packet.getDestinationAddress());
169 IpAddress.valueOf(ipv4Packet.getSourceAddress());
170 MacAddress srcMac = ethPkt.getSourceMAC();
171 routingService.packetReactiveProcessor(dstIp, srcIp,
172 srcConnectPoint, srcMac);
174 // TODO emit packet first or packetReactiveProcessor first
175 ConnectPoint egressConnectPoint = null;
176 egressConnectPoint = routingService.getEgressConnectPoint(dstIp);
177 if (egressConnectPoint != null) {
178 forwardPacketToDst(context, egressConnectPoint);
188 * Emits the specified packet onto the network.
190 * @param context the packet context
191 * @param connectPoint the connect point where the packet should be
194 private void forwardPacketToDst(PacketContext context,
195 ConnectPoint connectPoint) {
196 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
197 .setOutput(connectPoint.port()).build();
198 OutboundPacket packet =
199 new DefaultOutboundPacket(connectPoint.deviceId(), treatment,
200 context.inPacket().unparsed());
201 packetService.emit(packet);
202 log.trace("sending packet: {}", packet);