Packet Streamer (Dev)
PacketStreamer Service
Introduction
Packetstreamer is a packet streaming service that can selectively stream Openflow packets exchanged between any switch and the controller to an observer. It consists of two functional interfaces: (1) a REST-based interface to define the characteristics of the OpenFlow messages that are of interest, referred to as filter;  and (2) a Thrift-based interface for streaming the filtered packets.
REST API
The filter is defined with a POST request to the REST API: "http://<controller>:8080/wm/core/packettrace/json". The input data is parameters that define characteristics of the OpenFlow Messages we are interested in. Floodlight comes with a MAC-based filter, as an example. The following is the format for the filter.
{'mac':<hostMac>, 'direction':<direction>, 'period':<period>, 'sessionId':<sessionid>}
where,
Name | Value | Description |
---|---|---|
mac | <hostMac> | The OFMessage with matching hostMac (in the Ethernet frame in its payload) will be streamed. |
direction | in | OFPacketIn |
 | out | OFPacketOut and FlowMod |
 | both | in and out |
period | <period> | Defines the duration of the streaming session in seconds. |
 | -1 | terminate the given session |
sessionid | <sessionid> | The session to be terminated when period = -1. Otherwise, it is ignored. |
The REST API returns the sessionId, which can be used to receive packets from the streaming thrift server. The return data is in json format,
{'sessionId':<sessionid>}
Here is an example in python to create a streaming session for 1000 seconds and a function to terminate a session.
Â
Before moving forward, make sure you have started your PacketStreamerServer. See How to start PacketStreamerServer |
url = 'http://%s:8080/wm/core/packettrace/json' % controller filter = {'mac':host, 'direction':'both', 'period':1000} post_data = json.dumps(filter) request = urllib2.Request(url, post_data, {'Content-Type':'application/json'}) response_text = None try: response = urllib2.urlopen(request) response_text = response.read() except Exception, e: # Floodlight may not be running, but we don't want that to be a fatal # error, so we just ignore the exception in that case. print "Exception:", e exit if not response_text: print "Failed to start a packet trace session" sys.exit() response_text = json.loads(response_text) sessionId = None if "sessionId" in response_text: sessionId = response_text["sessionId"]
def terminateTrace(sid): global controller filter = {SESSIONID:sid, 'period':-1} post_data = json.dumps(filter) url = 'http://%s:8080/wm/core/packettrace/json' % controller request = urllib2.Request(url, post_data, {'Content-Type':'application/json'}) try: response = urllib2.urlopen(request) response_text = response.read() except Exception, e: # Floodlight may not be running, but we don't want that to be a fatal # error, so we just ignore the exception in that case. print "Exception:", e
Thrift-Based Streaming Service
The packet streaming service is brokered by a Thrift-based streaming server. The Thrift interfaces are listed below. The complete  Thrift interface can be found at src/main/thrift/packetstreamer.thrift.
service PacketStreamer { /** * Synchronous method to get packets for a given sessionid */ list<binary> getPackets(1:string sessionid), /** * Synchronous method to publish a packet. * It ensure the order that the packets are pushed */ i32 pushMessageSync(1:Message packet), /** * Asynchronous method to publish a packet. * Order is not guaranteed. */ oneway void pushMessageAsync(1:Message packet) /** * Terminate a session */ void terminateSession(1:string sessionid) }
The floodlight build script generates java and python libraries for the Thrift service. Other language support may be easily added by adding the language option into the build script, setup.sh.
The REST API section describes the creation of streaming session. Once the sessionId is created, the thrift interface, getPackets(sessionId), can be used to receive OFPackets for the given session. terminateSession(sessionId) can be used to terminate a live session.
A python example is below
try: # Make socket transport = TSocket.TSocket('localhost', 9090) # Buffering is critical. Raw sockets are very slow transport = TTransport.TFramedTransport(transport) # Wrap in a protocol protocol = TBinaryProtocol.TBinaryProtocol(transport) # Create a client to use the protocol encoder client = PacketStreamer.Client(protocol) # Connect! transport.open() while 1: packets = client.getPackets(sessionId) for packet in packets: print "Packet: %s"% packet if "FilterTimeout" in packet: sys.exit() except Thrift.TException, e: print '%s' % (e.message) terminateTrace(sessionId)
Example Client
The current version of floodlight comes with a mac-based packet streaming example. Some pieces of the client code are listed in previous sections.
A complete python client example. which illustrates the usage of both the REST API and thrift client, can be found in floodlight source at net.floodlightcontroller.packetstreamer.
Make sure to install thrift on the client machine and give the correct path for packetstreamer's gen-py and thrift python directories in the example.
How to Extend to Service
The packet streaming service can be extended beyond the mac-based streaming example. net/floodlightcontroller/core/web/PacketTraceResource.java defines the REST interface. Matching field can be extended by adding fields in FilterParameters class. The matching logic is implemented in net/floodlightcontroller/core/OFMessageFilterManager.java and can be easily extended by adding matching logic in getMatchedFilters() method. A plugin framework could replace the current implementation if more use cases pop up.
Packet Format
The mac-based streaming example have the floodlight controller perform the packet formatting. The packet formatting is done in net/floodlightcontroller/core/OFMessageFilterManager.java. In some application, raw packet may be more useful. Format can be added to the packet-trace filter as part of the session properties. Based on the session property, the corresponding formatter could be called.