package edu.usc.enl.dynamicmeasurement.floodlight;
import edu.usc.enl.dynamicmeasurement.model.WildcardPattern;
import net.floodlightcontroller.core.IOFSwitch;
import org.openflow.protocol.*;
import org.openflow.protocol.action.OFAction;
import org.openflow.protocol.action.OFActionOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created with IntelliJ IDEA.
* User: masoud
* Date: 10/18/13
* Time: 3:57 PM <br/>
* Tries to save rules in a single switch
*/
class RuleSaverThreadMethod implements Runnable {
public static final WildcardPattern DEFAULT_PATTERN = new WildcardPattern(0, WildcardPattern.TOTAL_LENGTH, 0);
private final SwitchData sw;
private final Map<WildcardPattern, WildcardPattern> toSaveRules;
/**
* Keeps track of the last fetched rules, to not save rules that have not changed.
*/
private final Map<WildcardPattern, WildcardPattern> lastFetchedRules;
private final List<OFMessage> deleteFlows;
private final List<OFMessage> installFlows;
private final OFFlowMod defaultFlowMod;
private int epoch;
//Statistics information
private int toDelete;
private int notInstall;
private int toInstall;
public RuleSaverThreadMethod(SwitchData aSwitch, int capacity, Map<WildcardPattern, WildcardPattern> toSaveRules,
Map<WildcardPattern, WildcardPattern> lastFetchedRules) {
this.sw = aSwitch;
this.toSaveRules = toSaveRules;
this.lastFetchedRules = lastFetchedRules;
deleteFlows = new ArrayList<>();
WildcardPattern pattern = new WildcardPattern(0, 0, 0);
for (int i = 0; i < capacity; i++) {
deleteFlows.add(getDeleteRule(pattern, sw.getFlow()));
}
defaultFlowMod = getOfFlowMod(DEFAULT_PATTERN, sw, true);
installFlows = new ArrayList<>();
for (int i = 0; i < capacity; i++) {
installFlows.add(getOfFlowMod(pattern, sw, true));
}
}
public static OFFlowMod getOfFlowMod(WildcardPattern pattern, SwitchData sw, boolean denyAccept) {
OFFlowMod flowMod = sw.getFlow();
long srcIP = pattern.getData() << pattern.getWildcardNum();
// long dstIP=1;
int srcIPWildcardNum = pattern.getWildcardNum();
flowMod.setCommand(OFFlowMod.OFPFC_ADD);
flowMod.setFlags((short) 0);
OFMatch match = new OFMatch();
match.setNetworkSource((int) srcIP);
// match.setNetworkDestination(IPv4.toIPv4Address(dstIP));
if (srcIPWildcardNum == WildcardPattern.TOTAL_LENGTH) {
match.setWildcards(Wildcards.FULL);
flowMod.setPriority(((short) (1)));
} else {
match.setWildcards(Wildcards.FULL.matchOn(Wildcards.Flag.DL_TYPE).withNwSrcMask(WildcardPattern.TOTAL_LENGTH - srcIPWildcardNum));
match.setDataLayerType(Short.parseShort("800", 16));
flowMod.setPriority(((short) (10)));
}
flowMod.setMatch(match);
flowMod.setOutPort(OFPort.OFPP_NONE.getValue());
flowMod.setBufferId(OFPacketOut.BUFFER_ID_NONE);
if (denyAccept) {
flowMod.setActions(new ArrayList<OFAction>());
flowMod.setLength((short) (OFFlowMod.MINIMUM_LENGTH));
} else {
List<OFAction> actions = new ArrayList<OFAction>();
if (sw.getSw().hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_FLOOD)) {
actions.add(new OFActionOutput(OFPort.OFPP_FLOOD.getValue(),
(short) 0xFFFF));
} else {
actions.add(new OFActionOutput(OFPort.OFPP_ALL.getValue(),
(short) 0xFFFF));
}
flowMod.setActions(actions);
flowMod.setLength((short) (OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH));
}
flowMod.setHardTimeout((short) 0);
flowMod.setIdleTimeout((short) 0);
return flowMod;
}
public static OFFlowMod getDeleteRule(WildcardPattern pattern, OFFlowMod flowMod) {
int srcIPWildcardNum = pattern.getWildcardNum();
OFMatch match = new OFMatch();
long srcIP = pattern.getData() << pattern.getWildcardNum();
match.setNetworkSource((int) srcIP);
if (srcIPWildcardNum == WildcardPattern.TOTAL_LENGTH) {
match.setWildcards(Wildcards.FULL);
flowMod.setPriority(((short) (1)));
} else {
match.setWildcards(Wildcards.FULL.matchOn(Wildcards.Flag.DL_TYPE).withNwSrcMask(WildcardPattern.TOTAL_LENGTH - srcIPWildcardNum));
match.setDataLayerType(Short.parseShort("800", 16));
flowMod.setPriority(((short) (10)));
}
flowMod.setMatch(match);
flowMod.setOutPort(OFPort.OFPP_NONE);
flowMod.setCommand(OFFlowMod.OFPFC_DELETE);
return flowMod;
}
@Override
public void run() {
try {
//find rules that must be deleted
toDelete = 0;
notInstall = 0;
toInstall = 0;
toSaveRules.put(DEFAULT_PATTERN, DEFAULT_PATTERN);
{
for (WildcardPattern wildcardPattern : lastFetchedRules.keySet()) {
if (!toSaveRules.containsKey(wildcardPattern)) {
// System.out.println(sw + " delete " + wildcardPattern);
//toDeleteFlowMods.add(getDeleteRule(wildcardPattern));
changeDeleteRule(wildcardPattern, (OFFlowMod) deleteFlows.get(toDelete++));
}
}
if (toDelete > 0) {
sw.write(deleteFlows.subList(0, toDelete));
sw.sendBarrier();
}
}
{
if (lastFetchedRules.size() == 0) {
sw.write(defaultFlowMod);
} else {
for (WildcardPattern pattern : toSaveRules.keySet()) {
if (!lastFetchedRules.containsKey(pattern)) {
changeDeleteRule(pattern, (OFFlowMod) installFlows.get(toInstall++));
} else {
notInstall++;
}
}
sw.write(installFlows.subList(0, toInstall));
}
sw.sendBarrier();
sw.getLogWriter().println(epoch + "," + toDelete + "," + notInstall + "," + toInstall);
}
} catch (IOException e) {
e.printStackTrace();
}
sw.flush();
}
private void changeDeleteRule(WildcardPattern pattern, OFFlowMod mod) {
int srcIPWildcardNum = pattern.getWildcardNum();
long srcIP = pattern.getData() << pattern.getWildcardNum();
OFMatch match = mod.getMatch();
match.setNetworkSource((int) srcIP);
match.setWildcards(Wildcards.FULL.matchOn(Wildcards.Flag.DL_TYPE).withNwSrcMask(WildcardPattern.TOTAL_LENGTH - srcIPWildcardNum));
}
public int getEpoch() {
return epoch;
}
public void setEpoch(int epoch) {
this.epoch = epoch;
}
}