Jonathan Hart
Committed by Gerrit Code Review

Reactive forwarding apps should explicitly ask for packets they want to receive.

Previously we relied on the table-miss entry set up for OVS switches, but
this doesn't work for non-OVS switches 1.3 switches.

Fixes ONOS-661.

Change-Id: Ibc0aee09f304eaf240691a4d5d2f8765a5f8cdd5
...@@ -30,10 +30,14 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -30,10 +30,14 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
30 import org.onlab.packet.Ethernet; 30 import org.onlab.packet.Ethernet;
31 import org.onosproject.core.ApplicationId; 31 import org.onosproject.core.ApplicationId;
32 import org.onosproject.core.CoreService; 32 import org.onosproject.core.CoreService;
33 +import org.onosproject.net.Device;
33 import org.onosproject.net.Host; 34 import org.onosproject.net.Host;
34 import org.onosproject.net.HostId; 35 import org.onosproject.net.HostId;
35 import org.onosproject.net.Path; 36 import org.onosproject.net.Path;
36 import org.onosproject.net.PortNumber; 37 import org.onosproject.net.PortNumber;
38 +import org.onosproject.net.device.DeviceEvent;
39 +import org.onosproject.net.device.DeviceListener;
40 +import org.onosproject.net.device.DeviceService;
37 import org.onosproject.net.flow.DefaultFlowRule; 41 import org.onosproject.net.flow.DefaultFlowRule;
38 import org.onosproject.net.flow.DefaultTrafficSelector; 42 import org.onosproject.net.flow.DefaultTrafficSelector;
39 import org.onosproject.net.flow.DefaultTrafficTreatment; 43 import org.onosproject.net.flow.DefaultTrafficTreatment;
...@@ -58,6 +62,7 @@ public class ReactiveForwarding { ...@@ -58,6 +62,7 @@ public class ReactiveForwarding {
58 62
59 private static final int TIMEOUT = 10; 63 private static final int TIMEOUT = 10;
60 private static final int PRIORITY = 10; 64 private static final int PRIORITY = 10;
65 + private static final int PUNT_RULE_PRIORITY = 5;
61 66
62 private final Logger log = getLogger(getClass()); 67 private final Logger log = getLogger(getClass());
63 68
...@@ -74,6 +79,9 @@ public class ReactiveForwarding { ...@@ -74,6 +79,9 @@ public class ReactiveForwarding {
74 protected FlowRuleService flowRuleService; 79 protected FlowRuleService flowRuleService;
75 80
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 + protected DeviceService deviceService;
83 +
84 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected CoreService coreService; 85 protected CoreService coreService;
78 86
79 private ReactivePacketProcessor processor = new ReactivePacketProcessor(); 87 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
...@@ -91,6 +99,8 @@ public class ReactiveForwarding { ...@@ -91,6 +99,8 @@ public class ReactiveForwarding {
91 @Activate 99 @Activate
92 public void activate(ComponentContext context) { 100 public void activate(ComponentContext context) {
93 appId = coreService.registerApplication("org.onosproject.fwd"); 101 appId = coreService.registerApplication("org.onosproject.fwd");
102 + deviceService.addListener(new InternalDeviceListener());
103 + pushRules();
94 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2); 104 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
95 readComponentConfiguration(context); 105 readComponentConfiguration(context);
96 log.info("Started with Application ID {}", appId.id()); 106 log.info("Started with Application ID {}", appId.id());
...@@ -293,6 +303,58 @@ public class ReactiveForwarding { ...@@ -293,6 +303,58 @@ public class ReactiveForwarding {
293 } 303 }
294 } 304 }
295 305
306 + /**
307 + * Pushes flow rules to all devices.
308 + */
309 + private void pushRules() {
310 + for (Device device : deviceService.getDevices()) {
311 + pushRules(device);
312 + }
313 + }
314 +
315 + /**
316 + * Pushes flow rules to the device to receive packets that need
317 + * to be processed.
318 + *
319 + * @param device the device to push the rules to
320 + */
321 + private synchronized void pushRules(Device device) {
322 + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
323 + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
324 +
325 + // Get all IPv4 packets
326 + sbuilder.matchEthType(Ethernet.TYPE_IPV4);
327 + tbuilder.punt();
328 + FlowRule flowArp =
329 + new DefaultFlowRule(device.id(),
330 + sbuilder.build(), tbuilder.build(),
331 + PUNT_RULE_PRIORITY, appId, 0, true);
332 +
333 + flowRuleService.applyFlowRules(flowArp);
334 + }
335 +
336 + public class InternalDeviceListener implements DeviceListener {
337 +
338 + @Override
339 + public void event(DeviceEvent event) {
340 + Device device = event.subject();
341 + switch (event.type()) {
342 + case DEVICE_ADDED:
343 + pushRules(device);
344 + break;
345 + case DEVICE_AVAILABILITY_CHANGED:
346 + case DEVICE_SUSPENDED:
347 + case DEVICE_UPDATED:
348 + case DEVICE_REMOVED:
349 + case PORT_ADDED:
350 + case PORT_UPDATED:
351 + case PORT_REMOVED:
352 + default:
353 + break;
354 + }
355 + }
356 + }
357 +
296 } 358 }
297 359
298 360
......
...@@ -25,11 +25,18 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -25,11 +25,18 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
25 import org.onlab.packet.Ethernet; 25 import org.onlab.packet.Ethernet;
26 import org.onosproject.core.ApplicationId; 26 import org.onosproject.core.ApplicationId;
27 import org.onosproject.core.CoreService; 27 import org.onosproject.core.CoreService;
28 +import org.onosproject.net.Device;
28 import org.onosproject.net.Host; 29 import org.onosproject.net.Host;
29 import org.onosproject.net.HostId; 30 import org.onosproject.net.HostId;
30 import org.onosproject.net.PortNumber; 31 import org.onosproject.net.PortNumber;
32 +import org.onosproject.net.device.DeviceEvent;
33 +import org.onosproject.net.device.DeviceListener;
34 +import org.onosproject.net.device.DeviceService;
35 +import org.onosproject.net.flow.DefaultFlowRule;
31 import org.onosproject.net.flow.DefaultTrafficSelector; 36 import org.onosproject.net.flow.DefaultTrafficSelector;
32 import org.onosproject.net.flow.DefaultTrafficTreatment; 37 import org.onosproject.net.flow.DefaultTrafficTreatment;
38 +import org.onosproject.net.flow.FlowRule;
39 +import org.onosproject.net.flow.FlowRuleService;
33 import org.onosproject.net.flow.TrafficSelector; 40 import org.onosproject.net.flow.TrafficSelector;
34 import org.onosproject.net.flow.TrafficTreatment; 41 import org.onosproject.net.flow.TrafficTreatment;
35 import org.onosproject.net.host.HostService; 42 import org.onosproject.net.host.HostService;
...@@ -52,6 +59,8 @@ public class IntentReactiveForwarding { ...@@ -52,6 +59,8 @@ public class IntentReactiveForwarding {
52 59
53 private final Logger log = getLogger(getClass()); 60 private final Logger log = getLogger(getClass());
54 61
62 + private static final int PUNT_RULE_PRIORITY = 5;
63 +
55 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 protected CoreService coreService; 65 protected CoreService coreService;
57 66
...@@ -67,12 +76,20 @@ public class IntentReactiveForwarding { ...@@ -67,12 +76,20 @@ public class IntentReactiveForwarding {
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected HostService hostService; 77 protected HostService hostService;
69 78
79 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 + protected FlowRuleService flowRuleService;
81 +
82 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 + protected DeviceService deviceService;
84 +
70 private ReactivePacketProcessor processor = new ReactivePacketProcessor(); 85 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
71 private ApplicationId appId; 86 private ApplicationId appId;
72 87
73 @Activate 88 @Activate
74 public void activate() { 89 public void activate() {
75 appId = coreService.registerApplication("org.onosproject.ifwd"); 90 appId = coreService.registerApplication("org.onosproject.ifwd");
91 + deviceService.addListener(new InternalDeviceListener());
92 + pushRules();
76 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2); 93 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
77 log.info("Started"); 94 log.info("Started");
78 } 95 }
...@@ -155,4 +172,56 @@ public class IntentReactiveForwarding { ...@@ -155,4 +172,56 @@ public class IntentReactiveForwarding {
155 intentService.submit(intent); 172 intentService.submit(intent);
156 } 173 }
157 174
175 + /**
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 +
158 } 227 }
......