blob: a74387fa4e25a47a29f6d7aedf4ed70cb5d3b633 [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
19import 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.IPv4;
26import org.onlab.packet.IpAddress;
27import org.onlab.packet.MacAddress;
28import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
30import org.onosproject.net.ConnectPoint;
31import org.onosproject.net.flow.DefaultTrafficSelector;
32import org.onosproject.net.flow.DefaultTrafficTreatment;
33import org.onosproject.net.flow.TrafficSelector;
34import org.onosproject.net.flow.TrafficTreatment;
35import org.onosproject.net.packet.DefaultOutboundPacket;
36import org.onosproject.net.packet.InboundPacket;
37import org.onosproject.net.packet.OutboundPacket;
38import org.onosproject.net.packet.PacketContext;
39import org.onosproject.net.packet.PacketPriority;
40import org.onosproject.net.packet.PacketProcessor;
41import org.onosproject.net.packet.PacketService;
42import org.onosproject.routing.RoutingService;
43import org.slf4j.Logger;
44
45/**
46 * This is reactive routing to handle 3 cases:
47 * (1) one host wants to talk to another host, both two hosts are in
48 * SDN network.
49 * (2) one host in SDN network wants to talk to another host in Internet.
50 * (3) one host from Internet wants to talk to another host in SDN network.
51 */
52@Component(immediate = true)
53public class SdnIpReactiveRouting {
54
55 private static final String APP_NAME = "org.onosproject.reactive.routing";
56 private final Logger log = getLogger(getClass());
57
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 protected CoreService coreService;
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
62 protected PacketService packetService;
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected RoutingService routingService;
66
67 private ApplicationId appId;
68
69 private ReactiveRoutingProcessor processor =
70 new ReactiveRoutingProcessor();
71
72 @Activate
73 public void activate() {
74 appId = coreService.registerApplication(APP_NAME);
75 packetService.addProcessor(processor,
76 PacketProcessor.ADVISOR_MAX + 2);
77
78 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
79 // TODO: to support IPv6 later
80 selector.matchEthType(Ethernet.TYPE_IPV4);
81 packetService.requestPackets(selector.build(),
82 PacketPriority.REACTIVE, appId);
83
84 log.info("SDN-IP Reactive Routing Started");
85 }
86
87 @Deactivate
88 public void deactivate() {
89 packetService.removeProcessor(processor);
90 processor = null;
91 log.info("SDN-IP Reactive Routing Stopped");
92 }
93
94 private class ReactiveRoutingProcessor implements PacketProcessor {
95 @Override
96 public void process(PacketContext context) {
97
98 InboundPacket pkt = context.inPacket();
99 Ethernet ethPkt = pkt.parsed();
100 if (ethPkt == null) {
101 return;
102 }
103
104 // In theory, we do not need to check whether it is Ethernet
105 // TYPE_IPV4. However, due to the current implementation of the
106 // packetService, we will receive all packets from all subscribers.
107 // Hence, we have to check the Ethernet type again here.
108 if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
109 return;
110 }
111
112 // Parse packet
113 IPv4 ipv4Packet = (IPv4) ethPkt.getPayload();
114 IpAddress dstIp =
115 IpAddress.valueOf(ipv4Packet.getDestinationAddress());
116 IpAddress srcIp =
117 IpAddress.valueOf(ipv4Packet.getSourceAddress());
118 ConnectPoint srcConnectPoint = pkt.receivedFrom();
119 MacAddress srcMac = ethPkt.getSourceMAC();
120 routingService.packetReactiveProcessor(dstIp, srcIp,
121 srcConnectPoint, srcMac);
122
123 // TODO emit packet first or packetReactiveProcessor first
124 ConnectPoint egressConnectPoint = null;
125 egressConnectPoint = routingService.getEgressConnectPoint(dstIp);
126 if (egressConnectPoint != null) {
127 forwardPacketToDst(context, egressConnectPoint);
128 }
129 }
130 }
131
132 /**
133 * Emits the specified packet onto the network.
134 *
135 * @param context the packet context
136 * @param connectPoint the connect point where the packet should be
137 * sent out
138 */
139 private void forwardPacketToDst(PacketContext context,
140 ConnectPoint connectPoint) {
141 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
142 .setOutput(connectPoint.port()).build();
143 OutboundPacket packet =
144 new DefaultOutboundPacket(connectPoint.deviceId(), treatment,
145 context.inPacket().unparsed());
146 packetService.emit(packet);
147 log.trace("sending packet: {}", packet);
148 }
149
150}
151