Frenetic-Pyretic - CSE Labs User Home Pages
Download
Report
Transcript Frenetic-Pyretic - CSE Labs User Home Pages
Programming Abstractions &
Languages for SDN:
Frenetic & Pyretic
Network Programming is Hard
• Programming network equipment is hard
– Complex software by equipment vendors
– Complex configuration by network administrators
• Expensive and error prone
– Network outages and security vulnerabilities
– Slow introduction of new features
• SDN gives us a chance to get this right!
– Rethink abstractions for network programming
2
Programming Software Defined Networks
• OpenFlow already helps a lot
Controller
– Network-wide view at controller
– Direct control over data plane
• The APIs do not make it easy
– Limited controller visibility
– No support for composition
– Asynchronous events
Switches
3
Example Network
SDN Switch
Servers
w/ labeled ports
Internet
1
A
2
3
B
4
A Simple OpenFlow Program
2:dstip=A
1:*
2:dstip=B
OpenFlow
Priority
Program
Counters for each rule
Route:
IP/fwd
- #bytes,
#packets
1
dstip!=A
dstip!=B
-> fwd(2)
-> fwd(1)
-> fwd(3)
Pattern
Action
dstip=A
A
2
3
dstip=B
B
5
One API, Many Uses
1:dstmac=A -> fwd(2)
1:dstmac=B -> fwd(3)
2:*
-> fwd(1)
Priority
Ordered
Pattern
Action
Switch: MAC/fwd
1
A
2
3
B
6
One API, Many Uses
srcip=0*,dstip=P -> mod(dstip=A)
srcip=1*,dstip=P -> mod(dstip=B)
Pattern
Action
Load Balancer: IP/mod
1
A
2
3
B
7
Composition: Simple Repeater
Simple Repeater
def switch_join(switch):
# Repeat Port 1 to Port 2
p1 = {in_port:1}
a1 = [forward(2)]
install(switch, p1, DEFAULT, a1)
# Repeat Port 2 to Port 1
p2 = {in_port:2}
a2 = [forward(1)]
install(switch, p2, DEFAULT, a2)
Controller
1
2
When a switch joins the network, install two forwarding rules.
Composition: Web Traffic Monitor
Monitor “port 80” traffic
def switch_join(switch)):
# Web traffic from Internet
p = {inport:2,tp_src:80}
install(switch, p, DEFAULT, [])
query_stats(switch, p)
1
def stats_in(switch, p, bytes, …)
print bytes
sleep(30)
query_stats(switch, p)
2
Web traffic
When a switch joins the network, install one monitoring rule.
9
Composition: Repeater + Monitor
Repeater + Monitor
def switch_join(switch):
pat1 = {inport:1}
pat2 = {inport:2}
pat2web = {in_port:2, tp_src:80}
install(switch, pat1, DEFAULT, None, [forward(2)])
install(switch, pat2web, HIGH, None, [forward(1)])
install(switch, pat2, DEFAULT, None, [forward(1)])
query_stats(switch, pat2web)
def stats_in(switch, xid, pattern, packets, bytes):
print bytes
sleep(30)
query_stats(switch, pattern)
Must think about both tasks at the same time.
OpenFlow Programming Stack
*First Order Approximation
App
Monolithic Controller
Control Flow, Data Structures, etc.
Runtime
Switch API
Switches
Controller Platform
(OpenFlow)
Limited Controller Visibility
• Example: MAC-learning switch
– Learn about new source MAC addresses
– Forward to known destination MAC addresses
• Controller program is more complex than it seems
– Cannot install destination-based forwarding rules
– … without keeping controller from learning new
sources
2
3
1
1 sends to 2 learn 1, install
3 sends to 1 never learn 3
1 sends to 3 always floods
• Solution: rules on <inport, src MAC, dst MAC>
Must think about reading and writing at the same time.
12
Asynchrony: Switch-Controller Delays
• Common OpenFlow programming idiom
– First packet of a flow goes to the controller
– Controller installs rules
to handle remaining packets
Controller
packets
• What if more packets arrive before rules installed?
– Multiple packets of a flow reach the controller
• What if rules along a path installed out of order?
– Packets reach intermediate switch before rules do
Must think about all possible event orderings.
13
Wouldn’t It Be Nice if You Could…
• Separate reading from writing
– Reading: specify queries on network state
– Writing: specify forwarding policies
• Compose multiple tasks
– Write each task once, and combine with
others
• Prevent race conditions
– Automatically apply forwarding policy to extra
packets
This is what Frenetic does!
14
Programming SDN w/ OpenFlow
• The Good
– Network-wide visibility
– Direct control over the switches
– Simple data-plane abstraction
• The Bad
– Low-level programming interface
– Functionality tied to hardware
– Explicit resource control
• The Ugly
– Non-modular, non-compositional
– Challenging distributed programming
Images by Billy Perkins
15
Today: OpenDaylight, POX, etc.
~ Registers, adders, etc.
App
~ Assembly language
Monolithic Controller
Data and Control Flow
Runtime
Switch API
Switches
Controller Platform
(OpenFlow)
Programming Software Defined Networks
• OpenFlow already helps a lot
Controller
– Network-wide view at controller
– Direct control over data plane
• The APIs do not make it easy
– Limited controller visibility
– No support for composition
– Asynchronous events
Switches
• Frenetic simplifies the programmer’s life
– A language that raises the level of abstraction
– A run-time system that handles the gory details
17
Frenetic Language
• Reads: query network state
– Queries can see any packets
– Queries do not affect forwarding
– Language designed to keep packets in data plane
• Writes: specify a forwarding policy
– Policy separate from mechanism for installing rules
– Streams of packets, topology changes, statistics, etc.
– Library to transform, split, merge, and filter streams
• Current implementation
– A collection of Python libraries on top of NOX
• http://www.frenetic-lang.org/
16
Example: Repeater + Monitor
# Static repeating between ports 1 and 2
def repeater():
rules=[Rule(inport:1, [forward(2)]),
Rule(inport:2, [forward(1)])]
register(rules)
Repeater
# Monitoring Web traffic
def web_monitor():
q = (Select(bytes) *
Where(inport:2 & tp_src:80) *
Every(30))
q >> Print()
Repeater + Monitor
Monitor
# Composition of two separate modules
def main():
repeater()
web_monitor()
19
Frenetic System Overview
• High-level language
– Query language
– Composition of
forwarding policies
• Run-time system
– Interprets queries
and policies
– Installs rules and
tracks statistics
– Handles asynchronous
events
20
Frenetic Run-Time System
• Rule granularity
– Microflow: exact header match
– Wildcard: allow “don’t care” fields
• Rule installation
– Reactive: first packet goes to controller
– Proactive: rules pushed to the switches
• Frenetic run-time system
– Version 1.0: reactive microflow rules [ICFP’11]
– Version 2.0: proactive wildcard rules [POPL’12]
• Get it right once, and free the programmer!
21
Evaluation
• Example applications
– Routing: spanning tree, shortest path
– Discovery: DHCP and ARP servers
– Load balancing: Web requests, memcached
queries
– Security: network scan detector, DDoS defenses
• Performance metrics
– Language: lines of code in applications
• Much shorter programs, especially when composing
– Run-time system: overhead on the controller
• Frenetic 1.0: competitive with programs running on NOX
• Frenetic 2.0: fewer packets to the controller
22
Conclusions
• Frenetic foundation
– Separating reading from writing
– Explicit query subscription and policy registration
– Operators that transform heterogeneous streams
• Makes programming easier
–
–
–
–
Higher-level patterns
Policy decoupled from mechanism
Composition of modules
Prevention of race conditions
• And makes new abstractions easier to build!
23
Modular SDN
Programming w/ Pyretic
Pyretic: Language & Platform
Monitor
Apps
Programmer API
Runtime
Switch API
Switches
Route
FW
LB
(Pyretic)
Pyretic Controller Platform
(OpenFlow)
{Frene,Pyre}tic?
• Frenetic is a SDN umbrella project focused on
– Language design
– Compiler implementation
• Princeton/Cornell Team Produced:
– Great (northbound) abstraction for programmers
– Techniques for implementing these abstractions
• Two current members of the family
– Pyretic: embedded & implemented in Python
– Frenetic Ocaml: embedded & implemented in OCaml
26
Pyretic or Frenetic Ocaml?
Pyretic
Frenetic
Ocaml
Target
Community
Systems and
Networking
Programming
Languages
Primary Dev.
Location
Princeton
Cornell
Host Language
Python
OCaml
27
Pyretic Philosophy
• Provide high-level programming
abstractions
• Based on state-of-the-art PL techniques
• Implement w/ state-of-the-art systems tech
• Package for the networking community
• Focus on real world utility and cutting edge
features
28
Open Source and
Programmer-Friendly
• Embedded and Implemented in Python
– Rich support for dynamic policies
– Familiar constructs and environment
– Python library / module system
• Default 3-clause BSD license
• Active & growing developer community
– GitHub repository & wiki
– Video tutorials and documentation
Basic Programmer Wishlist
• Encode policy concisely
• Write portable code
• Specify traffic of interest
• Compose code from independent modules
• Query network state
• Modify policy dynamically
30
Pyretic =
* Our goal
31
Pyretic Provides
Feature
Example
Concise policy
encoding
Boolean predicates
• flood()
• ~(match(dstip=10.0.0.1) |
match(srcip=10.0.0.1) )
Composition operators • (load_balance + monitor) >>
route
Virtual header fields
• match(switch)
• modify(class=‘staff’)
Query Policies
• count_packets()
32
Pyretic: Key Abstractions
• Abstract Packet Model
– packet flows as a dictionary mapping field names to values
– (nested) virtual header fields
– located packet: set multi-sets
• Network Object Model: virtual switches & ports
– “big switch”: one-to-many
– “virtual network”: many-to-one
33
Pyretic: Policy Language
• Composition: parallel and sequential composition
operators: “|” and “>>”
• High-level Policy Functions
–
•
•
•
–
Static Policies:
primitive actions
Predicates
query
Dynamic Application
def main():
P.when(…)
34
Policy in OpenFlow
• Defining “policy” is complicated
– All rules in all switches
– Packet-in handlers
– Polling of counters
• Programming “policy” is error-prone
– Duplication between rules and handlers
– Frequent changes in policy (e.g., flowmods)
– Policy changes affect packets in flight
35
From Rules to a Policy Function
• Located packet
– A packet and its location (switch and port)
• Policy function
– From located packet to set of located packets
• Examples
– Original packet: identity
– Drop the packet: drop
– Modified header: modify(f=v)
– New location: fwd(a)
36
Why a set? Consider flood
To flood every packet:
from pyretic.lib.corelib import *
def main():
return flood()
37
No worrying about:
•
•
•
•
Writing a separate handler for controller
Constructing and sending OpenFlow rules
Keeping track of each switch
Whether all switches supports the
OpenFlow “flood” action (portability!)
38
Programmer Wishlist
• Encode policy concisely
• Specify traffic of interest
• Write portable code
• Compose code from independent modules
• Query network state
• Modify policy dynamically
39
From Bit Patterns to Predicates
• OpenFlow: bit patterns
– No direct way to specify dstip!=10.0.0.1
– Requires two prioritized bitmatches
• Higher priority: dstip=10.0.0.1
• Lower priority: *
• Pyretic: boolean predicates
– Combined with &, |, and ~
– E.g., ~match(dstip=10.0.0.1)
40
Example: Access Control
Block host 10.0.0.3
def access_control():
return ~(match(srcip=‘10.0.0.3’) |
match(dstip=‘10.0.0.3’) )
41
Programmer Wishlist
• Encode policy concisely
• Write portable code
• Specify traffic of interest
• Compose code from independent modules
• Query network state
• Modify policy dynamically
42
OpenFlow Packets
• Location specific code needs both
– The packet
– The OF packet_in message*
• Tagging packets requires choosing
– Header field (e.g., VLAN, MPLS, TOS bits)
– Set of values
Neither concise nor portable
* https://github.com/noxrepo/pox/tree/betta/pox/misc/of_tutorial.py
43
Pyretic Virtual Header Fields
• Unified abstraction
– Real headers: dstip, srcport, …
– Packet location: switch and port
– User-defined: e.g., traffic_class
• Simple operations, concise syntax
– Match: match(f=v)
– Modify: modify(f=v)
• Example
– match(switch=A) & match(dstip=‘1.0.0.3’)
44
Runtime Handles Implementation
• Compiler chooses
– What set of header bits to use
– What each value means
• Conceptual – no tying to particular mech.
• Portable – different hw, other modules
• Efficient
– Don’t need same vlan value network-wide
– Sometimes tags will ‘factor out’
45
Programmer Wishlist
• Encode policy concisely
• Write portable code
• Specify traffic of interest
• Compose code from independent modules
• Query network state
• Modify policy dynamically
46
Recall OpenFlow
47
Balance then Route (in Sequence)
srcip=0*,dstip=P -> mod(dstip=A)
srcip=1*,dstip=P -> mod(dstip=B)
dstip=A
dstip=B
*
-> fwd(2)
-> fwd(3)
-> fwd(1)
Combined Rules?
(only one match)
srcip=0*,dstip=P
dstip=A
srcip=1*,dstip=P
dstip=B
*
dstip=A
->
->
->
->
mod(dstip=A)
fwd(2)
mod(dstip=B)
fwd(3)
fwd(1)
fwd(2)
dstip=B
srcip=0*,dstip=P
*
srcip=1*,dstip=P
->
->
fwd(3)
mod(dstip=A)
fwd(1)
mod(dstip=B)
Balances
Forwards w/o
Forwarding!
Balancing!
48
Route and Monitor (in Parallel)
Monitor
Route
dstip = 10.0.0.2 fwd(2)
dstip = 10.0.0.3 fwd(3)
*
fwd(1)
srcip = 5.6.7.8 count
IP = 10.0.0.2
1
2
3
IP = 10.0.0.3
srcip = 5.6.7.8
dstip
10.0.0.2 count
fwd(2)
dstip
10.0.0.3
dstip =
= 10.0.0.2
fwd(3)
fwd(2)
Counts butbut
Forwards
Combined
rules installed
on switch?
*
dstip = 10.0.0.3
fwd(1)
fwd(3)
forward
doesn’t count
*
srcip
= 5.6.7.8
count
fwd(1)
49
Requires a Cross Product
[ICFP’11, POPL’12]
Monitor
Route
dstip = 10.0.0.2 fwd(2)
dstip = 10.0.0.3 fwd(3)
*
fwd(1)
srcip = 5.6.7.8 count
IP = 10.0.0.2
1
srcip = 5.6.7.8 , dstip
srcip = 5.6.7.8 , dstip
srcip = 5.6.7.8
dstip
dstip
*
2
3
= 10.0.0.2
= 10.0.0.3
= 10.0.0.2
= 10.0.0.3
IP = 10.0.0.3
fwd(2) , count
fwd(3) , count
fwd(1) , count
fwd(2)
fwd(3)
fwd(1)
50
Policy Functions Enable
Compositional Operators
Parallel ‘+’: Do both C1 and C2 simultaneously
Sequential ‘>>’:
First do C1 and then do C2
51
Example: Sequential Composition
To first apply access control and then flood
access_control() >> flood()
• Two totally independent policies
• Combined w/o any change to either
52
Easily Define New Policies
E.g., the ‘if_’ policy
def if_(F,P1,P2):
return (F >> P1) + (~F >> P2)
53
Or flood
xfwd(a) = ~match(inport=a) >> fwd(a)
flood =
parallel([match(switch=sw) >>
parallel(map(xfwd,ports))
for sw,ports in MST])
• Portable: compiler chooses whether to
implement using OpenFlow ‘flood’ or ‘forward’
54
Programmer Wishlist
• Encode policy concisely
• Write portable code
• Specify traffic of interest
• Compose code from independent modules
• Query network state
• Modify policy dynamically
55
Querying In OpenFlow
• Pre-install rules at the needed granularity
(so byte/packet counters are available)
• Issue queries to poll these counters
• Parse the responses when they arrive
• Combine counter values from multiple rules
• Keep track of any packets sent to controller
56
Queries in Pyretic
• Just a special type of policy
• Forwarding to a “bucket”
– q = packets(limit=1,group_by=['srcip'])
• Used like any other (>>, +)
• w/ Callback function registration
– q.register_callback(printer)
57
Example: Monitor
q = count_bytes(interval=1)
q.register_callback(printer)
monitor = match(srcip='10.0.0.1') >> q
58
Query Policy Library
Syntax
Side Effect
packets(
limit=n,
group_by=[f1,f2,…])
count_packets(
interval=t,
group_by=[f1,f2,…])
callback on every packet
received for up to n packets
identical on fields f1,f2,...
count every packet received
callback every t seconds
providing count for each group
count_bytes(
count bytes received
interval=t,
callback every t seconds
group_by=[f1,f2,…]) providing count for each group
59
Recall OpenFlow Toy
Balance Route Monitor
60
In Pyretic
0*
1
1*
balance =
(match(srcip=0*,dstip=P) >> modify(dstip=A)) +
(match(srcip=1*,dstip=P) >> modify(dstip=B)) +
(~match(
dstip=P) >> identity)
route =
(match(dstip=A) >> fwd(2)) +
(match(dstip=B) >> fwd(3)) +
(~(match(dstip=A) | match(dstip=B)) >> fwd(1))
b = count_bytes(interval=1)
b.register_callback(print)
monitor = match(srcip=X) >> b
mlb = (balance >> route) + monitor
61
2
3
A
B
Compared to
install_flowmod(5,srcip=X & dstip=P,[mod(dstip=A), fwd(2)])
install_flowmod(4,srcip=0* & dstip=P,[mod(dstip=A), fwd(2)])
install_flowmod(4,srcip=1* & dstip=P,[mod(dstip=B), fwd(3)])
install_flowmod(4,srcip=X & dstip=A ,[
fwd(2)])
install_flowmod(4,srcip=X & dstip=B,[
fwd(3)])
install_flowmod(3,
dstip=A,[
fwd(2)])
install_flowmod(3,
dstip=B,[
fwd(3)])
install_flowmod(2,srcip=X
,[
fwd(1)])
install_flowmod(1,*
,[
fwd(3)])
62
Programmer Wishlist
• Encode policy concisely
• Write portable code
• Specify traffic of interest
• Compose code from independent modules
• Query network state
• Modify policy dynamically
63
Functions Support Dynamism
•
•
•
•
Dynamic policies are also functions of time
Value at current moment in self.policy
Reassigning updates dynamic policy
Can be driven by queries
64
Example: MAC-Learning
New Type of Dynamic Policy
First packet with unique
class learn(DynamicPolicy): srcmac, switch
def init(self):
q = packets(limit=1,[’srcmac’,’switch’])
q.register_callback(update)
Defined momentarily
self.policy = flood() + q
and query
policy unchanged
Update current val
to flood Otherwise,
Initialize current
def update(self,pkt):
value of time series
self.policy = if_(match(dstmac=pkt[’srcmac’],
If newly learned MAC
switch=pkt[’switch’]),
Forward directly to
fwd(pkt[’inport’]),
65
learned port
Dynamic Policies
Can also be driven by external events!
66
Example: UI Firewall
def __init__(self):
print "initializing firewall"
self.firewall = {}
...
self.ui = threading.Thread(
target=self.ui_loop)
self.ui.daemon = True
self.ui.start()
def AddRule (self, mac1, mac2):
if (mac2,mac1) in self.firewall:
return
self.firewall[(mac1,mac2)]=True
self.update_policy()
def update_policy (self):
self.policy = ~union([(match(srcmac=mac1) &
match(dstmac=mac2)) |
(match(dstmac=mac1) &
match(srcmac=mac2))
for (mac1,mac2)
in self.firewall.keys()])
67
Programmer Wishlist
• Encode policy concisely
• Write portable code
• Specify traffic of interest
• Compose code from independent modules
• Query network state
• Modify policy dynamically
68
Pyretic Platform
69
Platform Architecture
Controller
Process 1
Main
App 1
App 2
Pyretic Runtime
Pyretic Backend
Serialized Messages (TCP
socket)
OF Controller Client
Process 2
OF Controller Platform
OpenFlow Messages
Switches
Modes of Operation
• Interpreted (on controller)
– Fallback when rules haven’t been installed
– Good for debugging
• Reactive
– Rules installed in response to packets seen
– Fallback when proactive isn’t feasible
– Various flavors and optimizations
• Proactive
– Analyze policy and push rules
– Computation can be an issue
– Currently nuclear and simple incremental
71
Runtime Architecture (in Progress)
Interpreter, QoS, ACL, Topo
HA &
Query
Scale Out Mgmt
Classifier Generation
Incrementalization
Consistent Update
Flow Table Cache Management
Also in Progress
• New features
– Policy access controls
– QoS operators
– Enhanced querying library
• Applications
– Incorporation of RADIUS & DHCP services
– Wide-area traffic-management solutions for
ISPs at SDN-enabled Internet Exchange
Points.
73
Test It Out Yourself
www.frenetic-lang.org/pyretic
74
HW Middleware QA Ops
• Hard and soft-switches
• WAN, Enterprise, DC, Home
– Network processors
• Wireless & Optical
– Reconfigurable pipelines
• Systems Challenges
– Hardware accelerated features
– Scalability
– Programmable x86 dataplane
– Fault-tolerance
• APIs and Languages
– Consistency
• Traffic Monitoring/Sampling/QoS
– Upgradability
• Testing, Debugging, Verification
– Performance
• Experimentation & Testbeds
• Security
• Integration & Orchestration
• Virtualization
– End hosts
– of network
– Legacy switches
– of services
– Middleboxes
– of address space
– Network Services
75
Where Pyretic Fits
• Hard and soft-switches
• WAN, Enterprise, DC, Home
– Network processors
• Wireless & Optical
– Reconfigurable pipelines
• Systems Challenges
– Hardware accelerated features
– Scalability
– Programmable x86 dataplane
– Fault-tolerance
• APIs and Languages
– Consistency
• Traffic Monitoring/Sampling/QoS
– Upgradability
• Testing, Debugging, Verification
– Performance
• Experimentation & Testbeds
• Security
• Integration & Orchestration
• Virtualization
– End hosts
– of network
– Legacy switches
– of services
– Middleboxes
– of address space
– Network Services
76