Skip to content

Instantly share code, notes, and snippets.

@wh5a
Created July 30, 2013 16:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wh5a/6114586 to your computer and use it in GitHub Desktop.
Save wh5a/6114586 to your computer and use it in GitHub Desktop.
SDN Module 6 Pyresonance Load Balancer
'''
Coursera:
- Software Defined Networking (SDN) course
-- Module 7 Programming Assignment
Professor: Nick Feamster
Teaching Assistant: Muhammad Shahbaz
'''
################################################################################
# Resonance Project #
# Resonance implemented with Pyretic platform #
# author: Hyojoon Kim (joonk@gatech.edu) #
# author: Nick Feamster (feamster@cc.gatech.edu) #
################################################################################
from pyretic.lib.corelib import *
from pyretic.lib.std import *
from pyretic.examples.load_balancer import *
class ResonancePolicy():
state_policy_map = {}
def __init__(self):
self.state_policy_map['default'] = self.default_policy
def get_policy(self, state):
if self.state_policy_map.has_key(state):
return self.state_policy_map[state]
else:
return self.default_policy
""" Default state policy """
def default_policy(self):
return drop
class LBPolicy(ResonancePolicy):
def __init__(self, fsm):
self.fsm = fsm
def portA_policy(self):
public_ip = IP('10.0.0.100')
client_ips = [IP('10.0.0.1')]
repeating_R = [IP('10.0.0.2')]
# This will replace the incoming packet[src=10.0.0.1, dst=10.0.0.100] to packet[src=10.0.0.1, dst=10.0.0.2] and
# and packet[src=10.0.0.1, dst=10.0.0.2] back to packet[src=10.0.0.1, dst=10.0.0.100]
return rewrite(zip(client_ips, repeating_R), public_ip)
def portB_policy(self):
public_ip = IP('10.0.0.100')
client_ips = [IP('10.0.0.1')]
repeating_R = [IP('10.0.0.3')]
# This will replace the incoming packet[src=10.0.0.1, dst=10.0.0.100] to packet[src=10.0.0.1, dst=10.0.0.3] and
# and packet[src=10.0.0.1, dst=10.0.0.3] back to packet[src=10.0.0.1, dst=10.0.0.100]
return rewrite(zip(client_ips, repeating_R), public_ip)
def default_policy(self):
# Add the logic to return the right policy (i.e., portA_policy or portB_policy
# based on the state of the FSMs)
#hint:
# 1. get the list of hosts in portA state
aHosts = self.fsm.get_portA_hosts()
# 2. match the incoming packet's source and destination ip against that list of hosts (using pyretic predicates i.e., "match", "modify", and "if_" etc)
matchAHosts = parallel([match(srcip=aHost) for aHost in aHosts]) + parallel([match(dstip=aHost) for aHost in aHosts])
# 3. if there is a match apply portA policy else apply portB policy
return if_(matchAHosts, self.portA_policy(), self.portB_policy())
# return (matchAHosts >> self.portA_policy()) + (~matchAHosts >> self.portB_policy())
'''
Coursera:
- Software Defined Networking (SDN) course
-- Module 3 Programming Assignment
Professor: Nick Feamster
Teaching Assistant: Muhammad Shahbaz
'''
################################################################################
# Resonance Project #
# Resonance implemented with Pyretic platform #
# author: Hyojoon Kim (joonk@gatech.edu) #
# author: Nick Feamster (feamster@cc.gatech.edu) #
################################################################################
from pyretic.lib.corelib import *
from pyretic.lib.std import *
import json
from multiprocessing import Process, Manager
DEBUG = True
EVENT_TYPE_LB = 0
class ResonanceStateMachine():
def __init__(self):
manager = Manager()
self.flow_state_map = manager.dict()
self.flow_state_map.clear()
return
def transition_callback(self, cb, arg):
self.cb = cb
self.cbarg = arg
def parse_json(self, msg):
json_msg = json.loads(msg)
event_msg = json_msg['event']
state = event_msg['data']
msgtype = event_msg['event_type']
host = state['data']
next_state = state['value']
return (msgtype, host, next_state)
def handleMessage(self, msg, queue):
msgtype, host, next_state = self.parse_json(msg)
if DEBUG == True:
print "HANDLE", next_state, host
# In the parent class, we just do the transition.
# We don't type check the message type
self.state_transition(next_state, host, queue)
def check_state(self, host):
host_str = str(host)
if self.flow_state_map.has_key(host_str):
state = self.flow_state_map[host_str]
else:
state = 'default'
if DEBUG == True:
print "check_state", host_str, state
return state
def get_hosts_in_state(self, state):
hosts = []
for host in self.flow_state_map.keys():
if (self.flow_state_map[host] == state):
hosts.append(host)
return hosts
def state_transition(self, next_state, host, queue, previous_state=None):
state = self.check_state(host)
if previous_state is not None:
if state != previous_state:
print 'Given previous state is incorrect! Do nothing.'
return
else:
print "state_transition ->", str(host), next_state
queue.put('transition')
self.flow_state_map[str(host)] = next_state
if DEBUG == True:
print "CURRENT STATES: ", self.flow_state_map
# --------- Update the code below ------------
class LBStateMachine(ResonanceStateMachine):
def handleMessage(self, msg, queue):
msgtype, host, next_state = self.parse_json(msg)
# Add the state transition logic
# hint: use the state_transition function
if msgtype == EVENT_TYPE_LB:
self.state_transition(next_state, host, queue)
def get_portA_hosts(self):
return self.get_hosts_in_state('portA')
def get_portB_hosts(self):
return self.get_hosts_in_state('portB')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment