sudo mn --topo single,4 --mac --switch ovsk --controller

advertisement
SDN App Development
Tutorial
November, 2013
Srini Seetharaman
Dhananjay Sampath
Anirudh Ramachandran
Deutsche Telekom
Innovation center
1
Contact us if you're interested to
contribute hands-on materials to sdnhub.org
Hands-on Tutorial
Background Info
3
Bootstrap
1. sdnhub.org/
2. Install VirtualBox or Vmware player or Vmware Fusion
3. Import the tutorial VM appliances available at:
– 64-bit: (Login: ubuntu, Passwd: ubuntu)
http://yuba.stanford.edu/~srini/OpenFlow_tutorial_64bit.ova
– 32-bit: (Login: ubuntu, Passwd: ubuntu)
http://yuba.stanford.edu/~srini/OpenFlow_tutorial_32bit.ova
4. Install X-Windows if you do not already have it
– Mac user: Install xquartz
– Windows user: Install xming
5. Start the VM, and “ssh -X” to its host-only IP address
– VirtualBox: Ensure the vboxnet0 interface is configured for “host-only”
• File->Preferences->Network and “Add host-only network” button with default settings.
4
Inside the Virtual Machine
• openvswitch: Virtual switch programmable using OpenFlow
• mininet: Network emulation platform
– $sudo mn --topo single,3 --mac --switch ovsk --controller remote
• wireshark: Graphical tool for viewing packets with OF protocol plug-in
– Start wireshark: $sudo wireshark
– Start capture packets going through interface “lo” and Decode as OFP
• ovs-ofctl: Command-line utility for checking switch status and
manually inserting flow entries.
– Check supported commands in manual: $ man ovs-ofctl
• Multiple OpenFlow controllers with sample apps prepackaged
– NOX, POX, Ryu, and OpenDayLight
5
A quick primer on OpenFlow
Match
L1: Tunnel ID, Switchport
L2: MAC addr, VLAN ID,
Ether type
L3: IPv4/IPv6 fields, ARP
Controller
Alice's Rule
OpenFlow
Switch
Alice's code
PC
L4: TCP, UDP
Action
•
•
•
•
Output to zero or
more ports
Encapsulate
Header rewriting
Send to controller
Alice'sSwitch
Rule
OpenFlow
Decision?
OpenFlow
Protocol
Alice'sSwitch
Rule
OpenFlow
OpenFlow offloads control intelligence to a remote software
6
Setup 1: Mininet-based Single Switch
OpenFlow Tutorial
3hosts-1switch
Topology
c0
Controller
port6633
loopback
(127.0.0.1:6633)
s1
OpenFlow Switch
s1-eth0
h1-eth0
s1-eth1
h2-eth0
loopback
(127.0.0.1:6634)
ovs-ofctl
(user space
process)
s1-eth2
h3-eth0
h1
h2
h3
10.0.0.1
10.0.0.2
10.0.0.3
virtual hosts
$ sudo mn --topo single,3 --mac --switch ovsk --controller remote
7
Setup 2: Linear topology with 2 switches
OpenFlow Tutorial
2hosts-2switch
Topology
$ sudo mn --topo linear --switch ovsk --controller remote
8
Setup 3: Web Server Farm in Mininet
$ sudo mn --topo single,4 --mac --switch ovsk --controller remote
SERVER SETUP:
– h2 python -m CGIHTTPServer &
– h3 python -m CGIHTTPServer &
– h4 python -m CGIHTTPServer &
ARP INIT FOR REACHABILITY:
– h1 arp -s 10.0.0.5 00:00:00:00:00:05
– h2 arp -s 10.0.0.5 00:00:00:00:00:05
– h3 arp -s 10.0.0.5 00:00:00:00:00:05
– h4 arp -s 10.0.0.5 00:00:00:00:00:05
PREP (AFTER STARTING CONTROLLER):
– h1 ping h2
– h3 ping h4
CLIENT REQUEST:
– h1 curl http://10.0.0.5:8000/cgi-bin/serverip.cgi
ovs-ofctl and wireshark workflow
• Before controller is started, execute the following
$ ovs-ofctl show tcp:127.0.0.1:6634
$ ovs-ofctl dump-flows tcp:127.0.0.1:6634
mininet> h1 ping h2
All ports of switch shown,
but no flows installed.
Ping fails because ARP
cannot go through
$ ovs-ofctl add-flow tcp:127.0.0.1:6634 in_port=1,actions=output:2
$ ovs-ofctl add-flow tcp:127.0.0.1:6634 in_port=2,actions=output:1
Ping works now!
mininet> h1 ping h2
• Start controller and check OF messages on wireshark (enabling OFP decode)
– Openflow messages exchanged between switch and controller:
openflow/include/openflow/openflow.h
/* Header on all OpenFlow packets. */
struct ofp_header {
uint8_t version; /* OFP_VERSION. */
uint8_t type;
/* one of the OFPT_ constants.*/
uint 16_t length; /*Length including this ofp_header. */
uint32_t xid;
/*Transaction id associated with this packet..*/
};
10
Top 3 features in most controllers
A. Event-driven model
– Each module registers listeners or call-back functions
– Example async events include PACKET_IN, PORT_STATUS,
FEATURE_REPLY, STATS_REPLY
B. Packet parsing capabilities
– When switch sends an OpenFlow message, module extracts
relevant information using standard procedures
C. switch.send(msg), where msg can be
– PACKET_OUT with buffer_id or fabricated packet
– FLOW_MOD with match rules and action taken
– FEATURE_REQUEST, STATS_REQUEST, BARRIER_REQUEST
11
Sample App 1: Hub
• App logic:
Hub
(3)
(4)
POX
(2)
(5)
OF Switch
(1)
– On init, register the appropriate packet_in
handlers or interfaces
– On packet_in,
• Extract full packet or its buffer id
• Generate packet_out msg with data or
buffer id of the received packet
• Set action = FLOOD
• Send packet_out msg to the switch that
generated the packet_in
Sample App 2: MAC-learning switch
• App logic:
– On init, create a dict to store MAC to switch port mapping
• self.mac_to_port = {}
– On packet_in,
• Parse packet to reveal src and dst MAC addr
• Map src_mac to the incoming port
– self.mac_to_port[dpid] = {}
– self.mac_to_port[dpid][src_mac] = in_port
• Lookup dst_mac in mac_to_port dict to find next hop
• If found, create flow_mod and send
• Else, flood like hub.
Sample App 3: Stateless Load-balancer
Mininet setup:
• $ sudo mn --topo single,4 --mac --switch ovsk --controller remote
• mininet> h1 curl http://10.0.0.5:8000/cgi-bin/serverip.cgi
Application logic:
• Set virtual_ip (10.0.0.5), virtual_mac (00…:05)
• Initialize list of servers and their MAC
• On packet_in for virtual_ip from “Y”,
– Pick server “X” in round-robin fashion
– Insert flow
– Proactively Insert reverse flow
• Match: Same as the incoming packet
• Match: Src (IP, MAC,
TCP_Port) = X, Dst = Y,
• Action (DST_ip -> 10.0.0.2):
– Rewrite dst_mac, dst_ip of packet to that of “X”
• Action:
– Forward to port towards “X”
– Rewrite src_mac, src_ip to that
of virtual_ip
– Forward to port towards “Y”
OpenDayLight controller
15
Controller Architecture
16
Hydrogen Release
VTN
Coordinator
Management
GUI/CLI
OpenStack
Neutron
DDoS
Protection
Network Applications
Orchestration & Services
OpenDaylight APIs (REST)
Base Network Service Functions
Topology
Mgr
Stats
Mgr
Switch
Mgr
Host
Tracker
Shortest
Path
Forwarding
Affinity
Service
Network
Config
LISP
Service
OpenStack Service
VTN
Manager
Controller Platform
DOVE Mgr
Service Abstraction Layer (SAL)
(plug-in mgr., capability abstractions, flow programming, inventory, …)
OpenFlow
1.0
1.3
OpenFlow Enabled
Devices
NETCONF
OVSDB
Open vSwitches
SNMP
BGP-LS
PCEP
LISP
Additional Virtual &
Physical Devices
Southbound Interfaces
& Protocol Plugins
Data Plane Elements
(Virtual Switches,
Physical Device
Interfaces)
VTN: Virtual Tenant Network
DOVE: Distributed Overlay Virtual Ethernet
DDoS: Distributed Denial Of Service
LISP: Locator/Identifier Separation Protocol
OVSDB: Open vSwitch DataBase Protocol
BGP: Border Gateway Protocol
17
PCEP: Path Computation Element Communication Protocol
SNMP: Simple Network Management Protocol
Java, Maven, OSGi, Interface
• Java allows cross-platform execution
• Maven allows easier building
• OSGi:
– Allows dynamically loading bundles
– Allows registering dependencies and services exported
– For exchanging information across bundles
• Java Interfaces are used for event listening,
specifications and forming patterns
18
Setup
(See Brent Salisbury’s tutorial on youtube.com)
INSTALL OPENDAYLIGHT (Dependency Maven, JDK1.7)
• git clone https://git.opendaylight.org/gerrit/p/controller.git
• mv controller opendaylight; cd opendaylight
• cd opendaylight/distribution/opendaylight/
• mvn clean install
• cd target/distribution.opendaylight-0.1.0-SNAPSHOTosgipackage/opendaylight/
• ./run.sh
IMPORT OPENDAYLIGHT TO ECLIPSE
• Install Eclipse with Maven Integration Version 1.2.0
• File => Import => Maven => Existing Maven Projects
• Browse ~/opendaylight/opendaylight/distribution/opendaylight
• In distribution.opendaylight, right click on opendaylight-assembleit.launch
19
and select “Run”. Then “Run” opendaylight-application.launch
OpenDayLight web interface
20
Writing a new application
Clone an existing module
(e.g., arphandler) in
Eclipse project explorer
Update set/unset
bindings in the module’s
class so as to access
other bundle objects
Implement the interface
functions to handle the
async events or use other
bundle objects to edit state
Include the new app in
opendaylight/distribution/ope
ndaylight/pom.xml and in the
Eclipse“Run Configurations”
List dependencies
imported and interfaces
implemented in the
module’s Activator.java
Add needed northbound
REST API and associate
with the web bundle
Update dependencies
and services exported
in the new bundle’s
pom.xml
Done
21
Useful Interfaces and Bundles
Bundle
Exported interface
Description
arphandler
IHostFinder
Component responsible for learning
about host location by handling ARP.
hosttracker
IfIptoHost
Track the location of the host
relatively to the SDN network.
ISwitchManager
Component holding the inventory
information for all the known nodes
(i.e., switches) in the controller.
switchmanager
topologymanager ITopologyManager
Component holding the whole
network graph.
usermanager
Component taking care of user
management.
IUserManager
statisticsmanager IStatisticsManager
Component in charge of using the SAL
ReadService to collect several
statistics from the SDN network.
22
Useful Interfaces and Bundles
Bundle
sal
sal
sal
sal
web
Exported interface
Description
Interface for retrieving the network
IReadService
node's flow/port/queue hardware
view
Topology methods provided by SAL
ITopologyService
toward the applications
Interface for
IFlowProgrammerSer
installing/modifying/removing flows
vice
on a network node
Data Packet Services SAL provides to
IDataPacketService
the applications
Component tracking the several
IDaylightWeb
pieces of the UI depending on
bundles installed on the system.
23
Life of a Packet
1. A packet arriving at Switch1 will
be sent to the appropriate
plugin managing the switch
(3)
2. The plugin will parse the packet,
generate an event for SAL
3. SAL will dispatch the packet to
the modules listening for
DataPacket
4. Module handles packet and
sends packet_out through
IDataPacketService
5. SAL dispatches the packet to the
modules listening for
DataPacket
6. OpenFlow message sent to
appropriate switch
Tutorial_L2_
forwarding
ARP Handler
IListenDataPacket
(3)
IListenDataPacket
(4)
IDataPacketService
Service Abstraction Layer (SAL)
IPluginOutDataPacketService
(2)
IPluginInDataPacketService
(5)
OpenFlow
protocol plugin
OpenFlowJ
(1)
OpenFlow
(6)
Switch1
Switch3
Switch2
24
Coding Time!
(See tutorial_L2_forwarding app)
A. Packet in event handling:
– public class TutorialL2Forwarding implements IListenDataPacket
• Indicates that the class will handle any packet_in events
– public PacketResult receiveDataPacket(RawPacket inPkt) { ... }
• Call-back function to implement in the class for receiving packets
B. Packet parsing
– Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
– byte[] srcMAC = ((Ethernet)formattedPak).getSourceMACAddress();
– long srcMAC_val = BitBufferHelper.toNumber(srcMAC);
C. Send message (packet_out or flow_mod) to switch
– RawPacket destPkt = new RawPacket(inPkt);
– destPkt.setOutgoingNodeConnector(p);
– this.dataPacketService.transmitDataPacket(destPkt);
25
POX controller
26
Intro to POX controller
General execution: $ ~/pox/pox.py <dir>.<name>
Example: $ ~/pox/pox.py forwarding.hub
Parses messages from switch
and throws following events
Packets parsed
by pox/lib
Example msg sent from
controller to switch
FlowRemoved
FeaturesReceived
ConnectionUp
FeaturesReceived
RawStatsReply
PortStatus
PacketIn
BarrierIn
SwitchDescReceived
FlowStatsReceived
AggregateFlowStatsReceived
TableStatsReceived
PortStatsReceived
QueueStatsReceived
arp
dhcp
dns
eapol
eap
ethernet
icmp
igmp
ipv4
llc
lldp
mpls
rip
tcp
udp
vlan
ofp_packet_out
header:
version: 1
type: 13
length: 24
xid: 13
buffer_id: 272
in_port: 65535
actions_len: 1
actions:
type: 0
len: 8
port: 65531
max_len: 65535
Application 1: Hub
(inspect file pox/pox/misc/of_tutorial.py)
Hub
(3)
(4)
POX
(2)
(5)
OF Switch
(1)
(B)
(6)
(C)
(A)
Application 2: MAC-learning switch
(convert pox/pox/misc/of_tutorial.py to L2 switch)
• Build on your own with this logic:
– On init, create a dict to store MAC to switch port mapping
• self.mac_to_port = {}
– On packet_in,
• Parse packet to reveal src and dst MAC addr
• Map src_mac to the incoming port
– self.mac_to_port[dpid] = {}
– self.mac_to_port[dpid][src_mac] = in_port
• Lookup dst_mac in mac_to_port dict to find next hop
• If found, create flow_mod and send
msg = of.ofp_flow_mod()
• Else, flood like hub.
msg.match = of.ofp_match.from_packet(packet)
msg.buffer_id = event.ofp.buffer_id
• Execute:
pox/pox.py misc.of_tutorial
action = of.ofp_action_output(port = out_port)
msg.actions.append(action)
29
self.connection.send(msg)
App 3: Stateless Load-balancer
• Set virtual_ip (10.0.0.5), virtual_mac (00…:05)
• Initialize list of servers and their MAC
• On packet_in for virtual_ip from “Y”,
– Pick server “X” in round-robin fashion
– Insert flow
• Match: Same as the incoming packet
• Action (DST_ip -> 10.0.0.2):
– Rewrite dst_mac, dst_ip of packet to that of “X”
– Forward to port towards “X”
– Proactively Insert reverse flow
• Match: Src (IP, MAC, TCP_Port) = X, Dst = Y,
• Action:
– Rewrite src_mac, src_ip to that of virtual_ip
– Forward to port towards “Y”
Ryu controller
31
Intro to RYU: OpenFlow Controller
Topology
Viewer
Firewall
Statistics
simple_
switch
ofctl_
rest
app
quantum
plugin
lib
base
app_manager
RYU Controller
1.0
1.2
1.3
handler
dpset
event
controller
ofp_event
ofp_handler
controller
OF Switch
OF Switch
of_parser
–
–
Provides interface for control and state and
generates events
Communicates using message passing
lib
ofproto
OF Switch
Components:
of_header
Libraries:
– Functions called by components
– Ex: OF-Config, Netflow, sFlow,
Netconf, OVSDB
32
Application 1: Hub
ryu-manager --verbose ryu/ryu/app/tutorial_l2_hub.py
Hub
(3)
(4)
RYU
(2)
(5)
(A)
OF Switch
(1)
(6)
(B)
(C)
Application 2: MAC-learning switch
• Build on your own with this logic:
– On init, create a dict to store MAC to switch port mapping
• self.mac_to_port = {}
– On packet_in,
• Parse packet to reveal src and dst MAC addr
• Map src_mac to the incoming port
– self.mac_to_port[dpid] = {}
– self.mac_to_port[dpid][src_mac] = in_port
• Lookup dst_mac in mac_to_port dict to find next hop
• If found, create flow_mod and send
• Else, flood like hub.
Pssst… solution in
34
tutorial_l2_switch.py
The End
35
Download