blob: 9dd657ee5787e438b94345d9f31a33e50aff8af4 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.ifwd;
toma9a77c22014-10-03 17:05:20 -070017
Jonathan Harte8600eb2015-01-12 10:30:45 -080018import static org.slf4j.LoggerFactory.getLogger;
19
toma9a77c22014-10-03 17:05:20 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Harte8600eb2015-01-12 10:30:45 -080025import org.onlab.packet.Ethernet;
Brian O'Connorabafb502014-12-02 22:26:20 -080026import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
Jonathan Hart06ae79d2015-01-13 18:56:33 -080028import org.onosproject.net.Device;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.net.Host;
30import org.onosproject.net.HostId;
31import org.onosproject.net.PortNumber;
Jonathan Hart06ae79d2015-01-13 18:56:33 -080032import org.onosproject.net.device.DeviceEvent;
33import org.onosproject.net.device.DeviceListener;
34import org.onosproject.net.device.DeviceService;
35import org.onosproject.net.flow.DefaultFlowRule;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.flow.DefaultTrafficSelector;
37import org.onosproject.net.flow.DefaultTrafficTreatment;
Jonathan Hart06ae79d2015-01-13 18:56:33 -080038import org.onosproject.net.flow.FlowRule;
39import org.onosproject.net.flow.FlowRuleService;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.flow.TrafficSelector;
41import org.onosproject.net.flow.TrafficTreatment;
42import org.onosproject.net.host.HostService;
43import org.onosproject.net.intent.HostToHostIntent;
44import org.onosproject.net.intent.IntentService;
45import org.onosproject.net.packet.DefaultOutboundPacket;
46import org.onosproject.net.packet.InboundPacket;
47import org.onosproject.net.packet.OutboundPacket;
48import org.onosproject.net.packet.PacketContext;
49import org.onosproject.net.packet.PacketProcessor;
50import org.onosproject.net.packet.PacketService;
51import org.onosproject.net.topology.TopologyService;
toma9a77c22014-10-03 17:05:20 -070052import org.slf4j.Logger;
53
toma9a77c22014-10-03 17:05:20 -070054/**
55 * WORK-IN-PROGRESS: Sample reactive forwarding application using intent framework.
56 */
57@Component(immediate = true)
58public class IntentReactiveForwarding {
59
toma9a77c22014-10-03 17:05:20 -070060 private final Logger log = getLogger(getClass());
61
Jonathan Hart06ae79d2015-01-13 18:56:33 -080062 private static final int PUNT_RULE_PRIORITY = 5;
63
toma9a77c22014-10-03 17:05:20 -070064 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuskab97cf282014-10-20 23:31:12 -070065 protected CoreService coreService;
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
toma9a77c22014-10-03 17:05:20 -070068 protected TopologyService topologyService;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected PacketService packetService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected IntentService intentService;
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected HostService hostService;
78
Jonathan Hart06ae79d2015-01-13 18:56:33 -080079 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected FlowRuleService flowRuleService;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected DeviceService deviceService;
84
toma9a77c22014-10-03 17:05:20 -070085 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
Thomas Vachuskab97cf282014-10-20 23:31:12 -070086 private ApplicationId appId;
toma9a77c22014-10-03 17:05:20 -070087
88 @Activate
89 public void activate() {
Brian O'Connorabafb502014-12-02 22:26:20 -080090 appId = coreService.registerApplication("org.onosproject.ifwd");
Jonathan Hart06ae79d2015-01-13 18:56:33 -080091 deviceService.addListener(new InternalDeviceListener());
92 pushRules();
toma9a77c22014-10-03 17:05:20 -070093 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
tom0511a522014-10-04 12:06:02 -070094 log.info("Started");
toma9a77c22014-10-03 17:05:20 -070095 }
96
97 @Deactivate
98 public void deactivate() {
99 packetService.removeProcessor(processor);
100 processor = null;
101 log.info("Stopped");
102 }
103
toma9a77c22014-10-03 17:05:20 -0700104 /**
105 * Packet processor responsible for forwarding packets along their paths.
106 */
107 private class ReactivePacketProcessor implements PacketProcessor {
108
109 @Override
110 public void process(PacketContext context) {
111 // Stop processing if the packet has been handled, since we
112 // can't do any more to it.
113 if (context.isHandled()) {
114 return;
115 }
116
117 InboundPacket pkt = context.inPacket();
118 Ethernet ethPkt = pkt.parsed();
119
Jonathan Harte8600eb2015-01-12 10:30:45 -0800120 if (ethPkt == null) {
121 return;
122 }
123
toma9a77c22014-10-03 17:05:20 -0700124 HostId srcId = HostId.hostId(ethPkt.getSourceMAC());
125 HostId dstId = HostId.hostId(ethPkt.getDestinationMAC());
126
127 // Do we know who this is for? If not, flood and bail.
128 Host dst = hostService.getHost(dstId);
129 if (dst == null) {
130 flood(context);
131 return;
132 }
133
134 // Otherwise forward and be done with it.
135 setUpConnectivity(context, srcId, dstId);
Brian O'Connor958d3812014-10-03 19:46:23 -0700136 forwardPacketToDst(context, dst);
toma9a77c22014-10-03 17:05:20 -0700137 }
138 }
139
140 // Floods the specified packet if permissible.
141 private void flood(PacketContext context) {
142 if (topologyService.isBroadcastPoint(topologyService.currentTopology(),
143 context.inPacket().receivedFrom())) {
144 packetOut(context, PortNumber.FLOOD);
145 } else {
146 context.block();
147 }
148 }
149
150 // Sends a packet out the specified port.
151 private void packetOut(PacketContext context, PortNumber portNumber) {
152 context.treatmentBuilder().setOutput(portNumber);
153 context.send();
154 }
155
Brian O'Connor958d3812014-10-03 19:46:23 -0700156 private void forwardPacketToDst(PacketContext context, Host dst) {
157 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(dst.location().port()).build();
158 OutboundPacket packet = new DefaultOutboundPacket(dst.location().deviceId(),
tom0511a522014-10-04 12:06:02 -0700159 treatment, context.inPacket().unparsed());
Brian O'Connor958d3812014-10-03 19:46:23 -0700160 packetService.emit(packet);
161 log.info("sending packet: {}", packet);
162 }
163
toma9a77c22014-10-03 17:05:20 -0700164 // Install a rule forwarding the packet to the specified port.
165 private void setUpConnectivity(PacketContext context, HostId srcId, HostId dstId) {
166 TrafficSelector selector = DefaultTrafficSelector.builder().build();
167 TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
168
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700169 HostToHostIntent intent = new HostToHostIntent(appId, srcId, dstId,
170 selector, treatment);
toma9a77c22014-10-03 17:05:20 -0700171
172 intentService.submit(intent);
173 }
174
Jonathan Hart06ae79d2015-01-13 18:56:33 -0800175 /**
176 * Pushes flow rules to all devices.
177 */
178 private void pushRules() {
179 for (Device device : deviceService.getDevices()) {
180 pushRules(device);
181 }
182 }
183
184 /**
185 * Pushes flow rules to the device to receive packets that need
186 * to be processed.
187 *
188 * @param device the device to push the rules to
189 */
190 private synchronized void pushRules(Device device) {
191 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
192 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
193
194 // Get all IPv4 packets
195 sbuilder.matchEthType(Ethernet.TYPE_IPV4);
196 tbuilder.punt();
197 FlowRule flowArp =
198 new DefaultFlowRule(device.id(),
199 sbuilder.build(), tbuilder.build(),
200 PUNT_RULE_PRIORITY, appId, 0, true);
201
202 flowRuleService.applyFlowRules(flowArp);
203 }
204
205 public class InternalDeviceListener implements DeviceListener {
206
207 @Override
208 public void event(DeviceEvent event) {
209 Device device = event.subject();
210 switch (event.type()) {
211 case DEVICE_ADDED:
212 pushRules(device);
213 break;
214 case DEVICE_AVAILABILITY_CHANGED:
215 case DEVICE_SUSPENDED:
216 case DEVICE_UPDATED:
217 case DEVICE_REMOVED:
218 case PORT_ADDED:
219 case PORT_UPDATED:
220 case PORT_REMOVED:
221 default:
222 break;
223 }
224 }
225 }
226
toma9a77c22014-10-03 17:05:20 -0700227}