alshabib

avoid other OF listeners overwriting the priority of another listener

...@@ -13,12 +13,13 @@ public final class PortNumber { ...@@ -13,12 +13,13 @@ public final class PortNumber {
13 13
14 private static final long MAX_NUMBER = (2L * Integer.MAX_VALUE) + 1; 14 private static final long MAX_NUMBER = (2L * Integer.MAX_VALUE) + 1;
15 15
16 - public static final PortNumber FLOOD = new PortNumber(-1); 16 +
17 - public static final PortNumber IN_PORT = new PortNumber(-2); 17 + public static final PortNumber IN_PORT = new PortNumber(-8);
18 - public static final PortNumber TABLE = new PortNumber(-3); 18 + public static final PortNumber TABLE = new PortNumber(-7);
19 - public static final PortNumber NORMAL = new PortNumber(-4); 19 + public static final PortNumber NORMAL = new PortNumber(-6);
20 + public static final PortNumber FLOOD = new PortNumber(-5);
20 public static final PortNumber ALL = new PortNumber(-4); 21 public static final PortNumber ALL = new PortNumber(-4);
21 - public static final PortNumber LOCAL = new PortNumber(-5); 22 + public static final PortNumber LOCAL = new PortNumber(-2);
22 23
23 private final long number; 24 private final long number;
24 25
......
1 package org.onlab.onos.net.packet; 1 package org.onlab.onos.net.packet;
2 2
3 +import java.util.concurrent.atomic.AtomicBoolean;
4 +
3 import org.onlab.onos.net.flow.DefaultTrafficTreatment; 5 import org.onlab.onos.net.flow.DefaultTrafficTreatment;
4 import org.onlab.onos.net.flow.TrafficTreatment; 6 import org.onlab.onos.net.flow.TrafficTreatment;
5 import org.onlab.onos.net.flow.TrafficTreatment.Builder; 7 import org.onlab.onos.net.flow.TrafficTreatment.Builder;
...@@ -12,7 +14,7 @@ public abstract class DefaultPacketContext implements PacketContext { ...@@ -12,7 +14,7 @@ public abstract class DefaultPacketContext implements PacketContext {
12 private final OutboundPacket outPkt; 14 private final OutboundPacket outPkt;
13 private final TrafficTreatment.Builder builder; 15 private final TrafficTreatment.Builder builder;
14 16
15 - private boolean block = false; 17 + private final AtomicBoolean block;
16 18
17 19
18 protected DefaultPacketContext(long time, InboundPacket inPkt, 20 protected DefaultPacketContext(long time, InboundPacket inPkt,
...@@ -21,7 +23,7 @@ public abstract class DefaultPacketContext implements PacketContext { ...@@ -21,7 +23,7 @@ public abstract class DefaultPacketContext implements PacketContext {
21 this.time = time; 23 this.time = time;
22 this.inPkt = inPkt; 24 this.inPkt = inPkt;
23 this.outPkt = outPkt; 25 this.outPkt = outPkt;
24 - this.block = block; 26 + this.block = new AtomicBoolean(block);
25 this.builder = new DefaultTrafficTreatment.Builder(); 27 this.builder = new DefaultTrafficTreatment.Builder();
26 } 28 }
27 29
...@@ -49,13 +51,12 @@ public abstract class DefaultPacketContext implements PacketContext { ...@@ -49,13 +51,12 @@ public abstract class DefaultPacketContext implements PacketContext {
49 public abstract void send(); 51 public abstract void send();
50 52
51 @Override 53 @Override
52 - public void block() { 54 + public boolean blocked() {
53 - this.block = true; 55 + return this.block.getAndSet(true);
54 } 56 }
55 57
56 @Override 58 @Override
57 public boolean isHandled() { 59 public boolean isHandled() {
58 - return this.block; 60 + return this.block.get();
59 } 61 }
60 -
61 } 62 }
......
...@@ -43,14 +43,13 @@ public interface PacketContext { ...@@ -43,14 +43,13 @@ public interface PacketContext {
43 43
44 /** 44 /**
45 * Blocks the outbound packet from being sent from this point onward. 45 * Blocks the outbound packet from being sent from this point onward.
46 + * @return whether the outbound packet is blocked.
46 */ 47 */
47 - void block(); 48 + boolean blocked();
48 49
49 /** 50 /**
50 - * Indicates whether the packet has already been handled, i.e. sent or 51 + * Check whether the outbound packet is blocked.
51 - * blocked. 52 + * @return
52 - *
53 - * @return true if sent or blocked
54 */ 53 */
55 boolean isHandled(); 54 boolean isHandled();
56 55
......
1 package org.onlab.onos.net.device; 1 package org.onlab.onos.net.device;
2 2
3 +import static org.junit.Assert.assertEquals;
4 +import static org.onlab.onos.net.DeviceId.deviceId;
5 +
3 import org.junit.Test; 6 import org.junit.Test;
4 import org.onlab.onos.event.AbstractEventTest; 7 import org.onlab.onos.event.AbstractEventTest;
5 import org.onlab.onos.net.DefaultDevice; 8 import org.onlab.onos.net.DefaultDevice;
...@@ -9,9 +12,6 @@ import org.onlab.onos.net.Port; ...@@ -9,9 +12,6 @@ import org.onlab.onos.net.Port;
9 import org.onlab.onos.net.PortNumber; 12 import org.onlab.onos.net.PortNumber;
10 import org.onlab.onos.net.provider.ProviderId; 13 import org.onlab.onos.net.provider.ProviderId;
11 14
12 -import static org.junit.Assert.assertEquals;
13 -import static org.onlab.onos.net.DeviceId.deviceId;
14 -
15 /** 15 /**
16 * Tests of the device event. 16 * Tests of the device event.
17 */ 17 */
...@@ -22,20 +22,22 @@ public class DeviceEventTest extends AbstractEventTest { ...@@ -22,20 +22,22 @@ public class DeviceEventTest extends AbstractEventTest {
22 Device.Type.SWITCH, "box", "hw", "sw", "sn"); 22 Device.Type.SWITCH, "box", "hw", "sw", "sn");
23 } 23 }
24 24
25 + @Override
25 @Test 26 @Test
26 public void withTime() { 27 public void withTime() {
27 Device device = createDevice(); 28 Device device = createDevice();
28 - Port port = new DefaultPort(device, PortNumber.portNumber(123L), true); 29 + Port port = new DefaultPort(device, PortNumber.portNumber(123), true);
29 DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, 30 DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED,
30 device, port, 123L); 31 device, port, 123L);
31 validateEvent(event, DeviceEvent.Type.DEVICE_ADDED, device, 123L); 32 validateEvent(event, DeviceEvent.Type.DEVICE_ADDED, device, 123L);
32 assertEquals("incorrect port", port, event.port()); 33 assertEquals("incorrect port", port, event.port());
33 } 34 }
34 35
36 + @Override
35 @Test 37 @Test
36 public void withoutTime() { 38 public void withoutTime() {
37 Device device = createDevice(); 39 Device device = createDevice();
38 - Port port = new DefaultPort(device, PortNumber.portNumber(123L), true); 40 + Port port = new DefaultPort(device, PortNumber.portNumber(123), true);
39 long before = System.currentTimeMillis(); 41 long before = System.currentTimeMillis();
40 DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device); 42 DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device);
41 long after = System.currentTimeMillis(); 43 long after = System.currentTimeMillis();
......
...@@ -3,6 +3,7 @@ package org.onlab.onos.of.controller; ...@@ -3,6 +3,7 @@ package org.onlab.onos.of.controller;
3 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
4 4
5 import java.util.Collections; 5 import java.util.Collections;
6 +import java.util.concurrent.atomic.AtomicBoolean;
6 7
7 import org.onlab.packet.Ethernet; 8 import org.onlab.packet.Ethernet;
8 import org.projectfloodlight.openflow.protocol.OFPacketIn; 9 import org.projectfloodlight.openflow.protocol.OFPacketIn;
...@@ -18,7 +19,7 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext ...@@ -18,7 +19,7 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext
18 19
19 private final Logger log = getLogger(getClass()); 20 private final Logger log = getLogger(getClass());
20 21
21 - private boolean free = true; 22 + private final AtomicBoolean free = new AtomicBoolean(true);
22 private boolean isBuilt = false; 23 private boolean isBuilt = false;
23 private final OpenFlowSwitch sw; 24 private final OpenFlowSwitch sw;
24 private final OFPacketIn pktin; 25 private final OFPacketIn pktin;
...@@ -30,14 +31,8 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext ...@@ -30,14 +31,8 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext
30 } 31 }
31 32
32 @Override 33 @Override
33 - public void block() {
34 - free = false;
35 - }
36 -
37 - @Override
38 public void send() { 34 public void send() {
39 - if (free && isBuilt) { 35 + if (blocked() && isBuilt) {
40 - block();
41 sw.sendMsg(pktout); 36 sw.sendMsg(pktout);
42 } 37 }
43 } 38 }
...@@ -111,4 +106,9 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext ...@@ -111,4 +106,9 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext
111 return act; 106 return act;
112 } 107 }
113 108
109 + @Override
110 + public boolean blocked() {
111 + return free.getAndSet(false);
112 + }
113 +
114 } 114 }
......
...@@ -16,7 +16,7 @@ public interface OpenFlowPacketContext { ...@@ -16,7 +16,7 @@ public interface OpenFlowPacketContext {
16 * Blocks further responses (ie. send() calls) on this 16 * Blocks further responses (ie. send() calls) on this
17 * packet in event. 17 * packet in event.
18 */ 18 */
19 - public void block(); 19 + public boolean blocked();
20 20
21 /** 21 /**
22 * Provided build has been called send the packet 22 * Provided build has been called send the packet
......
1 package org.onlab.onos.of.controller.impl; 1 package org.onlab.onos.of.controller.impl;
2 2
3 import java.util.HashSet; 3 import java.util.HashSet;
4 -import java.util.Map;
5 import java.util.Set; 4 import java.util.Set;
6 -import java.util.TreeMap;
7 import java.util.concurrent.ConcurrentHashMap; 5 import java.util.concurrent.ConcurrentHashMap;
8 import java.util.concurrent.locks.Lock; 6 import java.util.concurrent.locks.Lock;
9 import java.util.concurrent.locks.ReentrantLock; 7 import java.util.concurrent.locks.ReentrantLock;
...@@ -27,6 +25,9 @@ import org.projectfloodlight.openflow.protocol.OFPortStatus; ...@@ -27,6 +25,9 @@ import org.projectfloodlight.openflow.protocol.OFPortStatus;
27 import org.slf4j.Logger; 25 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory; 26 import org.slf4j.LoggerFactory;
29 27
28 +import com.google.common.collect.ArrayListMultimap;
29 +import com.google.common.collect.Multimap;
30 +
30 @Component(immediate = true) 31 @Component(immediate = true)
31 @Service 32 @Service
32 public class OpenFlowControllerImpl implements OpenFlowController { 33 public class OpenFlowControllerImpl implements OpenFlowController {
...@@ -44,7 +45,9 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -44,7 +45,9 @@ public class OpenFlowControllerImpl implements OpenFlowController {
44 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent(); 45 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
45 protected Set<OpenFlowSwitchListener> ofEventListener = new HashSet<>(); 46 protected Set<OpenFlowSwitchListener> ofEventListener = new HashSet<>();
46 47
47 - protected Map<Integer, PacketListener> ofPacketListener = new TreeMap<>(); 48 + protected Multimap<Integer, PacketListener> ofPacketListener =
49 + ArrayListMultimap.create();
50 +
48 51
49 private final Controller ctrl = new Controller(); 52 private final Controller ctrl = new Controller();
50 53
......
1 package org.onlab.onos.provider.of.link.impl; 1 package org.onlab.onos.provider.of.link.impl;
2 2
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import java.util.Map;
6 +import java.util.concurrent.ConcurrentHashMap;
7 +
3 import org.apache.felix.scr.annotations.Activate; 8 import org.apache.felix.scr.annotations.Activate;
4 import org.apache.felix.scr.annotations.Component; 9 import org.apache.felix.scr.annotations.Component;
5 import org.apache.felix.scr.annotations.Deactivate; 10 import org.apache.felix.scr.annotations.Deactivate;
...@@ -13,9 +18,9 @@ import org.onlab.onos.net.provider.AbstractProvider; ...@@ -13,9 +18,9 @@ import org.onlab.onos.net.provider.AbstractProvider;
13 import org.onlab.onos.net.provider.ProviderId; 18 import org.onlab.onos.net.provider.ProviderId;
14 import org.onlab.onos.of.controller.Dpid; 19 import org.onlab.onos.of.controller.Dpid;
15 import org.onlab.onos.of.controller.OpenFlowController; 20 import org.onlab.onos.of.controller.OpenFlowController;
21 +import org.onlab.onos.of.controller.OpenFlowPacketContext;
16 import org.onlab.onos.of.controller.OpenFlowSwitch; 22 import org.onlab.onos.of.controller.OpenFlowSwitch;
17 import org.onlab.onos.of.controller.OpenFlowSwitchListener; 23 import org.onlab.onos.of.controller.OpenFlowSwitchListener;
18 -import org.onlab.onos.of.controller.OpenFlowPacketContext;
19 import org.onlab.onos.of.controller.PacketListener; 24 import org.onlab.onos.of.controller.PacketListener;
20 import org.projectfloodlight.openflow.protocol.OFPortConfig; 25 import org.projectfloodlight.openflow.protocol.OFPortConfig;
21 import org.projectfloodlight.openflow.protocol.OFPortDesc; 26 import org.projectfloodlight.openflow.protocol.OFPortDesc;
...@@ -23,11 +28,6 @@ import org.projectfloodlight.openflow.protocol.OFPortState; ...@@ -23,11 +28,6 @@ import org.projectfloodlight.openflow.protocol.OFPortState;
23 import org.projectfloodlight.openflow.protocol.OFPortStatus; 28 import org.projectfloodlight.openflow.protocol.OFPortStatus;
24 import org.slf4j.Logger; 29 import org.slf4j.Logger;
25 30
26 -import java.util.Map;
27 -import java.util.concurrent.ConcurrentHashMap;
28 -
29 -import static org.slf4j.LoggerFactory.getLogger;
30 -
31 /** 31 /**
32 * Provider which uses an OpenFlow controller to detect network 32 * Provider which uses an OpenFlow controller to detect network
33 * infrastructure links. 33 * infrastructure links.
...@@ -93,7 +93,7 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid ...@@ -93,7 +93,7 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid
93 return; 93 return;
94 } 94 }
95 if (ld.handleLLDP(pktCtx.unparsed(), pktCtx.inPort())) { 95 if (ld.handleLLDP(pktCtx.unparsed(), pktCtx.inPort())) {
96 - pktCtx.block(); 96 + pktCtx.blocked();
97 } 97 }
98 98
99 } 99 }
......
...@@ -2,6 +2,11 @@ package org.onlab.onos.provider.of.packet.impl; ...@@ -2,6 +2,11 @@ package org.onlab.onos.provider.of.packet.impl;
2 2
3 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
4 4
5 +import java.util.List;
6 +
7 +import org.onlab.onos.net.PortNumber;
8 +import org.onlab.onos.net.flow.Instruction;
9 +import org.onlab.onos.net.flow.Instruction.Type;
5 import org.onlab.onos.net.packet.DefaultPacketContext; 10 import org.onlab.onos.net.packet.DefaultPacketContext;
6 import org.onlab.onos.net.packet.InboundPacket; 11 import org.onlab.onos.net.packet.InboundPacket;
7 import org.onlab.onos.net.packet.OutboundPacket; 12 import org.onlab.onos.net.packet.OutboundPacket;
...@@ -24,18 +29,36 @@ public class OpenFlowCorePacketContext extends DefaultPacketContext { ...@@ -24,18 +29,36 @@ public class OpenFlowCorePacketContext extends DefaultPacketContext {
24 29
25 @Override 30 @Override
26 public void send() { 31 public void send() {
27 - if (!this.isHandled()) { 32 + if (!this.blocked()) {
28 - block();
29 if (outPacket() == null) { 33 if (outPacket() == null) {
30 - ofPktCtx.build(OFPort.FLOOD); 34 + sendBufferedPacket();
31 } else { 35 } else {
32 Ethernet eth = new Ethernet(); 36 Ethernet eth = new Ethernet();
33 eth.deserialize(outPacket().data().array(), 0, 37 eth.deserialize(outPacket().data().array(), 0,
34 outPacket().data().array().length); 38 outPacket().data().array().length);
35 ofPktCtx.build(eth, OFPort.FLOOD); 39 ofPktCtx.build(eth, OFPort.FLOOD);
36 } 40 }
41 +
42 + }
43 + }
44 +
45 + @SuppressWarnings({ "rawtypes", "unchecked" })
46 + private void sendBufferedPacket() {
47 + List<Instruction> ins = treatmentBuilder().build().instructions();
48 + OFPort p = null;
49 + //TODO: support arbitrary list of treatments
50 + for (Instruction i : ins) {
51 + if (i.type() == Type.OUTPUT) {
52 + p = buildPort(((Instruction<PortNumber>) i).instruction());
53 + break; //for now...
54 + }
55 + }
56 + ofPktCtx.build(p);
37 ofPktCtx.send(); 57 ofPktCtx.send();
38 } 58 }
59 +
60 + private OFPort buildPort(PortNumber port) {
61 + return OFPort.of((int) port.toLong());
39 } 62 }
40 63
41 } 64 }
......