flowrules are pushed: we still have an intermittent hang though
diff --git a/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java b/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java
index b9ae4c4..ce85938 100644
--- a/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java
+++ b/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java
@@ -1,5 +1,9 @@
package org.onlab.onos.fwd;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Set;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -9,6 +13,14 @@
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.flow.DefaultFlowRule;
+import org.onlab.onos.net.flow.DefaultTrafficSelector;
+import org.onlab.onos.net.flow.DefaultTrafficTreatment;
+import org.onlab.onos.net.flow.FlowRule;
+import org.onlab.onos.net.flow.FlowRuleService;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.flow.criteria.Criteria;
import org.onlab.onos.net.flow.instructions.Instructions;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.packet.InboundPacket;
@@ -16,12 +28,9 @@
import org.onlab.onos.net.packet.PacketProcessor;
import org.onlab.onos.net.packet.PacketService;
import org.onlab.onos.net.topology.TopologyService;
+import org.onlab.packet.Ethernet;
import org.slf4j.Logger;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
/**
* Sample reactive forwarding application.
*/
@@ -39,6 +48,9 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowRuleService flowRuleService;
+
private ReactivePacketProcessor processor = new ReactivePacketProcessor();
@Activate
@@ -62,6 +74,9 @@
@Override
public void process(PacketContext context) {
+ if (context.isHandled()) {
+ return;
+ }
InboundPacket pkt = context.inPacket();
HostId id = HostId.hostId(pkt.parsed().getDestinationMAC());
@@ -75,15 +90,16 @@
// Are we on an edge switch that our destination is on? If so,
// simply forward out to the destination and bail.
if (pkt.receivedFrom().deviceId().equals(dst.location().deviceId())) {
- forward(context, dst.location().port());
+ installRule(context, dst.location().port());
return;
}
// Otherwise, get a set of paths that lead from here to the
// destination edge switch.
+
Set<Path> paths = topologyService.getPaths(topologyService.currentTopology(),
- context.inPacket().receivedFrom().deviceId(),
- dst.location().deviceId());
+ context.inPacket().receivedFrom().deviceId(),
+ dst.location().deviceId());
if (paths.isEmpty()) {
// If there are no paths, flood and bail.
flood(context);
@@ -100,7 +116,7 @@
}
// Otherwise forward and be done with it.
- forward(context, path.src().port());
+ installRule(context, path.src().port());
}
}
@@ -118,18 +134,43 @@
// Floods the specified packet.
private void flood(PacketContext context) {
boolean canBcast = topologyService.isBroadcastPoint(topologyService.currentTopology(),
- context.inPacket().receivedFrom());
+ context.inPacket().receivedFrom());
if (canBcast) {
- forward(context, PortNumber.FLOOD);
+ packetOutFlood(context);
} else {
context.block();
}
}
- // Forwards the packet to the specified port.
- private void forward(PacketContext context, PortNumber portNumber) {
+ //Floods a packet out
+ private void packetOutFlood(PacketContext context) {
+ context.treatmentBuilder().add(Instructions.createOutput(PortNumber.FLOOD));
+ context.send();
+ }
+
+ // Install a rule forwarding the packet to the specified port.
+ private void installRule(PacketContext context, PortNumber portNumber) {
+ // we don't yet support bufferids in the flowservice so packet out and
+ // then install a flowmod.
context.treatmentBuilder().add(Instructions.createOutput(portNumber));
context.send();
+
+
+ Ethernet inPkt = context.inPacket().parsed();
+ TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
+ builder.add(Criteria.matchEthType(inPkt.getEtherType()))
+ .add(Criteria.matchEthSrc(inPkt.getSourceMAC()))
+ .add(Criteria.matchEthDst(inPkt.getDestinationMAC()))
+ .add(Criteria.matchInPort(context.inPacket().receivedFrom().port()));
+
+ TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder();
+ treat.add(Instructions.createOutput(portNumber));
+
+ FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(),
+ builder.build(), treat.build());
+
+ flowRuleService.applyFlowRules(f);
+
}
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
new file mode 100644
index 0000000..801e8f9
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
@@ -0,0 +1,38 @@
+package org.onlab.onos.net.flow;
+
+import org.onlab.onos.net.DeviceId;
+
+public class DefaultFlowRule implements FlowRule {
+
+ private final TrafficSelector selector;
+ private final TrafficTreatment treatment;
+ private final DeviceId deviceId;
+
+ public DefaultFlowRule(DeviceId deviceId,
+ TrafficSelector selector, TrafficTreatment treatment) {
+ this.treatment = treatment;
+ this.selector = selector;
+ this.deviceId = deviceId;
+ }
+
+ @Override
+ public int priority() {
+ return 0;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public TrafficSelector selector() {
+ return selector;
+ }
+
+ @Override
+ public TrafficTreatment treatment() {
+ return treatment;
+ }
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultTrafficSelector.java b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultTrafficSelector.java
new file mode 100644
index 0000000..9ec49e4
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultTrafficSelector.java
@@ -0,0 +1,44 @@
+package org.onlab.onos.net.flow;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.onlab.onos.net.flow.criteria.Criterion;
+import org.slf4j.Logger;
+
+public final class DefaultTrafficSelector implements TrafficSelector {
+
+ private final List<Criterion> selector;
+
+ private DefaultTrafficSelector(List<Criterion> selector) {
+ this.selector = Collections.unmodifiableList(selector);
+ }
+
+ @Override
+ public List<Criterion> criteria() {
+ return selector;
+ }
+
+ public static class Builder implements TrafficSelector.Builder {
+
+ private final Logger log = getLogger(getClass());
+
+ private final List<Criterion> selector = new LinkedList<>();
+
+ @Override
+ public TrafficSelector.Builder add(Criterion criterion) {
+ selector.add(criterion);
+ return this;
+ }
+
+ @Override
+ public TrafficSelector build() {
+ return new DefaultTrafficSelector(selector);
+ }
+
+ }
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultTrafficTreatment.java b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultTrafficTreatment.java
index 0bf4ea8..9de68dc 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultTrafficTreatment.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultTrafficTreatment.java
@@ -9,12 +9,11 @@
import org.onlab.onos.net.flow.instructions.Instruction;
import org.slf4j.Logger;
-@SuppressWarnings("rawtypes")
-public class DefaultTrafficTreatment implements TrafficTreatment {
+public final class DefaultTrafficTreatment implements TrafficTreatment {
private final List<Instruction> instructions;
- public DefaultTrafficTreatment(List<Instruction> instructions) {
+ private DefaultTrafficTreatment(List<Instruction> instructions) {
this.instructions = Collections.unmodifiableList(instructions);
}
diff --git a/features/features.xml b/features/features.xml
index d96b2fd..205d78e 100644
--- a/features/features.xml
+++ b/features/features.xml
@@ -69,6 +69,7 @@
<bundle>mvn:org.onlab.onos/onos-of-provider-link/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-of-provider-host/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-of-provider-packet/1.0.0-SNAPSHOT</bundle>
+ <bundle>mvn:org.onlab.onos/onos-of-provider-flow/1.0.0-SNAPSHOT</bundle>
</feature>
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/DefaultOpenFlowPacketContext.java b/of/api/src/main/java/org/onlab/onos/of/controller/DefaultOpenFlowPacketContext.java
index efb41b8..fd47ad3 100644
--- a/of/api/src/main/java/org/onlab/onos/of/controller/DefaultOpenFlowPacketContext.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/DefaultOpenFlowPacketContext.java
@@ -32,7 +32,7 @@
@Override
public void send() {
- if (blocked() && isBuilt) {
+ if (block() && isBuilt) {
sw.sendMsg(pktout);
}
}
@@ -109,8 +109,13 @@
}
@Override
- public boolean blocked() {
+ public boolean block() {
return free.getAndSet(false);
}
+ @Override
+ public boolean isHandled() {
+ return !free.get();
+ }
+
}
diff --git a/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowPacketContext.java b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowPacketContext.java
index e1360e2..0e90f95 100644
--- a/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowPacketContext.java
+++ b/of/api/src/main/java/org/onlab/onos/of/controller/OpenFlowPacketContext.java
@@ -16,7 +16,13 @@
* Blocks further responses (ie. send() calls) on this
* packet in event.
*/
- public boolean blocked();
+ public boolean block();
+
+ /**
+ * Checks whether the packet has been handled.
+ * @return true if handled, false otherwise.
+ */
+ public boolean isHandled();
/**
* Provided build has been called send the packet
diff --git a/providers/of/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/of/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
index 9a11a36..44b0792 100644
--- a/providers/of/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/of/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -26,6 +26,7 @@
import org.onlab.onos.net.flow.criteria.Criteria.VlanPcpCriterion;
import org.onlab.onos.net.flow.criteria.Criterion;
import org.onlab.onos.net.flow.instructions.Instruction;
+import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
@@ -136,6 +137,9 @@
case L3MODIFICATION:
acts.add(buildL3Modification(i, factory));
case OUTPUT:
+ OutputInstruction out = (OutputInstruction) i;
+ acts.add(factory.actions().buildOutput().setPort(
+ OFPort.of((int) out.port().toLong())).build());
break;
case GROUP:
default:
@@ -207,6 +211,7 @@
case ETH_TYPE:
EthTypeCriterion ethType = (EthTypeCriterion) c;
mBuilder.setExact(MatchField.ETH_TYPE, EthType.of(ethType.ethType()));
+ break;
case IPV4_DST:
ip = (IPCriterion) c;
mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toInt()));
diff --git a/providers/of/host/src/test/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProviderTest.java b/providers/of/host/src/test/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProviderTest.java
index 4138111..ea8db19 100644
--- a/providers/of/host/src/test/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProviderTest.java
+++ b/providers/of/host/src/test/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProviderTest.java
@@ -1,5 +1,11 @@
package org.onlab.onos.provider.of.host.impl;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.Set;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -24,10 +30,6 @@
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.types.OFPort;
-import java.util.Set;
-
-import static org.junit.Assert.*;
-
public class OpenFlowHostProviderTest {
private static final Integer INPORT = 10;
@@ -40,10 +42,10 @@
private static final MacAddress BCMAC = MacAddress.valueOf("ff:ff:ff:ff:ff:ff");
private static final byte[] IP = new byte[]{10, 0, 0, 1};
- private OpenFlowHostProvider provider = new OpenFlowHostProvider();
- private TestHostRegistry hostService = new TestHostRegistry();
- private TestController controller = new TestController();
- private TestTopologyService topoService = new TestTopologyService();
+ private final OpenFlowHostProvider provider = new OpenFlowHostProvider();
+ private final TestHostRegistry hostService = new TestHostRegistry();
+ private final TestController controller = new TestController();
+ private final TestTopologyService topoService = new TestTopologyService();
private TestHostProviderService providerService;
@Before
@@ -103,8 +105,8 @@
}
private class TestHostProviderService
- extends AbstractProviderService<HostProvider>
- implements HostProviderService {
+ extends AbstractProviderService<HostProvider>
+ implements HostProviderService {
Dpid added = null;
Dpid moved = null;
@@ -150,7 +152,7 @@
private class TestTopologyService extends TopologyServiceAdapter {
@Override
public boolean isInfrastructure(Topology topology,
- ConnectPoint connectPoint) {
+ ConnectPoint connectPoint) {
//simulate DPID3 as an infrastructure switch
if (Dpid.dpid(connectPoint.deviceId().uri()).equals(DPID3)) {
return true;
@@ -168,7 +170,7 @@
}
@Override
- public boolean blocked() {
+ public boolean block() {
return false;
}
@@ -189,16 +191,16 @@
// just things we (and serializers) need
ARP arp = new ARP();
arp.setSenderProtocolAddress(IP)
- .setSenderHardwareAddress(MAC.toBytes())
- .setTargetHardwareAddress(BCMAC.toBytes())
- .setTargetProtocolAddress(IP);
+ .setSenderHardwareAddress(MAC.toBytes())
+ .setTargetHardwareAddress(BCMAC.toBytes())
+ .setTargetProtocolAddress(IP);
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_ARP)
- .setVlanID(VLAN.toShort())
- .setSourceMACAddress(MAC.toBytes())
- .setDestinationMACAddress(BCMAC.getAddress())
- .setPayload(arp);
+ .setVlanID(VLAN.toShort())
+ .setSourceMACAddress(MAC.toBytes())
+ .setDestinationMACAddress(BCMAC.getAddress())
+ .setPayload(arp);
return eth;
}
@@ -218,5 +220,10 @@
return INPORT;
}
+ @Override
+ public boolean isHandled() {
+ return false;
+ }
+
}
}
diff --git a/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java b/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
index ff9a996..8935d59 100644
--- a/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
+++ b/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
@@ -93,7 +93,7 @@
return;
}
if (ld.handleLLDP(pktCtx.unparsed(), pktCtx.inPort())) {
- pktCtx.blocked();
+ pktCtx.block();
}
}
diff --git a/providers/of/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java b/providers/of/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java
index eb41c18..40b40e4 100644
--- a/providers/of/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java
+++ b/providers/of/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java
@@ -87,7 +87,7 @@
pktCtx.parsed(), ByteBuffer.wrap(pktCtx.unparsed()));
OpenFlowCorePacketContext corePktCtx =
- new OpenFlowCorePacketContext(0, inPkt, null, false, pktCtx);
+ new OpenFlowCorePacketContext(0, inPkt, null, pktCtx.isHandled(), pktCtx);
providerService.processPacket(corePktCtx);
}