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