merged of -> openflow
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
index 7ee2b56..32bfcde 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
@@ -1,8 +1,14 @@
package org.onlab.onos.openflow.controller.impl;
+import static org.onlab.util.Tools.namedThreads;
+
import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -10,6 +16,7 @@
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.of.controller.OpenFlowEventListener;
import org.onlab.onos.openflow.controller.DefaultOpenFlowPacketContext;
import org.onlab.onos.openflow.controller.Dpid;
import org.onlab.onos.openflow.controller.OpenFlowController;
@@ -22,10 +29,12 @@
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPacketIn;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
+import org.projectfloodlight.openflow.protocol.OFType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
@Component(immediate = true)
@@ -35,6 +44,10 @@
private static final Logger log =
LoggerFactory.getLogger(OpenFlowControllerImpl.class);
+ private final ExecutorService executor = Executors.newFixedThreadPool(16,
+ namedThreads("of-event-dispatch-%d"));
+
+
protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
@@ -43,11 +56,12 @@
new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
- protected Set<OpenFlowSwitchListener> ofEventListener = new HashSet<>();
+ protected Set<OpenFlowSwitchListener> ofSwitchListener = new HashSet<>();
protected Multimap<Integer, PacketListener> ofPacketListener =
ArrayListMultimap.create();
+ protected Map<OFType, List<OpenFlowEventListener>> ofEventListener = Maps.newHashMap();
private final Controller ctrl = new Controller();
@@ -93,14 +107,14 @@
@Override
public void addListener(OpenFlowSwitchListener listener) {
- if (!ofEventListener.contains(listener)) {
- this.ofEventListener.add(listener);
+ if (!ofSwitchListener.contains(listener)) {
+ this.ofSwitchListener.add(listener);
}
}
@Override
public void removeListener(OpenFlowSwitchListener listener) {
- this.ofEventListener.remove(listener);
+ this.ofSwitchListener.remove(listener);
}
@Override
@@ -122,7 +136,7 @@
public void processPacket(Dpid dpid, OFMessage msg) {
switch (msg.getType()) {
case PORT_STATUS:
- for (OpenFlowSwitchListener l : ofEventListener) {
+ for (OpenFlowSwitchListener l : ofSwitchListener) {
l.portChanged(dpid, (OFPortStatus) msg);
}
break;
@@ -134,6 +148,12 @@
p.handlePacket(pktCtx);
}
break;
+ case FLOW_REMOVED:
+ case ERROR:
+ case STATS_REPLY:
+ case BARRIER_REPLY:
+ executor.submit(new OFMessageHandler(dpid, msg));
+ break;
default:
log.warn("Handling message type {} not yet implemented {}",
msg.getType(), msg);
@@ -164,7 +184,7 @@
} else {
log.error("Added switch {}", dpid);
connectedSwitches.put(dpid, sw);
- for (OpenFlowSwitchListener l : ofEventListener) {
+ for (OpenFlowSwitchListener l : ofSwitchListener) {
l.switchAdded(dpid);
}
return true;
@@ -277,7 +297,7 @@
if (sw == null) {
sw = activeEqualSwitches.remove(dpid);
}
- for (OpenFlowSwitchListener l : ofEventListener) {
+ for (OpenFlowSwitchListener l : ofSwitchListener) {
l.switchRemoved(dpid);
}
}
@@ -288,5 +308,26 @@
}
}
+ private final class OFMessageHandler implements Runnable {
+
+ private final OFMessage msg;
+ private final Dpid dpid;
+
+ public OFMessageHandler(Dpid dpid, OFMessage msg) {
+ this.msg = msg;
+ this.dpid = dpid;
+ }
+
+ @Override
+ public void run() {
+ List<OpenFlowEventListener> listeners =
+ ofEventListener.get(OFType.FLOW_REMOVED);
+ for (OpenFlowEventListener listener : listeners) {
+ listener.handleMessage(dpid, msg);
+ }
+ }
+
+ }
+
}
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
index 0c15d95..9a85d69 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -2,58 +2,29 @@
import static org.slf4j.LoggerFactory.getLogger;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.flow.DefaultFlowRule;
import org.onlab.onos.net.flow.FlowEntry;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.FlowRuleProvider;
import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
import org.onlab.onos.net.flow.FlowRuleProviderService;
-import org.onlab.onos.net.flow.criteria.Criteria.EthCriterion;
-import org.onlab.onos.net.flow.criteria.Criteria.EthTypeCriterion;
-import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion;
-import org.onlab.onos.net.flow.criteria.Criteria.IPProtocolCriterion;
-import org.onlab.onos.net.flow.criteria.Criteria.PortCriterion;
-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;
-import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
-import org.onlab.onos.net.flow.instructions.L3ModificationInstruction;
-import org.onlab.onos.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.TopologyService;
+import org.onlab.onos.of.controller.OpenFlowEventListener;
import org.onlab.onos.openflow.controller.Dpid;
import org.onlab.onos.openflow.controller.OpenFlowController;
import org.onlab.onos.openflow.controller.OpenFlowSwitch;
-import org.projectfloodlight.openflow.protocol.OFFactory;
-import org.projectfloodlight.openflow.protocol.OFFlowMod;
-import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
-import org.projectfloodlight.openflow.protocol.action.OFAction;
-import org.projectfloodlight.openflow.protocol.match.Match;
-import org.projectfloodlight.openflow.protocol.match.MatchField;
-import org.projectfloodlight.openflow.types.EthType;
-import org.projectfloodlight.openflow.types.IPv4Address;
-import org.projectfloodlight.openflow.types.IpProtocol;
-import org.projectfloodlight.openflow.types.MacAddress;
-import org.projectfloodlight.openflow.types.OFBufferId;
-import org.projectfloodlight.openflow.types.OFPort;
-import org.projectfloodlight.openflow.types.OFVlanVidMatch;
-import org.projectfloodlight.openflow.types.VlanPcp;
-import org.projectfloodlight.openflow.types.VlanVid;
+import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
+import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.slf4j.Logger;
/**
@@ -105,168 +76,10 @@
private void applyRule(FlowRule flowRule) {
OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
- Match match = buildMatch(flowRule.selector().criteria(), sw.factory());
- List<OFAction> actions =
- buildActions(flowRule.treatment().instructions(), sw.factory());
-
- //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
- OFFlowMod fm = sw.factory().buildFlowModify()
- .setBufferId(OFBufferId.NO_BUFFER)
- .setActions(actions)
- .setMatch(match)
- .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
- .setIdleTimeout(10)
- .setHardTimeout(10)
- .setPriority(flowRule.priority())
- .build();
- sw.sendMsg(fm);
+ sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowMod());
}
- private List<OFAction> buildActions(List<Instruction> instructions, OFFactory factory) {
- List<OFAction> acts = new LinkedList<>();
- for (Instruction i : instructions) {
- switch (i.type()) {
- case DROP:
- log.warn("Saw drop action; assigning drop action");
- return new LinkedList<>();
- case L2MODIFICATION:
- acts.add(buildL2Modification(i, factory));
- 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:
- log.warn("Instruction type {} not yet implemented.", i.type());
- }
- }
- return acts;
- }
-
- private OFAction buildL3Modification(Instruction i, OFFactory factory) {
- L3ModificationInstruction l3m = (L3ModificationInstruction) i;
- ModIPInstruction ip;
- switch (l3m.subtype()) {
- case L3_DST:
- ip = (ModIPInstruction) i;
- return factory.actions().setNwDst(IPv4Address.of(ip.ip().toInt()));
- case L3_SRC:
- ip = (ModIPInstruction) i;
- return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toInt()));
- default:
- log.warn("Unimplemented action type {}.", l3m.subtype());
- break;
- }
- return null;
- }
-
- private OFAction buildL2Modification(Instruction i, OFFactory factory) {
- L2ModificationInstruction l2m = (L2ModificationInstruction) i;
- ModEtherInstruction eth;
- switch (l2m.subtype()) {
- case L2_DST:
- eth = (ModEtherInstruction) l2m;
- return factory.actions().setDlDst(MacAddress.of(eth.mac().toLong()));
- case L2_SRC:
- eth = (ModEtherInstruction) l2m;
- return factory.actions().setDlSrc(MacAddress.of(eth.mac().toLong()));
- case VLAN_ID:
- ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
- return factory.actions().setVlanVid(VlanVid.ofVlan(vlanId.vlanId.toShort()));
- case VLAN_PCP:
- ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
- return factory.actions().setVlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
- default:
- log.warn("Unimplemented action type {}.", l2m.subtype());
- break;
- }
- return null;
- }
-
- private Match buildMatch(List<Criterion> criteria, OFFactory factory) {
- Match.Builder mBuilder = factory.buildMatch();
- EthCriterion eth;
- IPCriterion ip;
- for (Criterion c : criteria) {
- switch (c.type()) {
- case IN_PORT:
- PortCriterion inport = (PortCriterion) c;
- mBuilder.setExact(MatchField.IN_PORT, OFPort.of((int) inport.port().toLong()));
- break;
- case ETH_SRC:
- eth = (EthCriterion) c;
- mBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(eth.mac().toLong()));
- break;
- case ETH_DST:
- eth = (EthCriterion) c;
- mBuilder.setExact(MatchField.ETH_DST, MacAddress.of(eth.mac().toLong()));
- break;
- 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()));
- break;
- case IPV4_SRC:
- ip = (IPCriterion) c;
- mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toInt()));
- break;
- case IP_PROTO:
- IPProtocolCriterion p = (IPProtocolCriterion) c;
- mBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(p.protocol()));
- break;
- case VLAN_PCP:
- VlanPcpCriterion vpcp = (VlanPcpCriterion) c;
- mBuilder.setExact(MatchField.VLAN_PCP, VlanPcp.of(vpcp.priority()));
- break;
- case VLAN_VID:
- VlanIdCriterion vid = (VlanIdCriterion) c;
- mBuilder.setExact(MatchField.VLAN_VID,
- OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
- break;
- case ARP_OP:
- case ARP_SHA:
- case ARP_SPA:
- case ARP_THA:
- case ARP_TPA:
- case ICMPV4_CODE:
- case ICMPV4_TYPE:
- case ICMPV6_CODE:
- case ICMPV6_TYPE:
- case IN_PHY_PORT:
- case IPV6_DST:
- case IPV6_EXTHDR:
- case IPV6_FLABEL:
- case IPV6_ND_SLL:
- case IPV6_ND_TARGET:
- case IPV6_ND_TLL:
- case IPV6_SRC:
- case IP_DSCP:
- case IP_ECN:
- case METADATA:
- case MPLS_BOS:
- case MPLS_LABEL:
- case MPLS_TC:
- case PBB_ISID:
- case SCTP_DST:
- case SCTP_SRC:
- case TCP_DST:
- case TCP_SRC:
- case TUNNEL_ID:
- case UDP_DST:
- case UDP_SRC:
- default:
- log.warn("Action type {} not yet implemented.", c.type());
- }
- }
- return mBuilder.build();
- }
@Override
public void removeFlowRule(FlowRule... flowRules) {
@@ -283,6 +96,45 @@
//TODO: InternalFlowRuleProvider listening to stats and error and flowremoved.
// possibly barriers as well. May not be internal at all...
+ private class InternalFlowProvider
+ implements OpenFlowSwitchListener, OpenFlowEventListener {
+
+
+ @Override
+ public void switchAdded(Dpid dpid) {
+
+
+ }
+
+ @Override
+ public void switchRemoved(Dpid dpid) {
+
+
+ }
+
+ @Override
+ public void portChanged(Dpid dpid, OFPortStatus status) {
+ //TODO: Decide whether to evict flows internal store.
+ }
+
+ @Override
+ public void handleMessage(Dpid dpid, OFMessage msg) {
+ switch (msg.getType()) {
+ case FLOW_REMOVED:
+ OFFlowRemoved removed = (OFFlowRemoved) msg;
+ FlowRule fr = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)), null, null);
+ providerService.flowRemoved(fr);
+ break;
+ case STATS_REPLY:
+ case BARRIER_REPLY:
+ case ERROR:
+ default:
+ log.warn("Unhandled message type: {}", msg.getType());
+ }
+
+ }
+
+ }
}
diff --git a/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowCorePacketContext.java b/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowCorePacketContext.java
index ef26613..248e17d 100644
--- a/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowCorePacketContext.java
+++ b/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowCorePacketContext.java
@@ -46,7 +46,7 @@
private void sendBufferedPacket() {
List<Instruction> ins = treatmentBuilder().build().instructions();
OFPort p = null;
- //TODO: support arbitrary list of treatments
+ //TODO: support arbitrary list of treatments must be supported in ofPacketContext
for (Instruction i : ins) {
if (i.type() == Type.OUTPUT) {
p = buildPort(((OutputInstruction) i).port());
diff --git a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
index 109672c..1c2bc1b 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
@@ -118,7 +118,7 @@
if (mask > MAX_INET_MASK) {
throw new IllegalArgumentException(
"Value of subnet mask cannot exceed "
- + MAX_INET_MASK);
+ + MAX_INET_MASK);
}
}
@@ -200,7 +200,7 @@
byte [] net = new byte [4];
byte [] mask = bytes(mask());
for (int i = 0; i < INET_LEN; i++) {
- net[i] = (byte) (octets[i] & mask[i]);
+ net[i] = (byte) (octets[i] & mask[i]);
}
return new IpAddress(version, net, netmask);
}
@@ -221,11 +221,15 @@
byte [] host = new byte [INET_LEN];
byte [] mask = bytes(mask());
for (int i = 0; i < INET_LEN; i++) {
- host[i] = (byte) (octets[i] & ~mask[i]);
+ host[i] = (byte) (octets[i] & ~mask[i]);
}
return new IpAddress(version, host, netmask);
}
+ public boolean isMasked() {
+ return mask() != 0;
+ }
+
@Override
public int hashCode() {
final int prime = 31;