First set of changes to the Cpqd driver to remove hardcoding
and adding ECMP group support
Change-Id: Id34ecd3336ce702e7c151b486c4dd02a28ef1c76
diff --git a/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java b/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
index 0ee2904..5dbdb3e 100644
--- a/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
+++ b/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
@@ -30,6 +30,7 @@
import net.floodlightcontroller.debugevent.IDebugEventService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.threadpool.IThreadPoolService;
+import net.onrc.onos.core.configmanager.INetworkConfigService;
import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
import net.onrc.onos.core.registry.IControllerRegistryService;
@@ -83,6 +84,8 @@
context.getServiceImpl(IControllerRegistryService.class));
controller.setLinkDiscoveryService(
context.getServiceImpl(ILinkDiscoveryService.class));
+ controller.setNetworkConfigService(
+ context.getServiceImpl(INetworkConfigService.class));
controller.init(context.getConfigParams(this));
}
diff --git a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
index 5f73d9a..4447b75 100644
--- a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
+++ b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
@@ -23,6 +23,7 @@
import net.floodlightcontroller.core.internal.Controller.Counters;
import net.floodlightcontroller.core.module.IFloodlightService;
+import net.onrc.onos.core.configmanager.INetworkConfigService;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.util.OnosInstanceId;
@@ -186,6 +187,28 @@
public void removeOFSwitchListener(IOFSwitchListener listener);
+ Set<Long> getAllSwitchDpids();
+
+ IOFSwitch getSwitch(long dpid);
+
+ /**
+ * Record a switch event in in-memory debug-event
+ *
+ * @param switchDPID
+ * @param reason Reason for this event
+ * @param flushNow see debug-event flushing in IDebugEventService
+ */
+ public void addSwitchEvent(long switchDPID, String reason, boolean flushNow);
+
+ Set<Long> getAllMasterSwitchDpids();
+
+ Set<Long> getAllEqualSwitchDpids();
+
+ IOFSwitch getMasterSwitch(long dpid);
+
+ IOFSwitch getEqualSwitch(long dpid);
+
+ void setAlwaysClearFlowsOnSwActivate(boolean value);
//************************
// Utility methods
@@ -235,29 +258,12 @@
*/
public Counters getCounters();
- void setAlwaysClearFlowsOnSwActivate(boolean value);
+
Map<String, Long> getMemory();
Long getUptime();
- Set<Long> getAllSwitchDpids();
- IOFSwitch getSwitch(long dpid);
-
- /**
- * Record a switch event in in-memory debug-event
- * @param switchDPID
- * @param reason Reason for this event
- * @param flushNow see debug-event flushing in IDebugEventService
- */
- public void addSwitchEvent(long switchDPID, String reason, boolean flushNow);
-
- Set<Long> getAllMasterSwitchDpids();
-
- Set<Long> getAllEqualSwitchDpids();
-
- IOFSwitch getMasterSwitch(long dpid);
-
- IOFSwitch getEqualSwitch(long dpid);
+ public INetworkConfigService getNetworkConfigService();
}
diff --git a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
index 425c6a9..8ac2912 100644
--- a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
@@ -1,5 +1,6 @@
package net.floodlightcontroller.core;
+import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -22,17 +23,20 @@
* by a switch implementing this interface. It is up to the implementation
* to translate the 'matchActionOp' into a match-instruction with actions,
* as expected by OF 1.3 switches.
- *
+ *
* @param matchActionOp
+ * @throws IOException
*/
- public void pushFlow(MatchActionOperationEntry matchActionOp);
+ public void pushFlow(MatchActionOperationEntry matchActionOp) throws IOException;
/**
* Pushes a collection of flows to the switch.
- *
+ *
* @param matchActionOps
+ * @throws IOException
*/
- public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps);
+ public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
+ throws IOException;
// ****************************
// Group related
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
index 40aa530..72ec404 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
@@ -624,4 +624,9 @@
*/
public void setTableFull(boolean isFull);
+ /**
+ * Get the switch driver hanshake state
+ */
+ public String getSwitchDriverState();
+
}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 3550297..72c536f 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -68,6 +68,7 @@
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.threadpool.IThreadPoolService;
import net.floodlightcontroller.util.LoadMonitor;
+import net.onrc.onos.core.configmanager.INetworkConfigService;
import net.onrc.onos.core.drivermanager.DriverManager;
import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
import net.onrc.onos.core.packet.Ethernet;
@@ -136,6 +137,7 @@
protected IDebugEventService debugEvents;
protected ILinkDiscoveryService linkDiscovery;
+ protected INetworkConfigService networkConfig;
// Configuration options
protected int openFlowPort = 6633;
@@ -483,6 +485,10 @@
this.linkDiscovery = linkDiscovery;
}
+ public void setNetworkConfigService(INetworkConfigService networkConfigService) {
+ this.networkConfig = networkConfigService;
+ }
+
public void setDebugCounter(IDebugCounterService debugCounters) {
this.debugCounters = debugCounters;
}
@@ -993,6 +999,10 @@
}
}
+ public INetworkConfigService getNetworkConfigService() {
+ return networkConfig;
+ }
+
// **************
// Initialization
// **************
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
index d2e4156..b011e6b 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
@@ -1069,7 +1069,7 @@
* controller. Next State: depends on the role of this controller for
* this switch - either MASTER or EQUAL.
*/
- WAIT_SWITCH_DRIVER_SUB_HANDSHAKE(true) {
+ WAIT_SWITCH_DRIVER_SUB_HANDSHAKE(false) {
@Override
void processOFError(OFChannelHandler h, OFErrorMsg m)
@@ -1871,7 +1871,14 @@
void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
throws SwitchStateException, IOException {
- unhandledMessageReceived(h, m);
+ // A role reply message received by the default handler implies
+ // that the channel state-machine is in a state where it does not
+ // expect a role message. That in turn implies that role-request was
+ // sent out by this controller, as a result of a callback
+ // from the registry service, because the chosen master (some other
+ // instance) died, while this controller instance has not completed
+ // handshake yet. Best to disconnect switch and start over.
+ illegalMessageReceived(h, m);
}
void processOFGetAsyncReply(OFChannelHandler h,
@@ -1925,15 +1932,17 @@
* controller that wins mastership. Once the registry API changes to
* reply to every request, we would not need to wait for a timeout to
* move to Role.EQUAL (or SLAVE).
- *
+ *
* @param h the channel handler for this switch
* @param ctx the netty channel handler context for the channel 'h'
* @throws IOException
*/
public void handleTimedOutHandshake(OFChannelHandler h,
ChannelHandlerContext ctx) throws IOException {
- log.error("Disconnecting switch {}: failed to complete handshake",
- h.getSwitchInfoString());
+ log.error("Disconnecting switch {}: failed to complete handshake " +
+ "in state {} (with driverState: {})",
+ h.getSwitchInfoString(), h.getStateForTesting(),
+ h.sw.getSwitchDriverState());
h.counters.switchDisconnectHandshakeTimeout.updateCounterWithFlush();
ctx.getChannel().close();
}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java
index 3e6d7b2..254e658 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java
@@ -1286,4 +1286,9 @@
public Lock getListenerWriteLock() {
return listenerLock.writeLock();
}
+
+ public String getSwitchDriverState() {
+ return "";
+ }
+
}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
index 60cf0b1..961a913 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -36,7 +36,7 @@
import net.onrc.onos.core.matchaction.action.PopMplsAction;
import net.onrc.onos.core.matchaction.action.PushMplsAction;
import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
-import net.onrc.onos.core.matchaction.match.Ipv4PacketMatch;
+import net.onrc.onos.core.matchaction.match.Ipv4Match;
import net.onrc.onos.core.matchaction.match.Match;
import net.onrc.onos.core.matchaction.match.MplsMatch;
import net.onrc.onos.core.packet.ARP;
@@ -432,7 +432,7 @@
private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
List<String> fwdToSws) {
- Ipv4PacketMatch ipMatch = new Ipv4PacketMatch(subnetIp);
+ Ipv4Match ipMatch = new Ipv4Match(subnetIp);
List<Action> actions = new ArrayList<>();
// If destination SW is the same as the fwd SW, then do not push MPLS label
@@ -537,9 +537,9 @@
Match m = ma.getMatch();
List<Action> actions = ma.getActions();
- if (m instanceof Ipv4PacketMatch) {
+ if (m instanceof Ipv4Match) {
logStr.append("If the IP matches with ");
- IPv4Net ip = ((Ipv4PacketMatch) m).getDestination();
+ IPv4Net ip = ((Ipv4Match) m).getDestination();
logStr.append(ip.toString());
logStr.append(" then ");
}
diff --git a/src/main/java/net/onrc/onos/core/configmanager/NetworkConfigManager.java b/src/main/java/net/onrc/onos/core/configmanager/NetworkConfigManager.java
index b1d3836..d7c0ac4 100644
--- a/src/main/java/net/onrc/onos/core/configmanager/NetworkConfigManager.java
+++ b/src/main/java/net/onrc/onos/core/configmanager/NetworkConfigManager.java
@@ -46,13 +46,13 @@
* JSON Config file needs to use one of the following types for defining the
* kind of switch or link it wishes to configure.
*/
- private static final String SEGMENT_ROUTER = "Router_SR";
- private static final String ROADM = "Roadm";
- private static final String OF10SWITCH = "Switch_OF10";
+ public static final String SEGMENT_ROUTER = "Router_SR";
+ public static final String ROADM = "Roadm";
+ public static final String OF10SWITCH = "Switch_OF10";
- private static final String PKT_LINK = "pktLink";
- private static final String WDM_LINK = "wdmLink";
- private static final String PKT_OPT_LINK = "pktOptLink";
+ public static final String PKT_LINK = "pktLink";
+ public static final String WDM_LINK = "wdmLink";
+ public static final String PKT_OPT_LINK = "pktOptLink";
NetworkConfig networkConfig;
private ConcurrentMap<Long, SwitchConfig> configuredSwitches;
diff --git a/src/main/java/net/onrc/onos/core/configmanager/PktLinkConfig.java b/src/main/java/net/onrc/onos/core/configmanager/PktLinkConfig.java
index f205686..e205e77 100644
--- a/src/main/java/net/onrc/onos/core/configmanager/PktLinkConfig.java
+++ b/src/main/java/net/onrc/onos/core/configmanager/PktLinkConfig.java
@@ -132,6 +132,7 @@
private void validateParams() {
// TODO - wrong-names, duplicate links,
// duplicate use of port, is switch-allowed for which link is allowed?
+ // valid port numbers
}
public static class PktLinkParamsNotSpecified extends RuntimeException {
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
index 2e80c3b..d722da8 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
@@ -2,16 +2,51 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+import net.floodlightcontroller.core.IOF13Switch;
+import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted;
import net.floodlightcontroller.core.internal.OFSwitchImplBase;
+import net.onrc.onos.core.configmanager.INetworkConfigService;
+import net.onrc.onos.core.configmanager.INetworkConfigService.NetworkConfigState;
+import net.onrc.onos.core.configmanager.INetworkConfigService.SwitchConfigStatus;
+import net.onrc.onos.core.configmanager.NetworkConfig.LinkConfig;
+import net.onrc.onos.core.configmanager.NetworkConfigManager;
+import net.onrc.onos.core.configmanager.PktLinkConfig;
+import net.onrc.onos.core.configmanager.SegmentRouterConfig;
+import net.onrc.onos.core.matchaction.MatchAction;
+import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
+import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
+import net.onrc.onos.core.matchaction.action.Action;
+import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
+import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
+import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
+import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
+import net.onrc.onos.core.matchaction.action.GroupAction;
+import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
+import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.matchaction.action.PopMplsAction;
+import net.onrc.onos.core.matchaction.action.PushMplsAction;
+import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
+import net.onrc.onos.core.matchaction.match.Ipv4Match;
+import net.onrc.onos.core.matchaction.match.Match;
+import net.onrc.onos.core.matchaction.match.MplsMatch;
+import net.onrc.onos.core.matchaction.match.PacketMatch;
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.IPv4Net;
+import net.onrc.onos.core.util.PortNumber;
import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
@@ -48,15 +83,18 @@
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.util.HexString;
+import com.google.common.collect.Sets;
+
/**
* OFDescriptionStatistics Vendor (Manufacturer Desc.): Stanford University,
* Ericsson Research and CPqD Research. Make (Hardware Desc.) : OpenFlow 1.3
* Reference Userspace Switch Model (Datapath Desc.) : None Software : Serial :
* None
*/
-public class OFSwitchImplCPqD13 extends OFSwitchImplBase {
+public class OFSwitchImplCPqD13 extends OFSwitchImplBase implements IOF13Switch {
private static final int VLAN_ID_OFFSET = 16;
private AtomicBoolean driverHandshakeComplete;
+ private AtomicBoolean haltStateMachine;
private OFFactory factory;
private static final int OFPCML_NO_BUFFER = 0xffff;
// Configuration of asynch messages to controller. We need different
@@ -73,7 +111,6 @@
private static final long TEST_FLOW_REMOVED_MASK = 0xf;
private static final long TEST_PACKET_IN_MASK = 0x7;
private static final long TEST_PORT_STATUS_MASK = 0x7;
- private long barrierXidToWaitFor = -1;
private static final int TABLE_VLAN = 0;
private static final int TABLE_TMAC = 1;
@@ -83,25 +120,38 @@
private static final int TABLE_ACL = 5;
private static final short MAX_PRIORITY = (short) 0xffff;
- private static final short SLASH_24_PRIORITY = (short) 0xfff0;
- private static final short SLASH_16_PRIORITY = (short) 0xff00;
- private static final short SLASH_8_PRIORITY = (short) 0xf000;
+ private static final short PRIORITY_MULTIPLIER = (short) 2046;
private static final short MIN_PRIORITY = 0x0;
private static final U64 METADATA_MASK = U64.of(Long.MAX_VALUE << 1 | 0x1);
ConcurrentHashMap<Integer, OFGroup> l2groups;
+ private long barrierXidToWaitFor = -1;
+ private DriverState driverState;
private final boolean usePipeline13;
+ private SegmentRouterConfig srConfig;
+ private ConcurrentMap<Dpid, Set<PortNumber>> neighbors;
+ private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
+
+
public OFSwitchImplCPqD13(OFDescStatsReply desc, boolean usePipeline13) {
super();
+ haltStateMachine = new AtomicBoolean(false);
+ driverState = DriverState.INIT;
driverHandshakeComplete = new AtomicBoolean(false);
l2groups = new ConcurrentHashMap<Integer, OFGroup>();
setSwitchDescription(desc);
-
+ neighbors = new ConcurrentHashMap<Dpid, Set<PortNumber>>();
+ ecmpGroups = new ConcurrentHashMap<NeighborSet, EcmpInfo>();
this.usePipeline13 = usePipeline13;
}
+ // *****************************
+ // OFSwitchImplBase
+ // *****************************
+
+
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@@ -123,10 +173,10 @@
if (!usePipeline13) {
// Send packet-in to controller if a packet misses the first table
populateTableMissEntry(0, true, false, false, 0);
+ driverHandshakeComplete.set(true);
} else {
- configureSwitch();
+ nextDriverState();
}
- sendBarrier(true);
}
@@ -141,64 +191,759 @@
public void processDriverHandshakeMessage(OFMessage m) {
if (!startDriverHandshakeCalled)
throw new SwitchDriverSubHandshakeNotStarted();
- if (driverHandshakeComplete.get())
+ if (isDriverHandshakeComplete())
throw new SwitchDriverSubHandshakeCompleted(m);
+ try {
+ processOFMessage(this, m);
+ } catch (IOException e) {
+ log.error("Error generated when processing OFMessage", e.getCause());
+ }
+ }
+ @Override
+ public String getSwitchDriverState() {
+ return driverState.toString();
+ }
+
+ // *****************************
+ // Driver handshake state-machine
+ // *****************************
+
+ enum DriverState {
+ INIT,
+ SET_TABLE_MISS_ENTRIES,
+ SET_TABLE_VLAN_TMAC,
+ SET_GROUPS,
+ VERIFY_GROUPS,
+ SET_ADJACENCY_LABELS,
+ EXIT
+ }
+
+ protected void nextDriverState() throws IOException {
+ DriverState currentState = driverState;
+ if (haltStateMachine.get())
+ return;
+ switch (currentState) {
+ case INIT:
+ driverState = DriverState.SET_TABLE_MISS_ENTRIES;
+ setTableMissEntries();
+ sendBarrier();
+ break;
+ case SET_TABLE_MISS_ENTRIES:
+ driverState = DriverState.SET_TABLE_VLAN_TMAC;
+ getNetworkConfig();
+ populateTableVlan();
+ populateTableTMac();
+ sendBarrier();
+ break;
+ case SET_TABLE_VLAN_TMAC:
+ driverState = DriverState.SET_GROUPS;
+ createGroups();
+ sendBarrier();
+ break;
+ case SET_GROUPS:
+ driverState = DriverState.VERIFY_GROUPS;
+ verifyGroups();
+ break;
+ case VERIFY_GROUPS:
+ driverState = DriverState.SET_ADJACENCY_LABELS;
+ assignAdjacencyLabels();
+ break;
+ case SET_ADJACENCY_LABELS:
+ driverState = DriverState.EXIT;
+ driverHandshakeComplete.set(true);
+ break;
+ case EXIT:
+ default:
+ driverState = DriverState.EXIT;
+ log.error("Driver handshake has exited for sw: {}", getStringId());
+ }
+ }
+
+ void processOFMessage(IOFSwitch sw, OFMessage m) throws IOException {
switch (m.getType()) {
case BARRIER_REPLY:
- if (m.getXid() == barrierXidToWaitFor)
- driverHandshakeComplete.set(true);
+ processBarrierReply(m);
break;
case ERROR:
- log.error("Switch {} Error {}", getStringId(), (OFErrorMsg) m);
+ processErrorMessage(m);
break;
- case FEATURES_REPLY:
- break;
- case FLOW_REMOVED:
- break;
case GET_ASYNC_REPLY:
OFAsyncGetReply asrep = (OFAsyncGetReply) m;
decodeAsyncGetReply(asrep);
break;
case PACKET_IN:
+ // not ready to handle packet-ins
break;
- case PORT_STATUS:
- break;
+
case QUEUE_GET_CONFIG_REPLY:
- break;
- case ROLE_REPLY:
+ // not doing queue config yet
break;
case STATS_REPLY:
processStatsReply((OFStatsReply) m);
break;
+ case ROLE_REPLY: // channelHandler should handle this
+ case PORT_STATUS: // channelHandler should handle this
+ case FEATURES_REPLY: // don't care
+ case FLOW_REMOVED: // don't care
default:
log.debug("Received message {} during switch-driver subhandshake "
- + "from switch {} ... Ignoring message", m, getStringId());
+ + "from switch {} ... Ignoring message", m, sw.getStringId());
+ }
+ }
+
+ private void processStatsReply(OFStatsReply sr) {
+ switch (sr.getStatsType()) {
+ case AGGREGATE:
+ break;
+ case DESC:
+ break;
+ case EXPERIMENTER:
+ break;
+ case FLOW:
+ break;
+ case GROUP_DESC:
+ processGroupDesc((OFGroupDescStatsReply) sr);
+ break;
+ case GROUP_FEATURES:
+ processGroupFeatures((OFGroupFeaturesStatsReply) sr);
+ break;
+ case METER_CONFIG:
+ break;
+ case METER_FEATURES:
+ break;
+ case PORT_DESC:
+ break;
+ case TABLE_FEATURES:
+ break;
+ default:
+ break;
}
}
+ private void processErrorMessage(OFMessage m) {
+ log.error("Switch {} Error {} in DriverState", getStringId(),
+ (OFErrorMsg) m, driverState);
+ }
+
+ private void processBarrierReply(OFMessage m) throws IOException {
+ if (m.getXid() == barrierXidToWaitFor) {
+ // Driver state-machine progresses to the next state.
+ // If Barrier messages is not received, then eventually
+ // the ChannelHandler state machine will timeout, and the switch
+ // will be disconnected.
+ nextDriverState();
+ } else {
+ log.error("Received incorrect barrier-message xid {} (expected: {}) in "
+ + "switch-driver state {} for switch {}", m, barrierXidToWaitFor,
+ driverState, getStringId());
+ }
+ }
+
+ private void processGroupDesc(OFGroupDescStatsReply gdsr) {
+ log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
+ try {
+ nextDriverState();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ // *****************************
+ // Utility methods
+ // *****************************
+
+ void setTableMissEntries() throws IOException {
+ // set all table-miss-entries
+ populateTableMissEntry(TABLE_VLAN, true, false, false, -1);
+ populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
+ populateTableMissEntry(TABLE_IPv4_UNICAST, false, true, true,
+ TABLE_ACL);
+ populateTableMissEntry(TABLE_MPLS, false, true, true,
+ TABLE_ACL);
+ populateTableMissEntry(TABLE_ACL, false, false, false, -1);
+ }
+
+ private void sendBarrier() throws IOException {
+ long xid = getNextTransactionId();
+ barrierXidToWaitFor = xid;
+ OFBarrierRequest br = getFactory()
+ .buildBarrierRequest()
+ .setXid(xid)
+ .build();
+ write(br, null);
+ }
+
+ /**
+ * Adds a table-miss-entry to a pipeline table.
+ * <p>
+ * The table-miss-entry can be added with 'write-actions' or
+ * 'apply-actions'. It can also add a 'goto-table' instruction. By default
+ * if none of the booleans in the call are set, then the table-miss entry is
+ * added with no instructions, which means that if a packet hits the
+ * table-miss-entry, pipeline execution will stop, and the action set
+ * associated with the packet will be executed.
+ *
+ * @param tableToAdd the table to where the table-miss-entry will be added
+ * @param toControllerNow as an APPLY_ACTION instruction
+ * @param toControllerWrite as a WRITE_ACTION instruction
+ * @param toTable as a GOTO_TABLE instruction
+ * @param tableToSend the table to send as per the GOTO_TABLE instruction it
+ * needs to be set if 'toTable' is true. Ignored of 'toTable' is
+ * false.
+ * @throws IOException
+ */
+ @SuppressWarnings("unchecked")
+ private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
+ boolean toControllerWrite,
+ boolean toTable, int tableToSend) throws IOException {
+ OFOxmList oxmList = OFOxmList.EMPTY;
+ OFMatchV3 match = factory.buildMatchV3()
+ .setOxmList(oxmList)
+ .build();
+ OFAction outc = factory.actions()
+ .buildOutput()
+ .setPort(OFPort.CONTROLLER)
+ .setMaxLen(OFPCML_NO_BUFFER)
+ .build();
+ List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+ if (toControllerNow) {
+ // table-miss instruction to send to controller immediately
+ OFInstruction instr = factory.instructions()
+ .buildApplyActions()
+ .setActions(Collections.singletonList(outc))
+ .build();
+ instructions.add(instr);
+ }
+
+ if (toControllerWrite) {
+ // table-miss instruction to write-action to send to controller
+ // this will be executed whenever the action-set gets executed
+ OFInstruction instr = factory.instructions()
+ .buildWriteActions()
+ .setActions(Collections.singletonList(outc))
+ .build();
+ instructions.add(instr);
+ }
+
+ if (toTable) {
+ // table-miss instruction to goto-table x
+ OFInstruction instr = factory.instructions()
+ .gotoTable(TableId.of(tableToSend));
+ instructions.add(instr);
+ }
+
+ if (!toControllerNow && !toControllerWrite && !toTable) {
+ // table-miss has no instruction - at which point action-set will be
+ // executed - if there is an action to output/group in the action
+ // set
+ // the packet will be sent there, otherwise it will be dropped.
+ instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
+ }
+
+ OFMessage tableMissEntry = factory.buildFlowAdd()
+ .setTableId(TableId.of(tableToAdd))
+ .setMatch(match) // match everything
+ .setInstructions(instructions)
+ .setPriority(MIN_PRIORITY)
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setIdleTimeout(0)
+ .setHardTimeout(0)
+ .setXid(getNextTransactionId())
+ .build();
+ write(tableMissEntry, null);
+ }
+
+ private void getNetworkConfig() {
+ INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
+ SwitchConfigStatus scs = ncs.checkSwitchConfig(new Dpid(getId()));
+ if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
+ srConfig = (SegmentRouterConfig) scs.getSwitchConfig();
+ } else {
+ log.error("Switch not configured as Segment-Router");
+ }
+
+ List<LinkConfig> linkConfigList = ncs.getConfiguredAllowedLinks();
+ setNeighbors(linkConfigList);
+ }
+
+ private void populateTableVlan() throws IOException {
+ List<OFMessage> msglist = new ArrayList<OFMessage>();
+ for (OFPortDesc p : getPorts()) {
+ int pnum = p.getPortNo().getPortNumber();
+ if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
+ OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
+ OFOxmVlanVid oxv = factory.oxms()
+ .vlanVid(OFVlanVidMatch.UNTAGGED);
+ OFOxmList oxmList = OFOxmList.of(oxp, oxv);
+ OFMatchV3 match = factory.buildMatchV3()
+ .setOxmList(oxmList).build();
+
+ // TODO: match on vlan-tagged packets for vlans configured on
+ // subnet ports and strip-vlan
+
+ // Do not need to add vlans
+ /*int vlanid = getVlanConfig(pnum);
+ OFOxmVlanVid vidToSet = factory.oxms()
+ .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
+ OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
+ OFAction setVlan = factory.actions().setField(vidToSet);
+ List<OFAction> actionlist = new ArrayList<OFAction>();
+ actionlist.add(pushVlan);
+ actionlist.add(setVlan);
+ OFInstruction appAction = factory.instructions().buildApplyActions()
+ .setActions(actionlist).build();*/
+
+ OFInstruction gotoTbl = factory.instructions().buildGotoTable()
+ .setTableId(TableId.of(TABLE_TMAC)).build();
+ List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+ // instructions.add(appAction);
+ instructions.add(gotoTbl);
+ OFMessage flowEntry = factory.buildFlowAdd()
+ .setTableId(TableId.of(TABLE_VLAN))
+ .setMatch(match)
+ .setInstructions(instructions)
+ .setPriority(1000) // does not matter - all rules
+ // exclusive
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setIdleTimeout(0)
+ .setHardTimeout(0)
+ .setXid(getNextTransactionId())
+ .build();
+ msglist.add(flowEntry);
+ }
+ }
+ write(msglist);
+ log.debug("Adding {} port/vlan-rules in sw {}", msglist.size(), getStringId());
+ }
+
+ private void populateTableTMac() throws IOException {
+ // match for router-mac and ip-packets
+ OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
+ OFOxmEthDst dmac = factory.oxms().ethDst(getRouterMacAddr());
+ OFOxmList oxmListIp = OFOxmList.of(dmac, oxe);
+ OFMatchV3 matchIp = factory.buildMatchV3()
+ .setOxmList(oxmListIp).build();
+ OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
+ .setTableId(TableId.of(TABLE_IPv4_UNICAST)).build();
+ List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
+ OFMessage ipEntry = factory.buildFlowAdd()
+ .setTableId(TableId.of(TABLE_TMAC))
+ .setMatch(matchIp)
+ .setInstructions(instructionsIp)
+ .setPriority(1000) // strict priority required lower than
+ // multicastMac
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setIdleTimeout(0)
+ .setHardTimeout(0)
+ .setXid(getNextTransactionId())
+ .build();
+
+ // match for router-mac and mpls packets
+ OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
+ OFOxmList oxmListMpls = OFOxmList.of(dmac, oxmpls);
+ OFMatchV3 matchMpls = factory.buildMatchV3()
+ .setOxmList(oxmListMpls).build();
+ OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
+ .setTableId(TableId.of(TABLE_MPLS)).build();
+ List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
+ OFMessage mplsEntry = factory.buildFlowAdd()
+ .setTableId(TableId.of(TABLE_TMAC))
+ .setMatch(matchMpls)
+ .setInstructions(instructionsMpls)
+ .setPriority(1001) // strict priority required lower than
+ // multicastMac
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setIdleTimeout(0)
+ .setHardTimeout(0)
+ .setXid(getNextTransactionId())
+ .build();
+
+ log.debug("Adding termination-mac-rules in sw {}", getStringId());
+ List<OFMessage> msglist = new ArrayList<OFMessage>(2);
+ msglist.add(ipEntry);
+ msglist.add(mplsEntry);
+ write(msglist);
+ }
+
+ private MacAddress getRouterMacAddr() {
+ if (srConfig != null) {
+ return MacAddress.of(srConfig.getRouterMac());
+ } else {
+ // return a dummy mac address - it will not be used
+ return MacAddress.of("00:00:00:00:00:00");
+ }
+ }
+
+ private MacAddress getNeighborRouterMacAddress(Dpid ndpid) {
+ INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
+ SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
+ if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
+ return MacAddress.of(((SegmentRouterConfig) scs.getSwitchConfig())
+ .getRouterMac());
+ } else {
+ // return a dummy mac address - it will not be used
+ return MacAddress.of("00:00:00:00:00:00");
+ }
+ }
+
+ private void setNeighbors(List<LinkConfig> linkConfigList) {
+ List<PortNumber> portlist = new ArrayList<PortNumber>();
+ for (LinkConfig lg : linkConfigList) {
+ if (!lg.getType().equals(NetworkConfigManager.PKT_LINK)) {
+ return;
+ }
+ PktLinkConfig plg = (PktLinkConfig) lg;
+ if (plg.getDpid1() == getId()) {
+ addNeighborAtPort(new Dpid(plg.getDpid2()),
+ PortNumber.uint32(plg.getPort1()));
+ } else if (plg.getDpid2() == getId()) {
+ addNeighborAtPort(new Dpid(plg.getDpid1()),
+ PortNumber.uint32(plg.getPort2()));
+ }
+ }
+ }
+
+ private void addNeighborAtPort(Dpid neighborDpid, PortNumber portToNeighbor) {
+ if (neighbors.get(neighborDpid) != null) {
+ neighbors.get(neighborDpid).add(portToNeighbor);
+ } else {
+ Set<PortNumber> ports = new HashSet<PortNumber>();
+ ports.add(portToNeighbor);
+ neighbors.put(neighborDpid, ports);
+ }
+ }
+
+ /**
+ * createGroups creates ECMP groups for all ports on this router connected
+ * to other routers (in the OF network). The information for ports is
+ * gleaned from the configured links. If no links are configured no groups
+ * will be created, and it is up to the caller of the IOF13Switch API to
+ * create groups.
+ * <p>
+ * By default all ports connected to the same neighbor router will be part
+ * of the same ECMP group. In addition, groups will be created for all
+ * possible combinations of neighbor routers.
+ * <p>
+ * For example, consider this router (R0) connected to 3 neighbors (R1, R2,
+ * and R3). The following groups will be created in R0:
+ * <li>1) all ports to R1,
+ * <li>2) all ports to R2,
+ * <li>3) all ports to R3,
+ * <li>4) all ports to R1 and R2
+ * <li>5) all ports to R1 and R3
+ * <li>6) all ports to R2 and R3
+ * <li>7) all ports to R1, R2, and R3
+ */
+ private void createGroups() {
+ Set<Dpid> dpids = neighbors.keySet();
+ if (dpids == null || dpids.isEmpty()) {
+ return;
+ }
+ // temp map of ecmp groupings
+ /* Map<NeighborSet, List<BucketInfo>> temp =
+ new HashMap<NeighborSet, List<BucketInfo>>();
+ */
+ // get all combinations of neighbors
+ Set<Set<Dpid>> powerSet = Sets.powerSet(dpids);
+ int groupid = 1;
+ for (Set<Dpid> combo : powerSet) {
+ if (combo.isEmpty()) {
+ // eliminate the empty set in the power set
+ continue;
+ }
+ List<BucketInfo> buckets = new ArrayList<BucketInfo>();
+ NeighborSet ns = new NeighborSet();
+ for (Dpid d : combo) {
+ ns.addDpid(d);
+ for (PortNumber sp : neighbors.get(d)) {
+ BucketInfo b = new BucketInfo(d,
+ MacAddress.of(srConfig.getRouterMac()),
+ getNeighborRouterMacAddress(d), sp);
+ buckets.add(b);
+ }
+ }
+ EcmpInfo ecmpInfo = new EcmpInfo(groupid++, buckets);
+ setEcmpGroup(ecmpInfo);
+ ecmpGroups.put(ns, ecmpInfo);
+ log.debug("Creating ecmp group in sw {}: {}", getStringId(), ecmpInfo);
+ }
+ }
+
+ private class EcmpInfo {
+ int groupId;
+ List<BucketInfo> buckets;
+
+ EcmpInfo(int gid, List<BucketInfo> bucketInfos) {
+ groupId = gid;
+ buckets = bucketInfos;
+ }
+
+ @Override
+ public String toString() {
+ return "groupId: " + groupId + ", buckets: " + buckets;
+ }
+ }
+
+ private class BucketInfo {
+ Dpid neighborDpid;
+ MacAddress srcMac;
+ MacAddress dstMac;
+ PortNumber outport;
+
+ BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac, PortNumber p) {
+ neighborDpid = nDpid;
+ srcMac = smac;
+ dstMac = dmac;
+ outport = p;
+ }
+
+ @Override
+ public String toString() {
+ return " {neighborDpid: " + neighborDpid + ", dstMac: " + dstMac +
+ ", srcMac: " + srcMac + ", outport: " + outport + "}";
+ }
+ }
+
+ private void setEcmpGroup(EcmpInfo ecmpInfo) {
+ List<OFMessage> msglist = new ArrayList<OFMessage>();
+ OFGroup group = OFGroup.of(ecmpInfo.groupId);
+
+ List<OFBucket> buckets = new ArrayList<OFBucket>();
+ for (BucketInfo b : ecmpInfo.buckets) {
+ OFOxmEthDst dmac = factory.oxms()
+ .ethDst(b.dstMac);
+ OFAction setDA = factory.actions().buildSetField()
+ .setField(dmac).build();
+ OFOxmEthDst smac = factory.oxms()
+ .ethDst(b.srcMac);
+ OFAction setSA = factory.actions().buildSetField()
+ .setField(smac).build();
+ OFAction outp = factory.actions().buildOutput()
+ .setPort(OFPort.of(b.outport.shortValue()))
+ .build();
+ List<OFAction> actions = new ArrayList<OFAction>();
+ actions.add(setSA);
+ actions.add(setDA);
+ actions.add(outp);
+ OFBucket ofb = factory.buildBucket()
+ .setWeight(1)
+ .setActions(actions)
+ .build();
+ buckets.add(ofb);
+ }
+
+ OFMessage gm = factory.buildGroupAdd()
+ .setGroup(group)
+ .setBuckets(buckets)
+ .setGroupType(OFGroupType.SELECT)
+ .setXid(getNextTransactionId())
+ .build();
+ msglist.add(gm);
+ try {
+ write(msglist);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void verifyGroups() throws IOException {
+ sendGroupDescRequest();
+ }
+
+ private void sendGroupDescRequest() throws IOException {
+ OFMessage gdr = factory.buildGroupDescStatsRequest()
+ .setXid(getNextTransactionId())
+ .build();
+ write(gdr, null);
+ }
+
+ private void assignAdjacencyLabels() {
+ // TODO
+ try {
+ nextDriverState();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void pushIpEntry(MatchActionOperationEntry mao) throws IOException {
+ MatchAction ma = mao.getTarget();
+ Operator op = mao.getOperator();
+ Ipv4Match ipm = (Ipv4Match) ma.getMatch();
+
+ // set match
+ IPv4Net ipdst = ipm.getDestination();
+ OFOxmEthType ethTypeIp = factory.oxms()
+ .ethType(EthType.IPv4);
+ OFOxmIpv4DstMasked ipPrefix = factory.oxms()
+ .ipv4DstMasked(
+ IPv4Address.of(ipdst.address().value()),
+ IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
+ );
+ OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
+ OFMatchV3 match = factory.buildMatchV3()
+ .setOxmList(oxmList).build();
+
+ // set actions
+ List<OFAction> writeActions = new ArrayList<OFAction>();
+ for (Action action : ma.getActions()) {
+ OFAction ofAction = null;
+ if (action instanceof OutputAction) {
+ OutputAction outputAction = (OutputAction) action;
+ OFPort port = OFPort.of((int) outputAction.getPortNumber().value());
+ ofAction = factory.actions().output(port, Short.MAX_VALUE);
+ } else if (action instanceof ModifyDstMacAction) {
+ long dstMac = ((ModifyDstMacAction) action).getDstMac().toLong();
+ OFOxmEthDst dmac = factory.oxms()
+ .ethDst(MacAddress.of(dstMac));
+ ofAction = factory.actions().buildSetField()
+ .setField(dmac).build();
+ } else if (action instanceof ModifySrcMacAction) {
+ long srcMac = ((ModifySrcMacAction) action).getSrcMac().toLong();
+ OFOxmEthSrc smac = factory.oxms()
+ .ethSrc(MacAddress.of(srcMac));
+ ofAction = factory.actions().buildSetField()
+ .setField(smac).build();
+ } else if (action instanceof PushMplsAction) {
+ ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
+ } else if (action instanceof SetMplsIdAction) {
+ int labelid = ((SetMplsIdAction) action).getMplsId();
+ OFOxmMplsLabel lid = factory.oxms()
+ .mplsLabel(U32.of(labelid));
+ ofAction = factory.actions().buildSetField()
+ .setField(lid).build();
+ } else if (action instanceof PopMplsAction) {
+
+ } else if (action instanceof GroupAction) {
+ ofAction = factory.actions().buildGroup()
+ .setGroup(OFGroup.of(0)) // TODO fail
+ .build();
+ } else if (action instanceof DecNwTtlAction) {
+
+ } else if (action instanceof DecMplsTtlAction) {
+
+ } else if (action instanceof CopyTtlInAction) {
+
+ } else if (action instanceof CopyTtlOutAction) {
+ ofAction = factory.actions().copyTtlOut();
+ } else {
+ log.warn("Unsupported Action type: {}", action.getClass().getName());
+ continue;
+ }
+ writeActions.add(ofAction);
+ }
+
+ // OFAction setBos =
+ // factory.actions().buildSetField().setField(bos).build();
+
+ // set instructions
+ OFInstruction writeInstr = factory.instructions().buildWriteActions()
+ .setActions(writeActions).build();
+ OFInstruction gotoInstr = factory.instructions().buildGotoTable()
+ .setTableId(TableId.of(TABLE_ACL)).build();
+ List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+ instructions.add(writeInstr);
+ instructions.add(gotoInstr);
+
+ // set flow priority
+ int priority = ipdst.prefixLen() * PRIORITY_MULTIPLIER;
+ if (ipdst.prefixLen() == (short) 32) {
+ priority = MAX_PRIORITY;
+ }
+
+ // set flow-mod XXX - This is only ADD (not doing DELETE yet)
+ OFMessage ipFlow = factory.buildFlowAdd()
+ .setTableId(TableId.of(TABLE_IPv4_UNICAST))
+ .setMatch(match)
+ .setInstructions(instructions)
+ .setPriority(priority)
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setIdleTimeout(0)
+ .setHardTimeout(0)
+ .setXid(getNextTransactionId())
+ .build();
+
+ write(ipFlow, null);
+ log.debug("Adding ip-rule {}-{} in sw {}", match, writeActions,
+ getStringId());
+ }
+
+ private void pushMplsEntry(MatchActionOperationEntry mao) {
+
+ }
+
+ private void pushAclEntry(MatchActionOperationEntry mao) {
+
+ }
+
+ // *****************************
+ // IOF13Switch
+ // *****************************
+
+ @Override
+ public void pushFlow(MatchActionOperationEntry matchActionOp) throws IOException {
+ final MatchAction matchAction = matchActionOp.getTarget();
+ final Match match = matchAction.getMatch();
+ if (match instanceof Ipv4Match) {
+ pushIpEntry(matchActionOp);
+ } else if (match instanceof MplsMatch) {
+ pushMplsEntry(matchActionOp);
+ } else if (match instanceof PacketMatch) {
+ pushAclEntry(matchActionOp);
+ } else {
+ log.error("Unknown match type {} pushed to switch {}", match,
+ getStringId());
+ }
+ }
+
+ @Override
+ public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
+ throws IOException {
+ for (MatchActionOperationEntry matchActionOp : matchActionOps) {
+ pushFlow(matchActionOp);
+ }
+ }
+
+ @Override
+ public int getEcmpGroupId(NeighborSet ns) {
+ EcmpInfo ei = ecmpGroups.get(ns);
+ if (ei == null) {
+ return -1;
+ } else {
+ return ei.groupId;
+ }
+ }
+
+ // *****************************
+ // Old Hardcoded Stuff
+ // *****************************
+
private void configureSwitch() throws IOException {
// setAsyncConfig();
// getTableFeatures();
sendGroupFeaturesRequest();
setL2Groups();
- sendBarrier(false);
+ sendBarrier();
setL3Groups();
setL25Groups();
- setEcmpGroup();
+ // setEcmpGroup();
sendGroupDescRequest();
populateTableVlan();
populateTableTMac();
populateIpTable();
populateMplsTable();
populateTableMissEntry(TABLE_ACL, false, false, false, -1);
- sendBarrier(true);
+ sendBarrier();
}
private void setAsyncConfig() throws IOException {
@@ -271,12 +1016,6 @@
write(gfr, null);
}
- private void sendGroupDescRequest() throws IOException {
- OFMessage gdr = factory.buildGroupDescStatsRequest()
- .setXid(getNextTransactionId())
- .build();
- write(gdr, null);
- }
/*Create L2 interface groups for all physical ports
Naming convention followed is the same as OF-DPA spec
@@ -324,14 +1063,6 @@
return portVlan;
}
- private MacAddress getRouterMacAddr() {
- if (getId() == 0x3)
- return MacAddress.of("00:00:07:07:07:80"); // router mac
- if (getId() == 0x1)
- return MacAddress.of("00:00:01:01:01:80");
- // switch 0x2
- return MacAddress.of("00:00:02:02:02:80");
- }
// only for ports connected to other routers
private OFAction getDestAction(int portnum) {
@@ -469,181 +1200,12 @@
log.debug("Creating {} MPLS groups in sw {}", msglist.size(), getStringId());
}
- private void setEcmpGroup() throws IOException {
- if (getId() != 0x1)
- return;
- List<OFMessage> msglist = new ArrayList<OFMessage>();
- OFGroup group47 = OFGroup.of(47);
-
- OFAction outg1 = factory.actions().buildGroup()
- .setGroup(OFGroup.of(0xa0000000 | // mpls group id
- 6))
- .build();
- OFBucket buc47_1 = factory.buildBucket()
- .setWeight(1)
- .setActions(Collections.singletonList(outg1))
- .build();
-
- OFAction outg2 = factory.actions().buildGroup()
- .setGroup(OFGroup.of(0xa0000000 | // mpls group id
- 7))
- .build();
- OFBucket buc47_2 = factory.buildBucket()
- .setWeight(1)
- .setActions(Collections.singletonList(outg2))
- .build();
-
- List<OFBucket> buckets47 = new ArrayList<OFBucket>();
- buckets47.add(buc47_1);
- buckets47.add(buc47_2);
- OFMessage gmS12 = factory.buildGroupAdd()
- .setGroup(group47)
- .setBuckets(buckets47)
- .setGroupType(OFGroupType.SELECT)
- .setXid(getNextTransactionId())
- .build();
- msglist.add(gmS12);
- write(msglist);
- log.debug("Creating {} ECMP groups in sw {}", msglist.size(), getStringId());
- }
-
- private void processStatsReply(OFStatsReply sr) {
- switch (sr.getStatsType()) {
- case AGGREGATE:
- break;
- case DESC:
- break;
- case EXPERIMENTER:
- break;
- case FLOW:
- break;
- case GROUP_DESC:
- processGroupDesc((OFGroupDescStatsReply) sr);
- break;
- case GROUP_FEATURES:
- processGroupFeatures((OFGroupFeaturesStatsReply) sr);
- break;
- case METER_CONFIG:
- break;
- case METER_FEATURES:
- break;
- case PORT_DESC:
- break;
- case TABLE_FEATURES:
- break;
- default:
- break;
-
- }
- }
private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
log.info("Sw: {} Group Features {}", getStringId(), gfsr);
}
- private void processGroupDesc(OFGroupDescStatsReply gdsr) {
- log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
- }
- private void populateTableVlan() throws IOException {
- // for all incoming ports assign configured port-vlans
- // currently assign portnum*10 -> vlanid to access ports
- // and vlan 192 to router to router ports
- List<OFMessage> msglist = new ArrayList<OFMessage>();
- for (OFPortDesc p : getPorts()) {
- int pnum = p.getPortNo().getPortNumber();
- if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
- int vlanid = getVlanConfig(pnum);
- OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
- OFOxmVlanVid oxv = factory.oxms()
- .vlanVid(OFVlanVidMatch.UNTAGGED);
- OFOxmList oxmList = OFOxmList.of(oxp, oxv);
- OFMatchV3 match = factory.buildMatchV3()
- .setOxmList(oxmList).build();
- OFOxmVlanVid vidToSet = factory.oxms()
- .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
- OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
- OFAction setVlan = factory.actions().setField(vidToSet);
- List<OFAction> actionlist = new ArrayList<OFAction>();
- actionlist.add(pushVlan);
- actionlist.add(setVlan);
- OFInstruction appAction = factory.instructions().buildApplyActions()
- .setActions(actionlist).build();
- OFInstruction gotoTbl = factory.instructions().buildGotoTable()
- .setTableId(TableId.of(TABLE_TMAC)).build();
- List<OFInstruction> instructions = new ArrayList<OFInstruction>();
- // instructions.add(appAction);
- instructions.add(gotoTbl);
- OFMessage flowEntry = factory.buildFlowAdd()
- .setTableId(TableId.of(TABLE_VLAN))
- .setMatch(match)
- .setInstructions(instructions)
- .setPriority(1000) // does not matter - all rules
- // exclusive
- .setBufferId(OFBufferId.NO_BUFFER)
- .setIdleTimeout(0)
- .setHardTimeout(0)
- .setXid(getNextTransactionId())
- .build();
- msglist.add(flowEntry);
- }
- }
- // table-vlan has no table-miss entry, and so packets that miss are
- // essentially dropped
- write(msglist);
- log.debug("Adding {} vlan-rules in sw {}", msglist.size(), getStringId());
- }
-
- private void populateTableTMac() throws IOException {
- // match for ip packets
- OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
- OFOxmList oxmListIp = OFOxmList.of(oxe);
- OFMatchV3 matchIp = factory.buildMatchV3()
- .setOxmList(oxmListIp).build();
- OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
- .setTableId(TableId.of(TABLE_IPv4_UNICAST)).build();
- List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
- OFMessage ipEntry = factory.buildFlowAdd()
- .setTableId(TableId.of(TABLE_TMAC))
- .setMatch(matchIp)
- .setInstructions(instructionsIp)
- .setPriority(1000) // strict priority required lower than
- // multicastMac
- .setBufferId(OFBufferId.NO_BUFFER)
- .setIdleTimeout(0)
- .setHardTimeout(0)
- .setXid(getNextTransactionId())
- .build();
-
- // match for mpls packets
- OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
- OFOxmList oxmListMpls = OFOxmList.of(oxmpls);
- OFMatchV3 matchMpls = factory.buildMatchV3()
- .setOxmList(oxmListMpls).build();
- OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
- .setTableId(TableId.of(TABLE_MPLS)).build();
- List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
- OFMessage mplsEntry = factory.buildFlowAdd()
- .setTableId(TableId.of(TABLE_TMAC))
- .setMatch(matchMpls)
- .setInstructions(instructionsMpls)
- .setPriority(1001) // strict priority required lower than
- // multicastMac
- .setBufferId(OFBufferId.NO_BUFFER)
- .setIdleTimeout(0)
- .setHardTimeout(0)
- .setXid(getNextTransactionId())
- .build();
-
- // match for everything else to send to controller. Essentially
- // the table miss flow entry
- populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
- log.debug("Adding termination-mac-rules in sw {}", getStringId());
- List<OFMessage> msglist = new ArrayList<OFMessage>(2);
- msglist.add(ipEntry);
- msglist.add(mplsEntry);
- write(msglist);
- }
private List<String> getMyIps() { // send to controller
List<String> myIps = new ArrayList<String>();
@@ -828,7 +1390,7 @@
.setTableId(TableId.of(TABLE_IPv4_UNICAST))
.setMatch(match)
.setInstructions(instructions)
- .setPriority(SLASH_24_PRIORITY)
+ .setPriority((short) 0xfff0)
.setBufferId(OFBufferId.NO_BUFFER)
.setIdleTimeout(0)
.setHardTimeout(0)
@@ -918,7 +1480,7 @@
if (routerNextHopIps.get(i).mask.equals("255.255.255.255"))
priority = MAX_PRIORITY;
else
- priority = SLASH_24_PRIORITY;
+ priority = (short) 0xfff0;
OFMessage myIpEntry = factory.buildFlowAdd()
.setTableId(TableId.of(TABLE_IPv4_UNICAST))
.setMatch(match)
@@ -1133,90 +1695,5 @@
}
- /**
- * By default if none of the booleans in the call are set, then the
- * table-miss entry is added with no instructions, which means that pipeline
- * execution will stop, and the action set associated with the packet will
- * be executed.
- *
- * @param tableToAdd
- * @param toControllerNow as an APPLY_ACTION instruction
- * @param toControllerWrite as a WRITE_ACITION instruction
- * @param toTable as a GOTO_TABLE instruction
- * @param tableToSend
- * @throws IOException
- */
- @SuppressWarnings("unchecked")
- private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
- boolean toControllerWrite,
- boolean toTable, int tableToSend) throws IOException {
- OFOxmList oxmList = OFOxmList.EMPTY;
- OFMatchV3 match = factory.buildMatchV3()
- .setOxmList(oxmList)
- .build();
- OFAction outc = factory.actions()
- .buildOutput()
- .setPort(OFPort.CONTROLLER)
- .setMaxLen(OFPCML_NO_BUFFER)
- .build();
- List<OFInstruction> instructions = new ArrayList<OFInstruction>();
- if (toControllerNow) {
- // table-miss instruction to send to controller immediately
- OFInstruction instr = factory.instructions()
- .buildApplyActions()
- .setActions(Collections.singletonList(outc))
- .build();
- instructions.add(instr);
- }
-
- if (toControllerWrite) {
- // table-miss instruction to write-action to send to controller
- // this will be executed whenever the action-set gets executed
- OFInstruction instr = factory.instructions()
- .buildWriteActions()
- .setActions(Collections.singletonList(outc))
- .build();
- instructions.add(instr);
- }
-
- if (toTable) {
- // table-miss instruction to goto-table x
- OFInstruction instr = factory.instructions()
- .gotoTable(TableId.of(tableToSend));
- instructions.add(instr);
- }
-
- if (!toControllerNow && !toControllerWrite && !toTable) {
- // table-miss has no instruction - at which point action-set will be
- // executed - if there is an action to output/group in the action
- // set
- // the packet will be sent there, otherwise it will be dropped.
- instructions = (List<OFInstruction>) Collections.EMPTY_LIST;
- }
-
- OFMessage tableMissEntry = factory.buildFlowAdd()
- .setTableId(TableId.of(tableToAdd))
- .setMatch(match) // match everything
- .setInstructions(instructions)
- .setPriority(MIN_PRIORITY)
- .setBufferId(OFBufferId.NO_BUFFER)
- .setIdleTimeout(0)
- .setHardTimeout(0)
- .setXid(getNextTransactionId())
- .build();
- write(tableMissEntry, null);
- }
-
- private void sendBarrier(boolean finalBarrier) throws IOException {
- int xid = getNextTransactionId();
- if (finalBarrier) {
- barrierXidToWaitFor = xid;
- }
- OFBarrierRequest br = factory
- .buildBarrierRequest()
- .setXid(xid)
- .build();
- write(br, null);
- }
}
diff --git a/src/main/java/net/onrc/onos/core/matchaction/match/Ipv4PacketMatch.java b/src/main/java/net/onrc/onos/core/matchaction/match/Ipv4PacketMatch.java
deleted file mode 100644
index 7182ca1..0000000
--- a/src/main/java/net/onrc/onos/core/matchaction/match/Ipv4PacketMatch.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package net.onrc.onos.core.matchaction.match;
-
-import net.onrc.onos.core.util.IPv4Net;
-
-public class Ipv4PacketMatch implements Match {
-
- IPv4Net dstIp;
-
- public Ipv4PacketMatch(String ipAddressSlash) {
- this.dstIp = new IPv4Net(ipAddressSlash);
- }
-
- public IPv4Net getDestination() {
- return dstIp;
- }
-
-}
diff --git a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java
index c5c15c1..1691759 100644
--- a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java
+++ b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java
@@ -45,6 +45,7 @@
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.core.util.ListenerDispatcher;
+import net.onrc.onos.core.configmanager.INetworkConfigService;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.util.OnosInstanceId;
@@ -368,4 +369,11 @@
public IOFSwitch getEqualSwitch(long dpid) {
return this.activeEqualSwitches.get(dpid);
}
+
+ @Override
+ public INetworkConfigService getNetworkConfigService() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}