* @param cntx
* @return
*/
private Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
// Read in packet data headers by using OFMatch
OFMatch match = new OFMatch();
match.loadFromPacket(pi.getPacketData(), pi.getInPort());
Long sourceMac = Ethernet.toLong(match.getDataLayerSource());
Long destMac = Ethernet.toLong(match.getDataLayerDestination());
Short vlan = match.getDataLayerVirtualLan();
if ((destMac & 0xfffffffffff0L) == 0x0180c2000000L) {
if (log.isTraceEnabled()) {
log.trace("ignoring packet addressed to 802.1D/Q reserved addr: switch {} vlan {} dest MAC {}",
new Object[]{ sw, vlan, HexString.toHexString(destMac) });
}
return Command.STOP;
}
if ((sourceMac & 0x010000000000L) == 0) {
// If source MAC is a unicast address, learn the port for this MAC/VLAN
this.addToPortMap(sw, sourceMac, vlan, pi.getInPort());
}
// Now output flow-mod and/or packet
Short outPort = getFromPortMap(sw, destMac, vlan);
if (outPort == null) {
// If we haven't learned the port for the dest MAC/VLAN, flood it
// Don't flood broadcast packets if the broadcast is disabled.
// XXX For LearningSwitch this doesn't do much. The sourceMac is removed
// from port map whenever a flow expires, so you would still see
// a lot of floods.
this.writePacketOutForPacketIn(sw, pi, OFPort.OFPP_FLOOD.getValue());
} else if (outPort == match.getInputPort()) {
log.trace("ignoring packet that arrived on same port as learned destination:"
+ " switch {} vlan {} dest MAC {} port {}",
new Object[]{ sw, vlan, HexString.toHexString(destMac), outPort });
} else {
// Add flow table entry matching source MAC, dest MAC, VLAN and input port
// that sends to the port we previously learned for the dest MAC/VLAN. Also
// add a flow table entry with source and destination MACs reversed, and
// input and output ports reversed. When either entry expires due to idle
// timeout, remove the other one. This ensures that if a device moves to
// a different port, a constant stream of packets headed to the device at
// its former location does not keep the stale entry alive forever.
// FIXME: current HP switches ignore DL_SRC and DL_DST fields, so we have to match on
// NW_SRC and NW_DST as well
match.setWildcards(((Integer)sw.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).intValue()
& ~OFMatch.OFPFW_IN_PORT
& ~OFMatch.OFPFW_DL_VLAN & ~OFMatch.OFPFW_DL_SRC & ~OFMatch.OFPFW_DL_DST
& ~OFMatch.OFPFW_NW_SRC_MASK & ~OFMatch.OFPFW_NW_DST_MASK);
// We write FlowMods with Buffer ID none then explicitly PacketOut the buffered packet
this.pushPacket(sw, match, pi, outPort);
this.writeFlowMod(sw, OFFlowMod.OFPFC_ADD, OFPacketOut.BUFFER_ID_NONE, match, outPort);
if (LEARNING_SWITCH_REVERSE_FLOW) {
this.writeFlowMod(sw, OFFlowMod.OFPFC_ADD, -1, match.clone()
.setDataLayerSource(match.getDataLayerDestination())
.setDataLayerDestination(match.getDataLayerSource())
.setNetworkSource(match.getNetworkDestination())
.setNetworkDestination(match.getNetworkSource())
.setTransportSource(match.getTransportDestination())
.setTransportDestination(match.getTransportSource())
.setInputPort(outPort),
match.getInputPort());
}
}
return Command.CONTINUE;
}