James Won-Ki Hong Department of Computer Science and Engineering POSTECH, Korea jwkhong@postech.ac.kr POSTECH CSED702Y: Software Defined Networking 1/24 Outline Introduction Overview Installation Floodlight Tutorial Rest API usage Native API usage Demo Demo scenarios Demo presentation POSTECH CSED702Y: Software Defined Networking 2/24 Introduction Floodlight A completely open, free, Apache-licensed Java-based OpenFlow controller • • • • Open sourced, currently hosted in github Apache licensed use for any purpose Java-based (forked from Beacon) Currently support OpenFlow v1.0 and v1.3 OpenFlowJ (Loxi) • A new OpenFlow API with support for OF1.[0-3+] • OpenFlow multi-version support, Bug resilience • Loxigen • A tool that generates OpenFlow protocol libraries for a number of languages • Support C, Python, Java and an auto-generated wireshark dissector in Lua • Currently used by many OpenFlow controllers (e.g., ONOS, floodlight …) POSTECH CSED702Y: Software Defined Networking 3/24 Floodlight Overview (1/2) Floodlight Architecture A controller + a collection of applications built on top of Floodlight Circuit Pusher (python) OpenStackQuantum Plugin (python) Your Applications … REST Applications REST API (Implement Restlet Routable Interface) Module Applications Floodlight Controller VNF PortDown Reconciliation Forwarding Hub Learning Switch Your Applications … POSTECH Java API Firewall StaticFlow EntryPusher Module Manager Thread Pool Device Manager Topology Service Packet Streamer Link Discovery Jython Sever Flow Cache Web UI Unit Tests Storage Memory NoSQL OpenFlow Services Switches Controller Memory PerfMon CSED702Y: Software Defined Networking Trace Counter Store 4/24 Floodlight Overview (2/2) Application Modules Routing/Forwarding • Default reactive packet forwarding application Learning switch • Example learning switch application, can replace routing/forwarding Static Flow Entry Pusher • Install specific flow entry (match + action) to a specific switch Firewall • An application to apply ACL rules to allow/deny traffic based on specified match Port Down Reconciliation Virtual Network Filter (VNF) • Simple MAC-based network isolation application Core REST APIs Static Flow Pusher REST API • Allow the user to proactively insert/delete/list the flows to OpenFlow switch Firewall REST API • Allow the user to insert/delete/list rules for firewall POSTECH CSED702Y: Software Defined Networking 5/24 Floodlight Installation Native Installation from Source Recommended OS: any version of Linux distribution Procedures • Install pre-requisite software packages $ sudo apt-get install openjdk-7-jdk $ sudo apt-get install ant # yum install java-1.7.0-openjdk java-1.7.0-openjdk-devel # yum install ant Ubuntu EPEL • Download source from github and build the stable version $ $ $ $ git clone git://github.com/floodlight/floodlight.git cd floodlight git checkout v1.0 ant • Run the floodlight # ./floodlight.sh • Access floodlight dashboard • http://floodlight_ip_address:8080/ui/index.html POSTECH CSED702Y: Software Defined Networking 6/24 Configuration of Floodlight Configuration Configuration files for Floodlight modules • Enumeration of ALL modules compiled in the floodlight.jar binary • “src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule” • Enumeration of modules selected to load/run • “src/main/resources/floodlightdefault.properties” • Also place to configure certain parameters • E.g., REST API server, web UI port, default timeout values and etc. • If you implement a new module, you need to update above two files to take effect Configuration file for logging • Floodlight relies on org.slf4j.Logger to log debug messages • Located at $FLOODLIGHT_ROOT/logback.xml <configuration scan="true"> <appender name="STDOUT"> <encoder> <pattern>%level [%logger:%thread] %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT" /> </root> <logger name="org" level="WARN"/> <logger name="net.floodlightcontroller" level="INFO"/> <logger name="net.floodlightcontroller.logging" level="WARN"/> </configuration> POSTECH CSED702Y: Software Defined Networking 7/24 Floodlight REST API (1/3) Static Flow Pusher API URI Description Arguments /.../json Add/delete static flow HTTP POST data (add), HTTP DELETE (deletion) /…/list/<switch>/json List static flows switch: Valid Switch DPID or "all" /…/clear/<switch>/json Clear static flows switch: Valid Switch DPID or "all" REST API Example Insert a flow on switch 1 (in port 1, out port 2) curl -d '{"switch": "00:00:00:00:00:00:00:01", "name":"flow-mod-1", "cookie":"0", "priority":"32768", "ingress-port":"1","active":"true", "actions":"output=2"}' http://<controller_ip>:8080/.../json List all inserted flows curl http://<controller_ip>:8080/wm/core/switch/1/flow/json; Delete a static flow by its name ‘flow-mod-1’ curl -X DELETE -d '{"name":"flow-mod-1"}' http://<controller_ip>:8080/wm/staticflowentrypusher/json POSTECH CSED702Y: Software Defined Networking 8/24 Floodlight REST API (2/3) URI Method URI Arguments Data Description /…/<op>/json GET op: status, enable, None disable, storageRules, subnet-mask query the status of, enable, and disable the firewall /…/rules/json GET None None List all existing rules in json format POST None {"<field 1>":"<value 1>", Create new firewall rule "<field 2>":"<value 2>", ...} "field":"value" pairs below Ex. "src-mac": in any order and "<xx:xx:xx:xx:xx:xx>" combination: DELETE None {"<ruleid>":"<int>"} Delete a rule by ruleid REST API Example Show whether the firewall is enabled or disabled curl http://localhost:8080/wm/firewall/module/status/json Enable or Disable the firewall curl http://localhost:8080/wm/firewall/module/enable/json curl http://localhost:8080/wm/firewall/module/disable/json POSTECH CSED702Y: Software Defined Networking 9/24 Floodlight REST API (3/3) REST API Example Adding an ALLOW rule for all flows to pass through switch 00:00:00:00:00:00:00:01 curl -X POST -d '{"switchid": "00:00:00:00:00:00:00:01"}' http://localhost:8080/wm/firewall/rules/json Adding an ALLOW rule for all flows between IP host 10.0.0.3 and host 10.0.0.7 (default action is allow, no need to specify) curl -X POST -d '{"src-ip": "10.0.0.3/32", "dst-ip": "10.0.0.7/32"}' http://localhost:8080/wm/firewall/rules/json curl -X POST -d '{"src-ip": "10.0.0.7/32", "dst-ip": "10.0.0.3/32"}' http://localhost:8080/wm/firewall/rules/json Adding an ALLOW rule for UDP, and then block port 5010 curl -X POST -d '{"src-ip": "10.0.0.3/32", "dst-ip": "10.0.0.7/32", "nw-proto":"UDP" }' http://localhost:8080/wm/firewall/rules/json curl -X POST -d '{"src-ip": "10.0.0.3/32", "dst-ip": "10.0.0.7/32", "nw-proto":"UDP", "tp-src":"5010", "action":"DENY" }' http://.../rules/json POSTECH CSED702Y: Software Defined Networking 10/24 How to Write a Module? (1/2) A Module Creation Create a class Implement IFloodlightModule interface public class YourModuleName implements IFloodlightModule { … } Add unimplemented methods @Override public Collection< Class< ? extends IFloodlightService >> getModuleServices() { // Add services to Collection< Class< ? extends IFloodlightService >> l // if you have any, otherwise just return null... return null; } @Override public Map< Class< ? extends IFloodlightService >, IFloodlightService > getServiceImpls() { // Add corresponding service implementation class to // Map< Class< ? extends IFloodlightService >, IFloodlightService > m, // if you have any, otherwise just return null... return null; } POSTECH CSED702Y: Software Defined Networking 11/24 How to Write a Module? (2/2) A Module Creation Add unimplemented methods @Override public Collection< Class< ? extends IFloodlightService >> getModuleDependencies() { // wire the module up to the module loading system // we tell the module loader that we depend on IFloodlightProviderService... Collection< Class< ? extends IFloodlightService >> l = new ArrayList< Class< ? extends IFloodlightService >>(); l.add( IFloodlightProviderService.class ); return l; } @Override public void init( FloodlightModuleContext context ) throws FloodlightModuleException { // add initialization logic into this method // this method is invoked early in the controller startup process // in this example, we obtain a FloodlightProviderService instance from context floodlightProvider = context.getServiceImpl( IFloodlightProviderService.class ); } @Override public void startUp( FloodlightModuleContext context ) throws FloodlightModuleException { // add basic program logic in here // this method is invoked when initialization phase is over ... } POSTECH CSED702Y: Software Defined Networking 12/24 How to Listen OpenFlow Message? (1/2) Listen All OpenFlow Messages Write a module by implementing IFloodlightModule interface Implement IOFMessageListener interface public class YourModuleName implements IOFMessageListener, IFloodlightModule { … } Add unimplemented methods @Override public String getName() { // add a customized name for our message listener... return YourModuleName.class.getSimpleName(); } @Override public boolean isCallbackOrderingPrereq( OFType type, String name ) { // true: process OF message after the module which has “name” return false; } @Override public boolean isCallbackOrderingPostreq( OFType type, String name ) { // true: process OF message before the module which as “name” return false; } POSTECH CSED702Y: Software Defined Networking 13/24 How to Listen OpenFlow Message? (2/2) Listen All OpenFlow Messages Add unimplemented methods @Override public Command receive( IOFSwitch sw, OFMessage msg, FloodlightContext cntx ) { // this method is invoked when controller receive a OF message from switch // sw: the switch instance that sends this OpenFlow message // msg: OpenFlow message instance // cntx: floodlight’s context instance ... // Command.CONTINUE: allow this message to continue to be handled by other handlers // Command.STOP: disallow other handlers to process this message anymore return Command.CONTINUE; } With receive method, we can capture the PACKET_IN / FlowRemoved OF message only. To capture other OF messages which sent from controller to switch, we have to re-implement OFSwitch class POSTECH CSED702Y: Software Defined Networking 14/24 How to Listen OpenFlow Switch? (1/2) Listen All OpenFlow Switches Write a module by implementing IFloodlightModule interface Implement IOFSwitchListener interface public class YourModuleName implements IOFSwitchListener, IFloodlightModule { … } Add unimplemented methods @Override public void switchAdded( DatapathId switchId ) { // this method is invoked when a switch becomes known to controller // E.g., a switch is connected at some controller } @Override public void switchRemoved( DatapathId switchId ) { // this method is invoked when a switch disconnects with a controller } @Override public void switchActivated( DatapathId switchId ) { // this method is invoked when a switch becomes active on controller } POSTECH CSED702Y: Software Defined Networking 15/24 How to Listen OpenFlow Switch? (2/2) Listen All OpenFlow Switches Add unimplemented methods @Override public void switchPortChanged( DatapathId switchId, OFPortDesc port, PortChangeType type ) { // this method is invoked when a port on a known switch changes // port: a port descriptor which has meta information of the port // type: five port change types // ADD a newly added port // DELETE a removed port from switch // UP a newly activated port // DOWN a deactivated port // OTHER_UPDATE any other changes to the port } @Override public void switchChanged( DatapathId switchId ) { // this method is invoked when any non-port related information // change after a switchAdded, currently unused... } POSTECH CSED702Y: Software Defined Networking 16/24 Message Objects and Builders OpenFlowJ Instance creation • Complex OF message types factory.createBuilder(); • Simple value objects IPv4.of(“1.2.3.4/24”); Message objects and builders Factory createBuilder() createBuilder() Builder Message setFoo(foo) setBar(bar) POSTECH getMessage() CSED702Y: Software Defined Networking 17/24 How to Add a New Flow to a Switch? (1/4) Push a FlowMod Message to a Switch Write a module by implementing IFloodlightModule interface Instantiate a IOFSwitchService instance in init method @Override public void init( FloodlightModuleContext context ) throws FloodlightModuleException { // need to declear switchService variable as global within this class switchService = context.getServiceImpl( IOFSwitchService.class ); } Instantiate a IOFSwitch instance by providing a DatapathId @Override public void switchAdded( DatapathId switchId ) { IOFSwitch sw = switchService.getSwitch( switchId ); // FlowMod message generation logic ... } POSTECH CSED702Y: Software Defined Networking 18/24 How to Add a New Flow to a Switch? (2/4) Push a FlowMod Message to a Switch Generate a unidirectional FlowMod for matching IP traffic IOFSwitch sw = switchService.getSwitch( switchId ); int APP_ID = 1; int USR = 2; // generate a Match Filter Match.Builder mb = sw.getOFFactory().buildMatch(); // here, we only would like to match // source and destination IP addresses IPv4Address srcIp = IPv4Address.of("10.0.0.1" ); IPv4Address dstIp = IPv4Address.of("10.0.0.2" ); mb.setExact( MatchField.IPV4_SRC, srcIp ); mb.setExact( MatchField.IPV4_DST, dstIp ); mb.setExact( MatchField.ETH_TYPE, EthType.IPv4 ); // first register an APP_ID to AppCookie... AppCookie.registerApp( APP_ID, "FlowModSample" ); // generate a cookie (for identification purpose) U64 cookie = AppCookie.makeCookie( APP_ID, USR ); // generate an action list List<OFAction> al = new ArrayList<OFAction>(); POSTECH // set output port as 2 OFPort outPort = OFPort.ofInt( 2 ); OFAction action = sw.getOFFactory().actions().buildOutput(). setPort(outPort). setMaxLen(Integer.MAX_VALUE). build(); // insert the defined action to action list al.add( action ); // start to build an OFFlowMod Message OFFlowMod.Builder fmb = sw.getOFFactory().buildFlowAdd(); fmb.setCookie( cookie ) .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT) .setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT) .setBufferId( OFBufferId.NO_BUFFER ) .setMatch( mb.build() ) .setActions( al ) .setPriority(FLOWMOD_DEFAULT_PRIORITY); // finally write it out to switch sw.write( fmb.build() ); sw.flush(); CSED702Y: Software Defined Networking 19/24 How to Add a New Flow to a Switch? (3/4) Push a FlowMod Message to a Switch Generate a unidirectional FlowMod for matching ARP traffic IOFSwitch sw = switchService.getSwitch( switchId ); int APP_ID = 1; int USR = 2; // generate a Match Filter Match.Builder mb = sw.getOFFactory().buildMatch(); // here, we only would like to match // source and destination IP addresses IPv4Address srcIp = IPv4Address.of("10.0.0.1" ); IPv4Address dstIp = IPv4Address.of("10.0.0.2" ); mb.setExact( MatchField.ARP_SPA, srcIp ); mb.setExact( MatchField.ARP_TPA, dstIp ); mb.setExact( MatchField.ETH_TYPE, EthType.ARP ); // first register an APP_ID to AppCookie... AppCookie.registerApp( APP_ID, "FlowModSample" ); // generate a cookie (for identification purpose) U64 cookie = AppCookie.makeCookie( APP_ID, USR ); // generate an action list List<OFAction> al = new ArrayList<OFAction>(); POSTECH // set output port as 2 OFPort outPort = OFPort.ofInt( 2 ); OFAction action = sw.getOFFactory().actions().buildOutput(). setPort(outPort). setMaxLen(Integer.MAX_VALUE). build(); // insert the defined action to action list al.add( action ); // start to build an OFFlowMod Message OFFlowMod.Builder fmb = sw.getOFFactory().buildFlowAdd(); fmb.setCookie( cookie ) .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT) .setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT) .setBufferId( OFBufferId.NO_BUFFER ) .setMatch( mb.build() ) .setActions( al ) .setPriority(FLOWMOD_DEFAULT_PRIORITY); // finally write it out to switch sw.write( fmb.build() ); sw.flush(); CSED702Y: Software Defined Networking 20/24 How to Add a New Flow to a Switch? (4/4) More on Match Address masking uses either net masking or CIDR • Match the first three octets • Net masking: 10.1.2.0/255.255.255.0 • CIDR: 10.1.2.0/24 • Match the last one octet • Net masking: 0.0.0.3/0.0.0.255 • CIDR: N/A ... Match.Builder mb = sw.getOFFactory().buildMatch(); String srcIpStr = “10.1.2.0/255.255.255.0”; String dstIpStr = “20.1.0.0/255.255.0.0”; mb.setMasked( MatchField.IPV4_SRC, IPv4AddressWithMask.of( srcIpStr ) ); mb.setMasked( MatchField.IPV4_DST, IPv4AddressWithMask.of( dstIpStr ) ); ... Check whether the current match support the designated field ... Match.Builder mb = sw.getOFFactory().buildMatch(); mb.supports( MatchField.IPv6_SRC ); ... POSTECH CSED702Y: Software Defined Networking 21/24 DEMO Scenarios Construct a Customized Topology Using Mininet A topology with two hosts and five switches Scenario Setup the flow in proactive manner Ping from host1 to host2 Ping from all hosts to the other hosts 1 0 1 2 2 1 2 switch2 switch3 switch1 1 3 switch 5 2 switch4 POSTECH 1 0 2 3 host1 Route #1 host 2 Route #2 CSED702Y: Software Defined Networking 22/24 Testbed Jython App Java App RESTbased App Static Flow Pusher Not standardized yet, use proprietary APIs Northbound API Floodlight Controller Southbound API OVS Switch Host Host Host POSTECH Host OVS Switch Host OVS Switch OVS Switch OVS Switch Host Implement OpenFlow Protocol Host Host Host Host mininet CSED702Y: Software Defined Networking 23/24 DEMO Execution Procedures Procedures Add/load the newly implemented module (proactive flow insertion) Start Floodlight controller daemon # $FLOODLIGHT_PATH/floodlight.sh Initialize Mininet by specifying custom topology $ sudo mn --custom ./topo.py --topo mytopo --controller=remote, ip=127.0.0.1,port=6653 Initiate a ICMP request from host1 mininet> h1 ping h2 Initiate ICMP requests from all hosts mininet> pingall Topology script: http://dpnm.postech.ac.kr/cs702/2015/src/topo/topo.py Floodlight module: http://dpnm.postech.ac.kr/cs702/2015/src/floodlight/FlowModSample.java POSTECH CSED702Y: Software Defined Networking 24/24 Q&A POSTECH CSED702Y: Software Defined Networking 25/24 References OpenFlowJ-Loxi https://github.com/floodlight/loxigen/wiki/OpenFlowJ-Loxi Floodlight Official Site http://www.projectfloodlight.org/floodlight/ Floodlight Source https://github.com/floodlight/floodlight POSTECH CSED702Y: Software Defined Networking 26/24