#!/usr/bin/python import urllib2 import json import re import sys from optparse import OptionParser sys.path.append('~/floodlight/target/gen-py') sys.path.append('~/floodlight/thrift/lib/py') from packetstreamer import PacketStreamer from packetstreamer.ttypes import * from thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol SESSIONID = 'sessionId' usage = "usage: %prog [options]" parser = OptionParser(usage=usage, version="%prog 1.0") parser.add_option("-c", "--controller", dest="controller", metavar="CONTROLLER_IP", default="127.0.0.1", help="controller's IP address") parser.add_option("-m", "--mac", dest="mac", metavar="HOST_MAC", help="The host mac address to trace the OF packets") (options, args) = parser.parse_args() def validateIp(ip): ipReg = ("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" "\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" "\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" "\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)") m = re.compile(ipReg).match(ip) if m: return True else : return False def validateMac(mac): macReg = '([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}' # same regex as above m = re.compile(macReg).match(mac) if m: return True else : return False if not validateIp(options.controller): parser.error("Invalid format for ip address.") if not options.mac: parser.error("-m or --mac option is required.") if not validateMac(options.mac): parser.error("Invalid format for mac address. Format: xx:xx:xx:xx:xx:xx") controller = options.controller host = options.mac 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 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 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] else: print "Failed to start a packet trace session" sys.exit() 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) except KeyboardInterrupt, e: terminateTrace(sessionId) # Close! transport.close()