diff options
Diffstat (limited to 'sflow-rt/extras/sflow.py')
| -rw-r--r-- | sflow-rt/extras/sflow.py | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/sflow-rt/extras/sflow.py b/sflow-rt/extras/sflow.py new file mode 100644 index 0000000..4941093 --- /dev/null +++ b/sflow-rt/extras/sflow.py @@ -0,0 +1,96 @@ +from mininet.net import Mininet +from mininet.util import quietRun +from requests import put +from os import listdir, environ +import re +import socket +import fcntl +import array +import struct +import sys + +def wrapper(fn): + + def getIfInfo(dst): + is_64bits = sys.maxsize > 2**32 + struct_size = 40 if is_64bits else 32 + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + max_possible = 8 # initial value + while True: + bytes = max_possible * struct_size + names = array.array('B') + for i in range(0, bytes): + names.append(0) + outbytes = struct.unpack('iL', fcntl.ioctl( + s.fileno(), + 0x8912, # SIOCGIFCONF + struct.pack('iL', bytes, names.buffer_info()[0]) + ))[0] + if outbytes == bytes: + max_possible *= 2 + else: + break + try: + namestr = names.tobytes() + namestr = namestr.decode('utf-8') + except AttributeError: + namestr = names.tostring() + s.connect((dst, 0)) + ip = s.getsockname()[0] + for i in range(0, outbytes, struct_size): + name = namestr[i:i+16].split('\0', 1)[0] + addr = socket.inet_ntoa(namestr[i+20:i+24].encode('utf-8')) + if addr == ip: + return (name,addr) + + def configSFlow(net,collector,ifname,sampling,polling): + print("*** Enabling sFlow:") + sflow = 'ovs-vsctl -- --id=@sflow create sflow agent=%s target=%s sampling=%s polling=%s --' % (ifname,collector,sampling,polling) + for s in net.switches: + sflow += ' -- set bridge %s sflow=@sflow' % s + print(' '.join([s.name for s in net.switches])) + quietRun(sflow) + + def sendTopology(net,agent,collector): + print("*** Sending topology") + topo = {'nodes':{}, 'links':{}} + for s in net.switches: + topo['nodes'][s.name] = {'agent':agent, 'ports':{}} + path = '/sys/devices/virtual/net/' + for child in listdir(path): + parts = re.match('(^.+)-(.+)', child) + if parts == None: continue + if parts.group(1) in topo['nodes']: + ifindex = open(path+child+'/ifindex').read().split('\n',1)[0] + topo['nodes'][parts.group(1)]['ports'][child] = {'ifindex': ifindex} + i = 0 + for s1 in net.switches: + j = 0 + for s2 in net.switches: + if j > i: + intfs = s1.connectionsTo(s2) + for intf in intfs: + s1ifIdx = topo['nodes'][s1.name]['ports'][intf[0].name]['ifindex'] + s2ifIdx = topo['nodes'][s2.name]['ports'][intf[1].name]['ifindex'] + linkName = '%s-%s' % (s1.name, s2.name) + topo['links'][linkName] = {'node1': s1.name, 'port1': intf[0].name, 'node2': s2.name, 'port2': intf[1].name} + j += 1 + i += 1 + + put('http://%s:8008/topology/json' % collector, json=topo) + + def result(*args,**kwargs): + res = fn(*args,**kwargs) + net = args[0] + collector = environ.get('COLLECTOR','127.0.0.1') + sampling = environ.get('SAMPLING','10') + polling = environ.get('POLLING','10') + (ifname, agent) = getIfInfo(collector) + configSFlow(net,collector,ifname,sampling,polling) + sendTopology(net,agent,collector) + return res + + return result + +setattr(Mininet, 'start', wrapper(Mininet.__dict__['start'])) + |
