boolean reqeustFlowRemovedNotifn,
boolean doFlush,
short flowModCommand) {
boolean srcSwitchIncluded = false;
OFFlowMod fm =
(OFFlowMod) floodlightProvider.getOFMessageFactory()
.getMessage(OFType.FLOW_MOD);
OFActionOutput action = new OFActionOutput();
action.setMaxLength((short)0xffff);
List<OFAction> actions = new ArrayList<OFAction>();
actions.add(action);
fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
.setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
.setBufferId(OFPacketOut.BUFFER_ID_NONE)
.setCookie(cookie)
.setCommand(flowModCommand)
.setMatch(match)
.setActions(actions)
.setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
List<NodePortTuple> switchPortList = route.getPath();
for (int indx = switchPortList.size()-1; indx > 0; indx -= 2) {
// indx and indx-1 will always have the same switch DPID.
long switchDPID = switchPortList.get(indx).getNodeId();
IOFSwitch sw = floodlightProvider.getSwitch(switchDPID);
if (sw == null) {
if (log.isWarnEnabled()) {
log.warn("Unable to push route, switch at DPID {} " +
"not available", switchDPID);
}
return srcSwitchIncluded;
}
// set the match.
fm.setMatch(wildcard(match, sw, wildcard_hints));
// set buffer id if it is the source switch
if (1 == indx) {
// Set the flag to request flow-mod removal notifications only for the
// source switch. The removal message is used to maintain the flow
// cache. Don't set the flag for ARP messages - TODO generalize check
if ((reqeustFlowRemovedNotifn)
&& (match.getDataLayerType() != Ethernet.TYPE_ARP)) {
/**with new flow cache design, we don't need the flow removal message from switch anymore
fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
*/
match.setWildcards(fm.getMatch().getWildcards());
}
}
short outPort = switchPortList.get(indx).getPortId();
short inPort = switchPortList.get(indx-1).getPortId();
// set input and output ports on the switch
fm.getMatch().setInputPort(inPort);
((OFActionOutput)fm.getActions().get(0)).setPort(outPort);
try {
counterStore.updatePktOutFMCounterStoreLocal(sw, fm);
if (log.isTraceEnabled()) {
log.trace("Pushing Route flowmod routeIndx={} " +
"sw={} inPort={} outPort={}",
new Object[] {indx,
sw,
fm.getMatch().getInputPort(),
outPort });
}
messageDamper.write(sw, fm, cntx);
if (doFlush) {
sw.flush();
counterStore.updateFlush();
}
// Push the packet out the source switch
if (sw.getId() == pinSwitch) {
// TODO: Instead of doing a packetOut here we could also
// send a flowMod with bufferId set....
pushPacket(sw, pi, false, outPort, cntx);
srcSwitchIncluded = true;
}
} catch (IOException e) {
log.error("Failure writing flow mod", e);
}
try {
fm = fm.clone();
} catch (CloneNotSupportedException e) {
log.error("Failure cloning flow mod", e);
}
}