blob: 1526cee4beb016278a902d9b7b78cdc894e59d7a [file] [log] [blame]
Dan Talayco34089522010-02-07 23:07:41 -08001"""
2OpenFlow Test Framework
3
4Controller class
5
6Provide the interface to the control channel to the switch under test.
7
8Class inherits from thread so as to run in background allowing
9asynchronous callbacks (if needed, not required). Also supports
10polling.
11
12The controller thread maintains a queue. Incoming messages that
13are not handled by a callback function are placed in this queue for
14poll calls.
15
16Callbacks and polling support specifying the message type
17
18@todo Support transaction semantics via xid
19"""
20
21import sys
22sys.path.append("../ofmsg")
23import os
24import socket
25import time
26import promisc
27from threading import Thread
28from threading import Lock
29from message import *
30
31class Controller(Thread):
32 """
33 Class abstracting the control interface to the switch.
34
35 For receiving messages, two mechanism will be implemented. First,
36 query the interface with poll. Second, register to have a
37 function called by message type. The callback is passed the
38 message type as well as the raw packet (or message object)
39
40 One of the main purposes of this object is to translate between network
41 and host byte order. 'Above' this object, things should be in host
42 byte order.
43 """
44
45 def __init__(port=6633, passive=1):
46 if (passive):
47 # FIXME: add error handling
48 self.sock = open_ctrlsocket()
49 self.clientsock, self.clientaddr = self.sock.accept()
50 else:
51 print "Error in controller init: Active cxn not supported"
52
53 def register(self, msg_type, handler):
54 """
55 Register a callback to receive a specific message type.
56
57 Only one handler may be registered for a given message type.
58 @param msg_type The type of message to receive. May be DEFAULT
59 for all non-handled packets.
60 @param handler The function to call when a message of the given
61 type is received.
62 """
63 print "Controller message handler registration not supported"
64
65 def poll(self, exp_msg=None, timeout=None):
66 """
67 Wait for the next OF message received from the switch.
68
69 @param exp_msg If set, return only when this type of message
70 is received.
71
72 @param timeout If set, return E_TIMEOUT if mesage is not
73 received in this time. If set to 0, will not block.
74
75 @retval A triple (msg_type, msg, data) where msg_type is the OpenFlow
76 message type value OFPT_xxx, msg is a message object (from a
77 SWIG generated class) appropriate to the message type and data is
78 a string of any additional information following the
79 normal message. Note that
80 many messages do not have classes so ofp_hello is returned which
81 simply has the header.
82 The data members in the message are in host endian order.
83 If a timeout (or other error) occurs, None is returned
84 """
85 while 1:
86 okay, pkt = rcv_data_from_socket(self.clientsoc, timeout)
87 if not okay or not pkt:
88 # FIXME: Check for error
89 return None, None
90 # Convert msg to the proper OpenFlow message object
91 msg_type, msg = ofpkt.pkt_to_msg(pkt)
92 print "DEBUG: Got msg type %d of len %d" % (msg_type, len(msg))
93
94 if not exp_msg or (exp_msg and (hdr.type == exp_msg)):
95 return msg_type, msg
96
97 def flow_install(self, flow):
98 """
99 Install the flow indicated through the control interface
100 TBD: We may just use message_send below with ofp_flow_mod objects
101 @param flow The ofp_flow_mod object to install
102 """
103
104 def message_send(self, msg):
105 """
106 Send the message to the switch
107 @param msg An OpenFlow message object (from a SWIG generated
108 class) to be forwarded to the switch. The data members of the
109 object must be in host endian order when pased to message_send.
110 """
111
112 def kill(self):
113 self.clientsock.close()