blob: b1defbd904171217ffe502f513f6ae77aac7e585 [file] [log] [blame]
Pingping Line28ae4c2015-03-13 11:37:03 -07001/*
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 */
16package org.onosproject.reactive.routing;
Pingping Line28ae4c2015-03-13 11:37:03 -070017import org.apache.felix.scr.annotations.Activate;
18import org.apache.felix.scr.annotations.Component;
19import org.apache.felix.scr.annotations.Deactivate;
20import org.apache.felix.scr.annotations.Reference;
21import org.apache.felix.scr.annotations.ReferenceCardinality;
Pingping Linc9e16bf2015-04-10 14:42:41 -070022import org.onlab.packet.ARP;
Jonathan Hart3217d1b2015-06-30 16:08:43 -070023import org.onlab.packet.EthType;
Pingping Line28ae4c2015-03-13 11:37:03 -070024import org.onlab.packet.Ethernet;
25import org.onlab.packet.IPv4;
Pingping Linc9e16bf2015-04-10 14:42:41 -070026import org.onlab.packet.Ip4Address;
Pingping Line28ae4c2015-03-13 11:37:03 -070027import org.onlab.packet.IpAddress;
28import org.onlab.packet.MacAddress;
29import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
31import org.onosproject.net.ConnectPoint;
32import org.onosproject.net.flow.DefaultTrafficSelector;
33import org.onosproject.net.flow.DefaultTrafficTreatment;
34import org.onosproject.net.flow.TrafficSelector;
35import 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;
40import org.onosproject.net.packet.PacketPriority;
41import org.onosproject.net.packet.PacketProcessor;
42import org.onosproject.net.packet.PacketService;
43import org.onosproject.routing.RoutingService;
Pingping Linc9e16bf2015-04-10 14:42:41 -070044import org.onosproject.routing.config.RoutingConfigurationService;
Pingping Line28ae4c2015-03-13 11:37:03 -070045import org.slf4j.Logger;
46
Jonathan Hart3217d1b2015-06-30 16:08:43 -070047import java.nio.ByteBuffer;
48
49import static org.slf4j.LoggerFactory.getLogger;
50
Pingping Line28ae4c2015-03-13 11:37:03 -070051/**
52 * This is reactive routing to handle 3 cases:
53 * (1) one host wants to talk to another host, both two hosts are in
54 * SDN network.
55 * (2) one host in SDN network wants to talk to another host in Internet.
56 * (3) one host from Internet wants to talk to another host in SDN network.
57 */
58@Component(immediate = true)
59public class SdnIpReactiveRouting {
60
61 private static final String APP_NAME = "org.onosproject.reactive.routing";
62 private final Logger log = getLogger(getClass());
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected CoreService coreService;
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected PacketService packetService;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected RoutingService routingService;
72
Pingping Linc9e16bf2015-04-10 14:42:41 -070073 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected RoutingConfigurationService config;
75
Pingping Line28ae4c2015-03-13 11:37:03 -070076 private ApplicationId appId;
77
78 private ReactiveRoutingProcessor processor =
79 new ReactiveRoutingProcessor();
80
81 @Activate
82 public void activate() {
83 appId = coreService.registerApplication(APP_NAME);
84 packetService.addProcessor(processor,
85 PacketProcessor.ADVISOR_MAX + 2);
86
87 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
88 // TODO: to support IPv6 later
89 selector.matchEthType(Ethernet.TYPE_IPV4);
90 packetService.requestPackets(selector.build(),
91 PacketPriority.REACTIVE, appId);
Pingping Linc9e16bf2015-04-10 14:42:41 -070092 selector.matchEthType(Ethernet.TYPE_ARP);
93 packetService.requestPackets(selector.build(),
94 PacketPriority.REACTIVE, appId);
Pingping Line28ae4c2015-03-13 11:37:03 -070095
96 log.info("SDN-IP Reactive Routing Started");
97 }
98
99 @Deactivate
100 public void deactivate() {
101 packetService.removeProcessor(processor);
102 processor = null;
103 log.info("SDN-IP Reactive Routing Stopped");
104 }
105
106 private class ReactiveRoutingProcessor implements PacketProcessor {
107 @Override
108 public void process(PacketContext context) {
109
110 InboundPacket pkt = context.inPacket();
111 Ethernet ethPkt = pkt.parsed();
112 if (ethPkt == null) {
113 return;
114 }
Pingping Line28ae4c2015-03-13 11:37:03 -0700115 ConnectPoint srcConnectPoint = pkt.receivedFrom();
Pingping Line28ae4c2015-03-13 11:37:03 -0700116
Jonathan Hart3217d1b2015-06-30 16:08:43 -0700117 switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
118 case ARP:
Pingping Linc9e16bf2015-04-10 14:42:41 -0700119 ARP arpPacket = (ARP) ethPkt.getPayload();
120 Ip4Address targetIpAddress = Ip4Address
121 .valueOf(arpPacket.getTargetProtocolAddress());
122 // Only when it is an ARP request packet and the target IP
123 // address is a virtual gateway IP address, then it will be
124 // processed.
125 if (arpPacket.getOpCode() == ARP.OP_REQUEST
126 && config.isVirtualGatewayIpAddress(targetIpAddress)) {
127 MacAddress gatewayMacAddress =
128 config.getVirtualGatewayMacAddress();
129 if (gatewayMacAddress == null) {
130 break;
131 }
132 Ethernet eth = ARP.buildArpReply(targetIpAddress,
133 gatewayMacAddress,
134 ethPkt);
135
136 TrafficTreatment.Builder builder =
137 DefaultTrafficTreatment.builder();
138 builder.setOutput(srcConnectPoint.port());
139 packetService.emit(new DefaultOutboundPacket(
140 srcConnectPoint.deviceId(),
141 builder.build(),
142 ByteBuffer.wrap(eth.serialize())));
143 }
144 break;
Jonathan Hart3217d1b2015-06-30 16:08:43 -0700145 case IPV4:
Pingping Linc9e16bf2015-04-10 14:42:41 -0700146 // Parse packet
147 IPv4 ipv4Packet = (IPv4) ethPkt.getPayload();
148 IpAddress dstIp =
149 IpAddress.valueOf(ipv4Packet.getDestinationAddress());
150 IpAddress srcIp =
151 IpAddress.valueOf(ipv4Packet.getSourceAddress());
152 MacAddress srcMac = ethPkt.getSourceMAC();
153 routingService.packetReactiveProcessor(dstIp, srcIp,
154 srcConnectPoint, srcMac);
155
156 // TODO emit packet first or packetReactiveProcessor first
157 ConnectPoint egressConnectPoint = null;
158 egressConnectPoint = routingService.getEgressConnectPoint(dstIp);
159 if (egressConnectPoint != null) {
160 forwardPacketToDst(context, egressConnectPoint);
161 }
162 break;
163 default:
164 break;
Pingping Line28ae4c2015-03-13 11:37:03 -0700165 }
166 }
167 }
168
169 /**
170 * Emits the specified packet onto the network.
171 *
172 * @param context the packet context
173 * @param connectPoint the connect point where the packet should be
174 * sent out
175 */
176 private void forwardPacketToDst(PacketContext context,
177 ConnectPoint connectPoint) {
178 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
179 .setOutput(connectPoint.port()).build();
180 OutboundPacket packet =
181 new DefaultOutboundPacket(connectPoint.deviceId(), treatment,
182 context.inPacket().unparsed());
183 packetService.emit(packet);
184 log.trace("sending packet: {}", packet);
185 }
186
187}
188