Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | |
| 3 | import urllib2 |
| 4 | import json |
| 5 | import re |
| 6 | import sys |
| 7 | |
| 8 | from optparse import OptionParser |
| 9 | |
| 10 | sys.path.append('~/floodlight/target/gen-py') |
| 11 | sys.path.append('~/floodlight/thrift/lib/py') |
| 12 | |
| 13 | from packetstreamer import PacketStreamer |
| 14 | from packetstreamer.ttypes import * |
| 15 | |
| 16 | from thrift import Thrift |
| 17 | from thrift.transport import TSocket |
| 18 | from thrift.transport import TTransport |
| 19 | from thrift.protocol import TBinaryProtocol |
| 20 | |
| 21 | SESSIONID = 'sessionId' |
| 22 | usage = "usage: %prog [options]" |
| 23 | parser = OptionParser(usage=usage, version="%prog 1.0") |
| 24 | parser.add_option("-c", "--controller", dest="controller", metavar="CONTROLLER_IP", |
| 25 | default="127.0.0.1", help="controller's IP address") |
| 26 | parser.add_option("-m", "--mac", dest="mac", metavar="HOST_MAC", |
| 27 | help="The host mac address to trace the OF packets") |
| 28 | |
| 29 | (options, args) = parser.parse_args() |
| 30 | |
| 31 | def validateIp(ip): |
| 32 | ipReg = ("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |
| 33 | "\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |
| 34 | "\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |
| 35 | "\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)") |
| 36 | m = re.compile(ipReg).match(ip) |
| 37 | if m: |
| 38 | return True |
| 39 | else : |
| 40 | return False |
| 41 | |
| 42 | def validateMac(mac): |
| 43 | macReg = '([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}' # same regex as above |
| 44 | m = re.compile(macReg).match(mac) |
| 45 | if m: |
| 46 | return True |
| 47 | else : |
| 48 | return False |
| 49 | |
| 50 | if not validateIp(options.controller): |
| 51 | parser.error("Invalid format for ip address.") |
| 52 | |
| 53 | if not options.mac: |
| 54 | parser.error("-m or --mac option is required.") |
| 55 | |
| 56 | if not validateMac(options.mac): |
| 57 | parser.error("Invalid format for mac address. Format: xx:xx:xx:xx:xx:xx") |
| 58 | |
| 59 | controller = options.controller |
| 60 | host = options.mac |
| 61 | |
| 62 | url = 'http://%s:8080/wm/core/packettrace/json' % controller |
| 63 | filter = {'mac':host, 'direction':'both', 'period':1000} |
| 64 | post_data = json.dumps(filter) |
| 65 | request = urllib2.Request(url, post_data, {'Content-Type':'application/json'}) |
| 66 | response_text = None |
| 67 | |
| 68 | def terminateTrace(sid): |
| 69 | global controller |
| 70 | |
| 71 | filter = {SESSIONID:sid, 'period':-1} |
| 72 | post_data = json.dumps(filter) |
| 73 | url = 'http://%s:8080/wm/core/packettrace/json' % controller |
| 74 | request = urllib2.Request(url, post_data, {'Content-Type':'application/json'}) |
| 75 | try: |
| 76 | response = urllib2.urlopen(request) |
| 77 | response_text = response.read() |
| 78 | except Exception, e: |
| 79 | # Floodlight may not be running, but we don't want that to be a fatal |
| 80 | # error, so we just ignore the exception in that case. |
| 81 | print "Exception:", e |
| 82 | |
| 83 | try: |
| 84 | response = urllib2.urlopen(request) |
| 85 | response_text = response.read() |
| 86 | except Exception, e: |
| 87 | # Floodlight may not be running, but we don't want that to be a fatal |
| 88 | # error, so we just ignore the exception in that case. |
| 89 | print "Exception:", e |
| 90 | exit |
| 91 | |
| 92 | if not response_text: |
| 93 | print "Failed to start a packet trace session" |
| 94 | sys.exit() |
| 95 | |
| 96 | response_text = json.loads(response_text) |
| 97 | |
| 98 | sessionId = None |
| 99 | if SESSIONID in response_text: |
| 100 | sessionId = response_text[SESSIONID] |
| 101 | else: |
| 102 | print "Failed to start a packet trace session" |
| 103 | sys.exit() |
| 104 | |
| 105 | try: |
| 106 | |
| 107 | # Make socket |
| 108 | transport = TSocket.TSocket('localhost', 9090) |
| 109 | |
| 110 | # Buffering is critical. Raw sockets are very slow |
| 111 | transport = TTransport.TFramedTransport(transport) |
| 112 | |
| 113 | # Wrap in a protocol |
| 114 | protocol = TBinaryProtocol.TBinaryProtocol(transport) |
| 115 | |
| 116 | # Create a client to use the protocol encoder |
| 117 | client = PacketStreamer.Client(protocol) |
| 118 | |
| 119 | # Connect! |
| 120 | transport.open() |
| 121 | |
| 122 | while 1: |
| 123 | packets = client.getPackets(sessionId) |
| 124 | for packet in packets: |
| 125 | print "Packet: %s"% packet |
| 126 | if "FilterTimeout" in packet: |
| 127 | sys.exit() |
| 128 | |
| 129 | except Thrift.TException, e: |
| 130 | print '%s' % (e.message) |
| 131 | terminateTrace(sessionId) |
| 132 | |
| 133 | except KeyboardInterrupt, e: |
| 134 | terminateTrace(sessionId) |
| 135 | |
| 136 | # Close! |
| 137 | transport.close() |
| 138 | |