From eaad2b6f2e3f5b7752c63603a57d3592dd17c960 Mon Sep 17 00:00:00 2001 From: Ryan Izard <rizard@g.clemson.edu> Date: Fri, 4 Dec 2015 12:07:05 -0500 Subject: [PATCH] OF-DPA utils integrated into Forwarding --- .../forwarding/Forwarding.java | 63 ++++++++++++++++++- .../routing/ForwardingBase.java | 7 ++- .../floodlightcontroller/util/OFDPAUtils.java | 24 +++---- .../forwarding/ForwardingTest.java | 7 +++ 4 files changed, 83 insertions(+), 18 deletions(-) diff --git a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java index 1db7e728d..aef485f3a 100644 --- a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java +++ b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java @@ -28,6 +28,8 @@ import java.util.Set; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.IOFSwitchListener; +import net.floodlightcontroller.core.PortChangeType; import net.floodlightcontroller.core.internal.IOFSwitchService; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; @@ -49,11 +51,16 @@ import net.floodlightcontroller.routing.IRoutingService; import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.NodePortTuple; +import net.floodlightcontroller.util.OFDPAUtils; +import net.floodlightcontroller.util.OFPortMode; +import net.floodlightcontroller.util.OFPortModeTuple; import org.projectfloodlight.openflow.protocol.OFFlowMod; import org.projectfloodlight.openflow.protocol.OFFlowModCommand; +import org.projectfloodlight.openflow.protocol.OFGroupType; import org.projectfloodlight.openflow.protocol.OFPacketIn; import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFPortDesc; import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.protocol.action.OFAction; import org.projectfloodlight.openflow.protocol.match.Match; @@ -65,14 +72,16 @@ import org.projectfloodlight.openflow.types.IPv6Address; import org.projectfloodlight.openflow.types.IpProtocol; import org.projectfloodlight.openflow.types.MacAddress; import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFGroup; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.OFVlanVidMatch; +import org.projectfloodlight.openflow.types.TableId; import org.projectfloodlight.openflow.types.U64; import org.projectfloodlight.openflow.types.VlanVid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Forwarding extends ForwardingBase implements IFloodlightModule { +public class Forwarding extends ForwardingBase implements IFloodlightModule, IOFSwitchListener { protected static Logger log = LoggerFactory.getLogger(Forwarding.class); @Override @@ -509,5 +518,57 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { @Override public void startUp(FloodlightModuleContext context) { super.startUp(); + switchService.addOFSwitchListener(this); + } + + @Override + public void switchAdded(DatapathId switchId) { + } + + @Override + public void switchRemoved(DatapathId switchId) { + } + + @Override + public void switchActivated(DatapathId switchId) { + IOFSwitch sw = switchService.getSwitch(switchId); + if (sw == null) { + log.warn("Switch {} was activated but had no switch object in the switch service. Perhaps it quickly disconnected", switchId); + return; + } + if (OFDPAUtils.isOFDPASwitch(sw)) { + sw.write(sw.getOFFactory().buildFlowDelete() + .setTableId(TableId.ALL) + .build() + ); + sw.write(sw.getOFFactory().buildGroupDelete() + .setGroup(OFGroup.ANY) + .setGroupType(OFGroupType.ALL) + .build() + ); + sw.write(sw.getOFFactory().buildGroupDelete() + .setGroup(OFGroup.ANY) + .setGroupType(OFGroupType.INDIRECT) + .build() + ); + sw.write(sw.getOFFactory().buildBarrierRequest().build()); + + List<OFPortModeTuple> portModes = new ArrayList<OFPortModeTuple>(); + for (OFPortDesc p : sw.getPorts()) { + portModes.add(OFPortModeTuple.of(p.getPortNo(), OFPortMode.ACCESS)); + } + if (log.isWarnEnabled()) { + log.warn("For OF-DPA switch {}, initializing VLAN {} on ports {}", new Object[] { switchId, VlanVid.ZERO, portModes}); + } + OFDPAUtils.addLearningSwitchPrereqs(sw, VlanVid.ZERO, portModes); + } + } + + @Override + public void switchPortChanged(DatapathId switchId, OFPortDesc port, PortChangeType type) { + } + + @Override + public void switchChanged(DatapathId switchId) { } } diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java index aa23ad24a..5cf593b3d 100644 --- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java +++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java @@ -42,6 +42,7 @@ import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.NodePortTuple; import net.floodlightcontroller.util.MatchUtils; +import net.floodlightcontroller.util.OFDPAUtils; import net.floodlightcontroller.util.OFMessageDamper; import net.floodlightcontroller.util.TimedCache; @@ -264,7 +265,7 @@ public abstract class ForwardingBase implements IOFMessageListener { outPort }); } - /*if (OFDPAUtils.isOFDPASwitch(sw)) { + if (OFDPAUtils.isOFDPASwitch(sw)) { OFDPAUtils.addLearningSwitchFlow(sw, cookie, FLOWMOD_DEFAULT_PRIORITY, FLOWMOD_DEFAULT_HARD_TIMEOUT, @@ -272,9 +273,9 @@ public abstract class ForwardingBase implements IOFMessageListener { fmb.getMatch(), null, // TODO how to determine output VLAN for lookup of L2 interface group outPort); - } else {*/ + } else { messageDamper.write(sw, fmb.build()); - /*}*/ + } /* Push the packet out the first hop switch */ if (sw.getId().equals(pinSwitch) && diff --git a/src/main/java/net/floodlightcontroller/util/OFDPAUtils.java b/src/main/java/net/floodlightcontroller/util/OFDPAUtils.java index da84770a6..b3a790412 100644 --- a/src/main/java/net/floodlightcontroller/util/OFDPAUtils.java +++ b/src/main/java/net/floodlightcontroller/util/OFDPAUtils.java @@ -268,7 +268,7 @@ public class OFDPAUtils { for (OFPortModeTuple p : ports) { if (sw.getOFFactory().getVersion().equals(OFVersion.OF_10) && (sw.getPort(p.getPort()) == null || p.getPort().getShortPortNumber() > 0xFF00)) { throw new IllegalArgumentException("Port " + p.getPort().getPortNumber() + " is not a valid port on switch " + sw.getId().toString()); - } else if (!sw.getOFFactory().getVersion().equals(OFVersion.OF_10) && (sw.getPort(p.getPort()) == null || p.getPort().getPortNumber() > 0xffFFff00)) { + } else if (!sw.getOFFactory().getVersion().equals(OFVersion.OF_10) && (sw.getPort(p.getPort()) == null || U32.of(p.getPort().getPortNumber()).compareTo(U32.of(0xffFFff00)) != -1)) { throw new IllegalArgumentException("Port " + p.getPort().getPortNumber() + " is not a valid port on switch " + sw.getId().toString()); } } @@ -285,7 +285,7 @@ public class OFDPAUtils { actions.add(sw.getOFFactory().actions().output(p.getPort(), 0xffFFffFF)); OFGroupAdd ga = sw.getOFFactory().buildGroupAdd() - .setGroup(GroupIds.createL2Interface(p.getPort(), (vlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : vlan))) + .setGroup(GroupIds.createL2Interface(p.getPort(), vlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : vlan)) .setGroupType(OFGroupType.INDIRECT) .setBuckets(Collections.singletonList( sw.getOFFactory().buildBucket() @@ -302,14 +302,11 @@ public class OFDPAUtils { List<OFBucket> bucketList = new ArrayList<OFBucket>(ports.size()); for (OFPortModeTuple p : ports) { List<OFAction> actions = new ArrayList<OFAction>(); - if (vlan.equals(VlanVid.ZERO) || p.getMode() == OFPortMode.ACCESS) { - actions.add(sw.getOFFactory().actions().popVlan()); - } - actions.add(sw.getOFFactory().actions().output(p.getPort(), 0xffFFffFF)); + actions.add(sw.getOFFactory().actions().group(GroupIds.createL2Interface(p.getPort(), vlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : vlan))); bucketList.add(sw.getOFFactory().buildBucket().setActions(actions).build()); } OFGroupAdd ga = sw.getOFFactory().buildGroupAdd() /* use the VLAN ID as the group ID */ - .setGroup(GroupIds.createL2Flood(U16.of(vlan.getVlan()), vlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : vlan)) + .setGroup(GroupIds.createL2Flood(U16.of((vlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : vlan).getVlan()), vlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : vlan)) .setGroupType(OFGroupType.ALL) .setBuckets(bucketList) .build(); @@ -352,7 +349,7 @@ public class OFDPAUtils { for (OFPortModeTuple p : ports) { if (sw.getOFFactory().getVersion().equals(OFVersion.OF_10) && (sw.getPort(p.getPort()) == null || p.getPort().getShortPortNumber() > 0xFF00)) { throw new IllegalArgumentException("Port " + p.getPort().getPortNumber() + " is not a valid port on switch " + sw.getId().toString()); - } else if (!sw.getOFFactory().getVersion().equals(OFVersion.OF_10) && (sw.getPort(p.getPort()) == null || p.getPort().getPortNumber() > 0xffFFff00)) { + } else if (!sw.getOFFactory().getVersion().equals(OFVersion.OF_10) && (sw.getPort(p.getPort()) == null || U32.of(p.getPort().getPortNumber()).compareTo(U32.of(0xffFFff00)) != -1)) { throw new IllegalArgumentException("Port " + p.getPort().getPortNumber() + " is not a valid port on switch " + sw.getId().toString()); } } @@ -441,13 +438,15 @@ public class OFDPAUtils { /* * We will insert a DLF flow to send to controller in the bridging table (50). */ - writeActions.add(sw.getOFFactory().actions().group(OFDPAUtils.GroupIds.createL2Flood(U16.of(vlan.getVlan()) /* ID */, vlan))); /* bogus action */ + writeActions.add(sw.getOFFactory().actions().group(OFDPAUtils.GroupIds.createL2Flood( + U16.of((vlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : vlan).getVlan()) /* ID */, + vlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : vlan))); /* bogus action */ applyActions.add(sw.getOFFactory().actions().output(OFPort.CONTROLLER, 0xffFFffFF)); /* real, intended action */ instructions.add(sw.getOFFactory().instructions().writeActions(writeActions)); instructions.add(sw.getOFFactory().instructions().applyActions(applyActions)); instructions.add(sw.getOFFactory().instructions().gotoTable(Tables.POLICY_ACL)); /* must go to policy ACL otherwise dropped; bogus though */ fab = fab.setMatch(sw.getOFFactory().buildMatch() - .setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlanVid(vlan)) /* must match on just VLAN; dst MAC wildcarded */ + .setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlanVid(vlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : vlan)) /* must match on just VLAN; dst MAC wildcarded */ .build()) .setInstructions(instructions) .setPriority(DLF_PRIORITY) /* lower priority */ @@ -526,10 +525,7 @@ public class OFDPAUtils { */ ArrayList<OFInstruction> instructions = new ArrayList<OFInstruction>(); ArrayList<OFAction> actions = new ArrayList<OFAction>(); - - if (outVlan.equals(VlanVid.ZERO)) { - actions.add(sw.getOFFactory().actions().popVlan()); - } + actions.add(sw.getOFFactory().actions().group(GroupIds.createL2Interface(outPort, (outVlan.equals(VlanVid.ZERO) ? VlanVid.ofVlan(1) : outVlan)))); instructions.add(sw.getOFFactory().instructions().writeActions(actions)); instructions.add(sw.getOFFactory().instructions().gotoTable(Tables.POLICY_ACL)); /* must go here or dropped */ diff --git a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java index 8c84298cd..f3fc8c8ba 100644 --- a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java +++ b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java @@ -31,6 +31,7 @@ import java.util.Set; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.SwitchDescription; import net.floodlightcontroller.core.internal.IOFSwitchService; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.test.MockThreadPoolService; @@ -67,6 +68,7 @@ import org.projectfloodlight.openflow.protocol.OFFeaturesReply; import org.projectfloodlight.openflow.protocol.OFFlowMod; import org.projectfloodlight.openflow.protocol.match.Match; import org.projectfloodlight.openflow.protocol.match.MatchField; +import org.projectfloodlight.openflow.protocol.OFDescStatsReply; import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.OFMessage; @@ -99,6 +101,7 @@ public class ForwardingTest extends FloodlightTestCase { protected MockThreadPoolService threadPool; protected IOFSwitch sw1, sw2; protected OFFeaturesReply swFeatures; + protected OFDescStatsReply swDescription; protected IDevice srcDevice, dstDevice1, dstDevice2; /* reuse for IPv4 and IPv6 */ protected OFPacketIn packetIn; protected OFPacketIn packetInIPv6; @@ -162,6 +165,7 @@ public class ForwardingTest extends FloodlightTestCase { entityClassifier.startUp(fmc); verify(topology); + swDescription = factory.buildDescStatsReply().build(); swFeatures = factory.buildFeaturesReply().setNBuffers(1000).build(); // Mock switches sw1 = EasyMock.createMock(IOFSwitch.class); @@ -177,6 +181,9 @@ public class ForwardingTest extends FloodlightTestCase { expect(sw1.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes(); expect(sw2.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes(); + + expect(sw1.getSwitchDescription()).andReturn(new SwitchDescription(swDescription)).anyTimes(); + expect(sw2.getSwitchDescription()).andReturn(new SwitchDescription(swDescription)).anyTimes(); // Load the switch map Map<DatapathId, IOFSwitch> switches = new HashMap<DatapathId, IOFSwitch>(); -- GitLab