main.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import subprocess, os, re, argparse
  2. from flask import Flask, render_template, redirect, request, url_for
  3. app = Flask(__name__)
  4. pattern = None
  5. dev_list = None
  6. def parse_arguments():
  7. parser = argparse.ArgumentParser(description='TC web GUI')
  8. parser.add_argument('--ip', type=str, required=False,
  9. help='The IP where the server is listening')
  10. parser.add_argument('--port', type=str, required=False,
  11. help='The port where the server is listening')
  12. parser.add_argument('--dev', type=str, nargs='*', required=False,
  13. help='The interfaces to restrict to')
  14. parser.add_argument('--regex',type=str, required=False,
  15. help='A regex to match interfaces')
  16. parser.add_argument('--debug',action='store_true',
  17. help='Run Flask in debug mode')
  18. return parser.parse_args()
  19. @app.route("/")
  20. def main():
  21. rules = get_active_rules()
  22. return render_template('main.html', rules=rules)
  23. @app.route('/new_rule/<interface>', methods=['POST'])
  24. def new_rule(interface):
  25. delay = request.form['Delay']
  26. loss = request.form['Loss']
  27. duplicate = request.form['Duplicate']
  28. reorder = request.form['Reorder']
  29. corrupt = request.form['Corrupt']
  30. rate = request.form['Rate']
  31. # remove old setup
  32. command = 'tc qdisc del dev %s root netem' % interface
  33. command = command.split(' ')
  34. proc = subprocess.Popen(command)
  35. proc.wait()
  36. # apply new setup
  37. command = 'tc qdisc add dev %s root netem' % interface
  38. if rate != '':
  39. command += ' rate %smbit' % rate
  40. if delay != '':
  41. command += ' delay %sms' % delay
  42. if loss != '':
  43. command += ' loss %s%%' % loss
  44. if duplicate != '':
  45. command += ' duplicate %s%%' % duplicate
  46. if reorder != '':
  47. command += ' reorder %s%%' % reorder
  48. if corrupt != '':
  49. command += ' corrupt %s%%' % corrupt
  50. print(command)
  51. command = command.split(' ')
  52. proc = subprocess.Popen(command)
  53. proc.wait()
  54. return redirect(url_for('main'))
  55. @app.route('/remove_rule/<interface>', methods=['POST'])
  56. def remove_rule(interface):
  57. # remove old setup
  58. command = 'tc qdisc del dev %s root netem' % interface
  59. command = command.split(' ')
  60. proc = subprocess.Popen(command)
  61. proc.wait()
  62. return redirect(url_for('main'))
  63. def get_active_rules():
  64. proc = subprocess.Popen(['tc', 'qdisc'], stdout=subprocess.PIPE)
  65. output = proc.communicate()[0].decode()
  66. lines = output.split('\n')[:-1]
  67. rules = []
  68. dev = set()
  69. for line in lines:
  70. arguments = line.split(' ')
  71. rule = parse_rule(arguments)
  72. if rule['name'] and rule['name'] not in dev:
  73. rules.append(rule)
  74. dev.add(rule['name'])
  75. return rules
  76. def parse_rule(splitted_rule):
  77. rule = {'name': None,
  78. 'rate': None,
  79. 'delay': None,
  80. 'loss': None,
  81. 'duplicate': None,
  82. 'reorder': None,
  83. 'corrupt': None}
  84. i = 0
  85. for argument in splitted_rule:
  86. if argument == 'dev':
  87. # Both regex pattern and dev name can be given
  88. # An interface could match the pattern and/or
  89. # be in the interface list
  90. if pattern is None and dev_list is None:
  91. rule['name'] = splitted_rule[i+1]
  92. if pattern:
  93. if pattern.match(splitted_rule[i+1]) :
  94. rule['name'] = splitted_rule[i+1]
  95. if dev_list:
  96. if splitted_rule[i+1] in dev_list:
  97. rule['name'] = splitted_rule[i+1]
  98. elif argument == 'rate':
  99. rule['rate'] = splitted_rule[i + 1].split('Mbit')[0]
  100. elif argument == 'delay':
  101. rule['delay'] = splitted_rule[i + 1]
  102. elif argument == 'loss':
  103. rule['loss'] = splitted_rule[i + 1]
  104. elif argument == 'duplicate':
  105. rule['duplicate'] = splitted_rule[i + 1]
  106. elif argument == 'reorder':
  107. rule['reorder'] = splitted_rule[i + 1]
  108. elif argument == 'corrupt':
  109. rule['corrupt'] = splitted_rule[i + 1]
  110. i += 1
  111. return rule
  112. if __name__ == "__main__":
  113. #if os.geteuid() != 0:
  114. # exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.")
  115. args = parse_arguments()
  116. if args.regex:
  117. pattern = re.compile(args.regex)
  118. if args.dev:
  119. dev_list = args.dev
  120. app_args={}
  121. if args.ip:
  122. app_args['host'] = args.ip
  123. if args.port:
  124. app_args['port'] = args.port
  125. if not args.debug:
  126. app_args['debug'] = False
  127. app.debug = True
  128. app.run(**app_args)