summaryrefslogtreecommitdiff
path: root/sflow-rt/extras/sflow.py
blob: 4941093194b678108ef9c1a4d4b5ff9c82f8d147 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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']))