blob: a0519eaecf7bb7a2f45f95b6a9cb646c102c7584 [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
Dan Talaycoe37999f2010-02-09 15:27:12 -080022sys.path.append("../protocol")
Dan Talayco34089522010-02-07 23:07:41 -080023import os
24import socket
25import time
26import promisc
27from threading import Thread
28from threading import Lock
29from message import *
Dan Talaycoe37999f2010-02-09 15:27:12 -080030from parse import *
31from netutils import *
Dan Talayco34089522010-02-07 23:07:41 -080032
33class Controller(Thread):
34 """
35 Class abstracting the control interface to the switch.
36
37 For receiving messages, two mechanism will be implemented. First,
38 query the interface with poll. Second, register to have a
39 function called by message type. The callback is passed the
40 message type as well as the raw packet (or message object)
41
42 One of the main purposes of this object is to translate between network
43 and host byte order. 'Above' this object, things should be in host
44 byte order.
45 """
46
Dan Talaycoe37999f2010-02-09 15:27:12 -080047 def __init__(host=HOST_DEFAULT, port=PORT_DEFAULT, passive=1):
Dan Talayco34089522010-02-07 23:07:41 -080048 if (passive):
49 # FIXME: add error handling
Dan Talaycoe37999f2010-02-09 15:27:12 -080050 self.sock = open_ctrlsocket(host, port)
Dan Talayco34089522010-02-07 23:07:41 -080051 self.clientsock, self.clientaddr = self.sock.accept()
52 else:
53 print "Error in controller init: Active cxn not supported"
54
55 def register(self, msg_type, handler):
56 """
57 Register a callback to receive a specific message type.
58
59 Only one handler may be registered for a given message type.
60 @param msg_type The type of message to receive. May be DEFAULT
61 for all non-handled packets.
62 @param handler The function to call when a message of the given
63 type is received.
64 """
65 print "Controller message handler registration not supported"
66
Dan Talaycoe37999f2010-02-09 15:27:12 -080067 def poll(self, exp_msg=None, timeout=RCV_TIMEOUT_DEFAULT):
Dan Talayco34089522010-02-07 23:07:41 -080068 """
69 Wait for the next OF message received from the switch.
70
71 @param exp_msg If set, return only when this type of message
72 is received.
73
74 @param timeout If set, return E_TIMEOUT if mesage is not
75 received in this time. If set to 0, will not block.
76
77 @retval A triple (msg_type, msg, data) where msg_type is the OpenFlow
78 message type value OFPT_xxx, msg is a message object (from a
79 SWIG generated class) appropriate to the message type and data is
80 a string of any additional information following the
81 normal message. Note that
82 many messages do not have classes so ofp_hello is returned which
83 simply has the header.
84 The data members in the message are in host endian order.
85 If a timeout (or other error) occurs, None is returned
86 """
87 while 1:
88 okay, pkt = rcv_data_from_socket(self.clientsoc, timeout)
89 if not okay or not pkt:
90 # FIXME: Check for error
91 return None, None
92 # Convert msg to the proper OpenFlow message object
Dan Talaycoe37999f2010-02-09 15:27:12 -080093 hdr = of_header_parse(pkt)
94 print "DEBUG: msg in. pkt len %d. type %d. length %d" % \
95 (len(pkt), hdr.type, hdr.length)
Dan Talayco34089522010-02-07 23:07:41 -080096
97 if not exp_msg or (exp_msg and (hdr.type == exp_msg)):
98 return msg_type, msg
99
Dan Talaycoe37999f2010-02-09 15:27:12 -0800100 def transact(self, msg, xid=None):
Dan Talayco34089522010-02-07 23:07:41 -0800101 """
Dan Talaycoe37999f2010-02-09 15:27:12 -0800102 Run a transaction
103
104 Send the message in msg and wait for a reply with a matching
105 transaction id.
106
107 @param msg The message to send
108 @param xid If non None, set the transaction ID of the message;
109 otherwise use the one already present in the message's header.
110
Dan Talayco34089522010-02-07 23:07:41 -0800111 """
Dan Talaycoe37999f2010-02-09 15:27:12 -0800112 print "Controller transact not supported"
Dan Talayco34089522010-02-07 23:07:41 -0800113
114 def message_send(self, msg):
115 """
116 Send the message to the switch
Dan Talaycoe37999f2010-02-09 15:27:12 -0800117
118 @param msg An OpenFlow message object to be forwarded to the switch.
119
Dan Talayco34089522010-02-07 23:07:41 -0800120 """
Dan Talaycoe37999f2010-02-09 15:27:12 -0800121 pass
Dan Talayco34089522010-02-07 23:07:41 -0800122
123 def kill(self):
124 self.clientsock.close()