alshabib

flowrules are pushed: we still have an intermittent hang though

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.Host;
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.PacketContext;
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 @@ public class ReactiveForwarding {
@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 @@ public class ReactiveForwarding {
@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 @@ public class ReactiveForwarding {
// 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 @@ public class ReactiveForwarding {
}
// Otherwise forward and be done with it.
forward(context, path.src().port());
installRule(context, path.src().port());
}
}
......@@ -118,18 +134,43 @@ public class ReactiveForwarding {
// 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);
}
}
......
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;
}
}
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);
}
}
}
......@@ -9,12 +9,11 @@ import java.util.List;
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);
}
......
......@@ -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>
......
......@@ -32,7 +32,7 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext
@Override
public void send() {
if (blocked() && isBuilt) {
if (block() && isBuilt) {
sw.sendMsg(pktout);
}
}
......@@ -109,8 +109,13 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext
}
@Override
public boolean blocked() {
public boolean block() {
return free.getAndSet(false);
}
@Override
public boolean isHandled() {
return !free.get();
}
}
......
......@@ -16,7 +16,13 @@ public interface OpenFlowPacketContext {
* 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
......
......@@ -26,6 +26,7 @@ import org.onlab.onos.net.flow.criteria.Criteria.VlanIdCriterion;
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 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
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 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
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()));
......
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.onlab.packet.VlanId;
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 @@ public class OpenFlowHostProviderTest {
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 @@ public class OpenFlowHostProviderTest {
}
private class TestHostProviderService
extends AbstractProviderService<HostProvider>
implements HostProviderService {
extends AbstractProviderService<HostProvider>
implements HostProviderService {
Dpid added = null;
Dpid moved = null;
......@@ -150,7 +152,7 @@ public class OpenFlowHostProviderTest {
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 @@ public class OpenFlowHostProviderTest {
}
@Override
public boolean blocked() {
public boolean block() {
return false;
}
......@@ -189,16 +191,16 @@ public class OpenFlowHostProviderTest {
// 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 @@ public class OpenFlowHostProviderTest {
return INPORT;
}
@Override
public boolean isHandled() {
return false;
}
}
}
......
......@@ -93,7 +93,7 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid
return;
}
if (ld.handleLLDP(pktCtx.unparsed(), pktCtx.inPort())) {
pktCtx.blocked();
pktCtx.block();
}
}
......
......@@ -87,7 +87,7 @@ public class OpenFlowPacketProvider extends AbstractProvider implements PacketPr
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);
}
......