havox 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +674 -0
  7. data/README.md +82 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/config.rb +4 -0
  12. data/examples/example_3x3.dot +81 -0
  13. data/examples/example_3x3.hvx +5 -0
  14. data/exe/havox +107 -0
  15. data/havox.gemspec +33 -0
  16. data/lib/havox.rb +51 -0
  17. data/lib/havox/app/api.rb +57 -0
  18. data/lib/havox/app/helpers/methods.rb +43 -0
  19. data/lib/havox/classes/edge.rb +11 -0
  20. data/lib/havox/classes/modified_policy.rb +44 -0
  21. data/lib/havox/classes/node.rb +19 -0
  22. data/lib/havox/classes/policy.rb +68 -0
  23. data/lib/havox/classes/rib.rb +30 -0
  24. data/lib/havox/classes/route.rb +82 -0
  25. data/lib/havox/classes/route_filler.rb +43 -0
  26. data/lib/havox/classes/rule.rb +74 -0
  27. data/lib/havox/classes/rule_expander.rb +47 -0
  28. data/lib/havox/classes/rule_sanitizer.rb +42 -0
  29. data/lib/havox/classes/topology.rb +75 -0
  30. data/lib/havox/classes/translator.rb +37 -0
  31. data/lib/havox/configuration.rb +20 -0
  32. data/lib/havox/dsl/directive.rb +70 -0
  33. data/lib/havox/dsl/directive_proxy.rb +36 -0
  34. data/lib/havox/dsl/examples/routeflow.hvx +12 -0
  35. data/lib/havox/dsl/network.rb +64 -0
  36. data/lib/havox/exceptions.rb +21 -0
  37. data/lib/havox/modules/command.rb +31 -0
  38. data/lib/havox/modules/field_parser.rb +21 -0
  39. data/lib/havox/modules/merlin.rb +85 -0
  40. data/lib/havox/modules/openflow10/ovs/actions.rb +41 -0
  41. data/lib/havox/modules/openflow10/ovs/matches.rb +35 -0
  42. data/lib/havox/modules/openflow10/routeflow/actions.rb +45 -0
  43. data/lib/havox/modules/openflow10/routeflow/matches.rb +44 -0
  44. data/lib/havox/modules/openflow10/trema/actions.rb +45 -0
  45. data/lib/havox/modules/openflow10/trema/matches.rb +43 -0
  46. data/lib/havox/modules/routeflow.rb +50 -0
  47. data/lib/havox/version.rb +3 -0
  48. data/lib/merlin/policies/common.mln +9 -0
  49. data/lib/merlin/policies/defense.mln +5 -0
  50. data/lib/merlin/policies/max.mln +2 -0
  51. data/lib/merlin/policies/min.mln +2 -0
  52. data/lib/merlin/policies/routeflow.mln +8 -0
  53. data/lib/merlin/policies/test.mln +2 -0
  54. data/lib/merlin/policies/tetrahedron.mln +8 -0
  55. data/lib/merlin/policies/tetrahedron.sample.mln +15 -0
  56. data/lib/merlin/policies/web_balanced.mln +7 -0
  57. data/lib/merlin/policies/web_unbalanced.mln +2 -0
  58. data/lib/merlin/topologies/common.dot +63 -0
  59. data/lib/merlin/topologies/defense.dot +20 -0
  60. data/lib/merlin/topologies/max.dot +17 -0
  61. data/lib/merlin/topologies/min.dot +11 -0
  62. data/lib/merlin/topologies/routeflow.dot +37 -0
  63. data/lib/merlin/topologies/tetrahedron.dot +39 -0
  64. data/lib/trema/controllers/main_controller.rb +113 -0
  65. data/lib/trema/topologies/common_topology.rb +36 -0
  66. data/lib/trema/topologies/routeflow_topology.rb +21 -0
  67. data/lib/trema/topologies/tetrahedron_topology.rb +22 -0
  68. metadata +253 -0
@@ -0,0 +1,82 @@
1
+ # Havox
2
+
3
+ Havox is a rule generator for Autonomous Systems supported by OpenFlow switches. Based on orchestration directives (or instructions) written in its own DSL, Havox generates a set of OpenFlow rules to be installed on the underlying switches.
4
+
5
+ As part of a bigger architecture, Havox is designed to run as a web API that receives requests containing the directives, the topology graph description and some parameters for rule formatting. Once the rules are generated, the API responds with a JSON message containing all the rules, each one indicating which OpenFlow switch it should be installed on.
6
+
7
+ The mentioned architecture is composed of Havox, [RouteFlow](https://github.com/routeflow/RouteFlow) and [Merlin](https://github.com/merlin-lang/merlin), and currently tested in a [Mininet](https://github.com/mininet/mininet) environment with support of [MiniNext](https://github.com/USC-NSL/miniNExT) implementing Quagga routing engines. RouteFlow requests rules from Havox and therefore is a client, whereas Merlin is a dependency which effectively calculates the paths between the AS exits.
8
+
9
+ ## Development status
10
+
11
+ Havox is still experimental, born from a [master's thesis](http://www2.uniriotec.br/ppgi/banco-de-dissertacoes-ppgi-unirio/ano-2017/havox-uma-arquitetura-para-orquestracao-de-trafego-em-redes-openflow/view), so it is being actively developed and improved. There is yet a lot of new functionalities to come.
12
+
13
+ ## How it works
14
+
15
+ Havox is implemented in Ruby and is strongly based on metaprogramming concepts. The orchestration directives that forms its DSL are methods executed by the Ruby interpreter, having both values and entire blocks of code as parameters. The following code shows some Havox directives:
16
+
17
+ ```ruby
18
+ topology 'example.dot'
19
+ associate :rfvmE, :s5
20
+
21
+ exit(:s4) { destination_port 80 }
22
+
23
+ exit(:s3) {
24
+ source_ip '200.156.0.0/16'
25
+ destination_ip '200.20.0.0/16'
26
+ }
27
+ ```
28
+
29
+ The first one, `topology <file_name>` is a topology file definition directive. It takes a string and specifies the topology description file that should be considered, which usually goes together with the directives file in the same request.
30
+
31
+ The second, `associate <router_name>, <switch_name>` is the router-switch association directive. It takes a string or a [symbol](https://ruby-doc.org/core-2.4.0/Symbol.html) that specifies the RouteFlow container name that runs the target routing instance and its associated OpenFlow switch name. In this case, it associates the routing container _rfvmE_ to the switch _s5_.
32
+
33
+ Next, there are two orchestration directives that instructs the matching flow to leave the network by the indicated switch. The exit directive, `exit(<switch_name>) { <openflow_fields_and_values> }`, takes the switch name as a string or symbol and a block containing the supported OpenFlow fields and their respective matching values, which can be strings or integers depending on the field.
34
+
35
+ For example, the first `exit` directive tells that any matching traffic with destination port 80 should leave the domain by the switch _s4_. The second `exit` directive tells that any packet that comes from the network 200.156/16 and heads to the network 200.20/16 must leave the domain by the switch _s3_.
36
+
37
+ The topology file is a graph description file written in [DOT language](https://en.wikipedia.org/wiki/DOT_(graph_description_language)) and describes how the network topology is organized. This file is processed by both Havox and its dependency, Merlin. Each node has informations like its name, its internal IP address from one of its interfaces and how it is connected to the other nodes. It is important to know that this IP address is used by Havox to infer the associations between routing containers and switches using OSPF routes. Otherwise, it would be required to manually associate each pair using the association directive described above.
38
+
39
+ The exit directives from the request will be transcompiled to Merlin blocks of code, written in a Merlin policy file. This file is sent with the topology file to the Merlin process, where they will be evaluated for paths calculation. The generated raw rules are then post-processed, formatted and outputted by the API.
40
+
41
+ More details about the transcompilation, parsing and formatting processes can be found [here](http://www2.uniriotec.br/ppgi/banco-de-dissertacoes-ppgi-unirio/ano-2017/havox-uma-arquitetura-para-orquestracao-de-trafego-em-redes-openflow/view) (master's thesis in brazilian portuguese).
42
+
43
+ ## Installation
44
+
45
+ Install Havox by:
46
+
47
+ 1. Cloning the repository: `$ git clone https://github.com/rodrigosoares/havox`
48
+ 2. Accessing the directory: `$ cd havox`
49
+ 3. Installing gem dependencies: `$ bin/setup`
50
+
51
+ Besides, Havox requires [Merlin](https://github.com/merlin-lang/merlin) and a [modified version of RouteFlow](https://github.com/rodrigosoares/RouteFlow) that implements IP source and VLAN ID matching, subnet mask support and RFHavox module. The latter is an extra RouteFlow module designed to request rules from the remote Havox web API and enqueue them into the RouteFlow IPC system.
52
+
53
+ If the tests will be run in a experimental network, [Mininet](https://github.com/mininet/mininet) and [MiniNext](https://github.com/USC-NSL/miniNExT) are also required. Gists containing example Quagga BGP configurations and Mininet topology files can be found [here](https://gist.github.com/rodrigosoares/53ca13f0376ade1fa7b7221328dae3ce).
54
+
55
+ It is *strongly recommended* to install Merlin, RouteFlow and Mininet/MiniNext in isolated virtual machines, each. Make sure that all the VMs ping each other successfully. The recommendation is to use [VirtualBox](https://www.virtualbox.org/) with _host-only network_ adapters.
56
+
57
+ Setup all projects following their respective installation instructions. If using RouteFlow with Mininet, follow the [instructions](https://github.com/routeflow/RouteFlow/wiki/Tutorial-2:-rftest2) on setting Mininet up with RouteFlow remote controller.
58
+
59
+ ## Usage
60
+
61
+ HVX, MN and RF are the environments running Havox, Mininet and RouteFlow, respectively.
62
+
63
+ 1. (HVX) Setup Merlin and RouteFlow IPs and etcetera in `config.rb`.
64
+ 2. (HVX) Start Havox API web server: `$ havox`.
65
+ 3. (MN) Start Mininet, pointing its remote controller to the RouteFlow VM.
66
+ 4. (RF) Start RouteFlow: `sudo ./rftest2`.
67
+
68
+ If everything runs fine, RouteFlow will send a POST request to Havox, which in turn will log it and respond.
69
+
70
+ ## Development
71
+
72
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rspec --format d` to run the tests and read a little documentation about what each component does. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
73
+
74
+ ## Contributing
75
+
76
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rodrigosoares/havox.
77
+
78
+ Be sure to follow [Ruby best practices](https://github.com/bbatsov/ruby-style-guide) and to create a spec test case for each new method, module or component you create.
79
+
80
+ ## License
81
+
82
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "havox"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,4 @@
1
+ Havox.configure do |config|
2
+ config.merlin_host = '192.168.56.102'
3
+ config.rf_lxc_names = %w(rfvmA rfvmB rfvmC rfvmD rfvmE rfvmF rfvmG rfvmH rfvmI)
4
+ end
@@ -0,0 +1,81 @@
1
+ digraph g1 {
2
+ h1 [type = host, mac = "00:00:00:00:00:01", ip = "172.31.1.100"];
3
+ h2 [type = host, mac = "00:00:00:00:00:02", ip = "172.31.2.100"];
4
+ h3 [type = host, mac = "00:00:00:00:00:03", ip = "172.31.3.100"];
5
+ h4 [type = host, mac = "00:00:00:00:00:04", ip = "172.31.4.100"];
6
+ h5 [type = host, mac = "00:00:00:00:00:05", ip = "172.31.5.100"];
7
+ h6 [type = host, mac = "00:00:00:00:00:06", ip = "172.31.6.100"];
8
+ h7 [type = host, mac = "00:00:00:00:00:07", ip = "172.31.7.100"];
9
+ h8 [type = host, mac = "00:00:00:00:00:08", ip = "172.31.8.100"];
10
+ h9 [type = host, mac = "00:00:00:00:00:09", ip = "172.31.9.100"];
11
+
12
+ s1 [type = switch, ip = "172.31.1.1", id = 1];
13
+ s2 [type = switch, ip = "172.31.2.1", id = 2];
14
+ s3 [type = switch, ip = "172.31.3.1", id = 3];
15
+ s4 [type = switch, ip = "172.31.4.1", id = 4];
16
+ s5 [type = switch, ip = "172.31.5.1", id = 5];
17
+ s6 [type = switch, ip = "172.31.6.1", id = 6];
18
+ s7 [type = switch, ip = "172.31.7.1", id = 7];
19
+ s8 [type = switch, ip = "172.31.8.1", id = 8];
20
+ s9 [type = switch, ip = "172.31.9.1", id = 9];
21
+
22
+ s1 -> h1 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
23
+ h1 -> s1 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
24
+
25
+ s2 -> h2 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
26
+ h2 -> s2 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
27
+
28
+ s3 -> h3 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
29
+ h3 -> s3 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
30
+
31
+ s4 -> h4 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
32
+ h4 -> s4 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
33
+
34
+ s5 -> h5 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
35
+ h5 -> s5 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
36
+
37
+ s6 -> h6 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
38
+ h6 -> s6 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
39
+
40
+ s7 -> h7 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
41
+ h7 -> s7 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
42
+
43
+ s8 -> h8 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
44
+ h8 -> s8 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
45
+
46
+ s9 -> h9 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
47
+ h9 -> s9 [src_port = 1, dst_port = 1, cost = 1, capacity = "1Gbps"];
48
+
49
+ s1 -> s2 [src_port = 2, dst_port = 2, cost = 1, capacity = "1Gbps"];
50
+ s1 -> s4 [src_port = 3, dst_port = 2, cost = 1, capacity = "1Gbps"];
51
+
52
+ s2 -> s1 [src_port = 2, dst_port = 2, cost = 1, capacity = "1Gbps"];
53
+ s2 -> s3 [src_port = 3, dst_port = 2, cost = 1, capacity = "1Gbps"];
54
+ s2 -> s5 [src_port = 4, dst_port = 1, cost = 1, capacity = "1Gbps"];
55
+
56
+ s3 -> s2 [src_port = 2, dst_port = 3, cost = 1, capacity = "1Gbps"];
57
+ s3 -> s6 [src_port = 3, dst_port = 2, cost = 1, capacity = "1Gbps"];
58
+
59
+ s4 -> s1 [src_port = 2, dst_port = 3, cost = 1, capacity = "1Gbps"];
60
+ s4 -> s5 [src_port = 4, dst_port = 2, cost = 1, capacity = "1Gbps"];
61
+ s4 -> s7 [src_port = 3, dst_port = 3, cost = 1, capacity = "1Gbps"];
62
+
63
+ s5 -> s2 [src_port = 1, dst_port = 4, cost = 1, capacity = "1Gbps"];
64
+ s5 -> s4 [src_port = 2, dst_port = 4, cost = 1, capacity = "1Gbps"];
65
+ s5 -> s6 [src_port = 3, dst_port = 4, cost = 1, capacity = "1Gbps"];
66
+ s5 -> s8 [src_port = 4, dst_port = 4, cost = 1, capacity = "1Gbps"];
67
+
68
+ s6 -> s3 [src_port = 2, dst_port = 3, cost = 1, capacity = "1Gbps"];
69
+ s6 -> s5 [src_port = 4, dst_port = 3, cost = 1, capacity = "1Gbps"];
70
+ s6 -> s9 [src_port = 3, dst_port = 3, cost = 1, capacity = "1Gbps"];
71
+
72
+ s7 -> s4 [src_port = 3, dst_port = 3, cost = 1, capacity = "1Gbps"];
73
+ s7 -> s8 [src_port = 2, dst_port = 2, cost = 1, capacity = "1Gbps"];
74
+
75
+ s8 -> s5 [src_port = 4, dst_port = 4, cost = 1, capacity = "1Gbps"];
76
+ s8 -> s7 [src_port = 2, dst_port = 2, cost = 1, capacity = "1Gbps"];
77
+ s8 -> s9 [src_port = 3, dst_port = 2, cost = 1, capacity = "1Gbps"];
78
+
79
+ s9 -> s6 [src_port = 3, dst_port = 3, cost = 1, capacity = "1Gbps"];
80
+ s9 -> s8 [src_port = 2, dst_port = 3, cost = 1, capacity = "1Gbps"];
81
+ }
@@ -0,0 +1,5 @@
1
+ Havox::Network.define do
2
+ topology 'example_3x3.dot'
3
+ associate :rfvmE, :s5
4
+ exit(:s4) { destination_port 80 }
5
+ end
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'havox'
4
+ require 'optparse'
5
+ require 'ostruct'
6
+ require_relative '../lib/havox/app/api'
7
+
8
+ # Defines command options and parameters.
9
+ args = OpenStruct.new
10
+ OptionParser.new do |opt|
11
+ opt.separator ''
12
+ opt.separator <<-DESCRIPTION
13
+ Havox is a rule generator for Autonomous Systems supported by OpenFlow switches.
14
+ Based on a directives file written in its own DSL and a graph topology file, Havox
15
+ generates a set of OpenFlow rules to be installed in the underlying switches. Just
16
+ run the following command to start the Havox API web server:
17
+
18
+ havox
19
+
20
+ This will run the server on port 4567. It listens for HTTP requests to the /rules
21
+ route, POST method. The request should contain the directives file, the topology
22
+ file and a set of configuration parameters that define how the rules should be
23
+ formatted.
24
+
25
+ An alternative way to run Havox is by calling its rules-only mode (prints the rules
26
+ to the STDOUT) or using the Trema controller (yet experimental). See the options below.
27
+ DESCRIPTION
28
+ opt.separator ''
29
+
30
+ opt.on('-c', '--trema-topo CONF', 'Trema topology configuration file') { |o| args.trema_topology = o }
31
+ opt.on('-t', '--merlin-topo TOPO', 'Merlin topology file') { |o| args.merlin_topology = o }
32
+ opt.on('-p', '--merlin-policy POLICY', 'Merlin policy file') { |o| args.merlin_policy = o }
33
+ opt.on('-d', '--directives DIRECTIVES_FILE', 'Havox directives file') { |o| args.havox_directives = o }
34
+ opt.on('-s', '--syntax trema,ovs,routeflow', [:trema, :ovs, :routeflow], 'Output syntax for generated rules (default: trema)') { |o| args.syntax = o }
35
+ opt.on('-f', '--[no-]force', 'Forces Havox to ignore field conflicts in rules generated by Merlin') { |o| args.force = o }
36
+ opt.on('-b', '--[no-]basic-policies', 'Automatically appends policies for basic protocols in the policies file') { |o| args.basic = o }
37
+ opt.on('-x', '--[no-]expand', 'Expands rules from VLAN-based to full predicates') { |o| args.expand = o }
38
+ opt.on('-o', '--[no-]output', 'Switches all occurrences of Enqueue action to Output action') { |o| args.output = o }
39
+ opt.on('--rules-only', 'Tells Havox to just output rules without loading anything') { |o| args.rules_only = o }
40
+ opt.on('--trema', 'Tells Havox to load Trema environment') { |o| args.trema = o }
41
+ end.parse!
42
+
43
+ # Sets all required environment variables to be read in the controller.
44
+ def set_environment_vars(args)
45
+ ENV['HAVOX_FORCE'] = args.force.to_s
46
+ ENV['HAVOX_BASIC'] = args.basic.to_s
47
+ ENV['HAVOX_EXPAND'] = args.expand.to_s
48
+ ENV['HAVOX_OUTPUT'] = args.output.to_s
49
+ ENV['HAVOX_SYNTAX'] = args.syntax.to_s
50
+ ENV['HAVOX_MERLIN_TOPOLOGY'] = args.merlin_topology
51
+ ENV['HAVOX_MERLIN_POLICY'] = args.merlin_policy
52
+ end
53
+
54
+ # Defines the Trema execution method.
55
+ def start_trema!(args)
56
+ puts 'Loading Havox with Trema...'
57
+ cmd = 'trema run lib/trema/controllers/main_controller.rb' \
58
+ " -c #{args.trema_topology}"
59
+ system(cmd)
60
+ rescue Interrupt
61
+ puts 'Closing.'
62
+ end
63
+
64
+ # Checks arguments for rules generation.
65
+ def files_ok?(args)
66
+ !(args.havox_directives.nil? && args.merlin_policy.nil?) &&
67
+ !args.merlin_topology.nil?
68
+ end
69
+
70
+ # Checks arguments for Trema initialization.
71
+ def can_start_trema?(args)
72
+ !args.trema_topology.nil? && files_ok?(args)
73
+ end
74
+
75
+ # Sets environment variables and starts Havox.
76
+ def set_env_and_start_trema!(args)
77
+ if can_start_trema?(args)
78
+ set_environment_vars(args)
79
+ start_trema!(args)
80
+ end
81
+ end
82
+
83
+ # Transcompiles Havox directives to Merlin blocks and returns the resulting Merlin file.
84
+ def transcompile_to_merlin(args)
85
+ mln_filename = "./#{File.basename(args.havox_directives, '.hvx')}.mln"
86
+ eval File.read(args.havox_directives)
87
+ mln_blocks = Havox::Network.transcompile(args)
88
+ File.open(mln_filename, 'w') { |f| f.write(mln_blocks.join("\n")) }
89
+ mln_filename
90
+ end
91
+
92
+ # Calls the rules generation and outputs the rules.
93
+ def output_rules!(args)
94
+ if files_ok?(args)
95
+ args.merlin_policy = transcompile_to_merlin(args) unless args.havox_directives.nil?
96
+ puts Havox::Policy.new(args.to_h).to_json
97
+ end
98
+ end
99
+
100
+ # After everything is defined, main execution flux starts here.
101
+ if args.rules_only
102
+ output_rules!(args)
103
+ elsif args.trema
104
+ set_env_and_start_trema!(args)
105
+ else
106
+ Havox::API.run!
107
+ end
@@ -0,0 +1,33 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'havox/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'havox'
7
+ spec.version = Havox::VERSION
8
+ spec.authors = ['Rodrigo Soares']
9
+ spec.email = ['silvars1@gmail.com']
10
+
11
+ spec.summary = %q{A gem for making the generation of OpenFlow network rules easier.}
12
+ spec.description = %q{This gem offers a friendly way to deal with OpenFlow network policies generated by Merlin, integrating it with RouteFlow through a simple orchestration DSL.}
13
+ spec.homepage = 'https://github.com/rodrigosoares/havox'
14
+ spec.license = 'GPL-3.0'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'exe'
20
+ spec.executables = 'havox'
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.11'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'rspec', '~> 3.0'
26
+ spec.add_development_dependency 'factory_girl', '~> 4.8'
27
+ spec.add_development_dependency 'awesome_print', '~> 1.7'
28
+ spec.add_runtime_dependency 'net-ssh', '~> 4.0'
29
+ spec.add_runtime_dependency 'net-scp', '~> 1.2'
30
+ spec.add_runtime_dependency 'trema', '~> 0.10.1'
31
+ spec.add_runtime_dependency 'colorize', '~> 0.8'
32
+ spec.add_runtime_dependency 'sinatra', '~> 2.0'
33
+ end
@@ -0,0 +1,51 @@
1
+ require 'json'
2
+ require 'ipaddr'
3
+ require 'singleton'
4
+ require 'havox/version'
5
+ require 'havox/exceptions'
6
+ require 'havox/configuration'
7
+ require 'havox/modules/command'
8
+ require 'havox/modules/routeflow'
9
+ require 'havox/modules/merlin'
10
+ require 'havox/modules/field_parser'
11
+ require 'havox/modules/openflow10/ovs/actions'
12
+ require 'havox/modules/openflow10/ovs/matches'
13
+ require 'havox/modules/openflow10/routeflow/actions'
14
+ require 'havox/modules/openflow10/routeflow/matches'
15
+ require 'havox/modules/openflow10/trema/actions'
16
+ require 'havox/modules/openflow10/trema/matches'
17
+ require 'havox/classes/topology'
18
+ require 'havox/classes/node'
19
+ require 'havox/classes/edge'
20
+ require 'havox/classes/modified_policy'
21
+ require 'havox/classes/policy'
22
+ require 'havox/classes/rib'
23
+ require 'havox/classes/route'
24
+ require 'havox/classes/route_filler'
25
+ require 'havox/classes/rule'
26
+ require 'havox/classes/rule_sanitizer'
27
+ require 'havox/classes/rule_expander'
28
+ require 'havox/classes/translator'
29
+ require 'havox/dsl/directive.rb'
30
+ require 'havox/dsl/directive_proxy.rb'
31
+ require 'havox/dsl/network.rb'
32
+ require 'net/ssh'
33
+ require 'net/scp'
34
+
35
+ module Havox
36
+ class << self
37
+ attr_accessor :configuration
38
+ end
39
+
40
+ def self.configuration
41
+ @configuration ||= Configuration.new
42
+ end
43
+
44
+ def self.reset
45
+ @configuration = Configuration.new
46
+ end
47
+
48
+ def self.configure
49
+ yield(configuration)
50
+ end
51
+ end
@@ -0,0 +1,57 @@
1
+ require 'bundler/setup' # TODO: Remove this line after Havox is released to RubyGems.
2
+ require 'sinatra'
3
+ require 'colorize'
4
+ require 'havox'
5
+ require_relative '../../../config'
6
+ require_relative 'helpers/methods'
7
+
8
+ module Havox
9
+ class API < Sinatra::Base
10
+ set :bind, '0.0.0.0'
11
+
12
+ before { content_type :json }
13
+
14
+ # TODO: Make this read files from anywhere in the file system.
15
+ get '/rules/:name' do
16
+ base_dir = '/home/rod/Projetos/Mestrado/havox/lib/merlin'
17
+ opts = {
18
+ merlin_topology: "#{base_dir}/topologies/#{params[:name]}.dot",
19
+ merlin_policy: "#{base_dir}/policies/#{params[:name]}.mln",
20
+ force: params[:force].eql?('true'),
21
+ basic: params[:basic].eql?('true'),
22
+ expand: params[:expand].eql?('true'),
23
+ output: params[:output].eql?('true'),
24
+ syntax: params[:syntax]&.to_sym
25
+ }
26
+ Havox::Policy.new(opts).to_json
27
+ end
28
+
29
+ post '/rules' do
30
+ dot_filepath = handle_file(params[:dot_file])
31
+ hvx_filepath = handle_file(params[:hvx_file])
32
+ pre_opts = {
33
+ qos: params[:qos],
34
+ preferred: params[:preferred],
35
+ arbitrary: params[:arbitrary]
36
+ }
37
+ mln_filepath = run_network(dot_filepath, hvx_filepath, pre_opts)
38
+
39
+ if mln_filepath.nil?
40
+ [].to_json
41
+ else
42
+ pos_opts = {
43
+ merlin_topology: dot_filepath,
44
+ merlin_policy: mln_filepath,
45
+ force: params[:force].eql?('true'),
46
+ basic: params[:basic].eql?('true'),
47
+ expand: params[:expand].eql?('true'),
48
+ output: params[:output].eql?('true'),
49
+ syntax: params[:syntax]&.to_sym
50
+ }
51
+ policy = Havox::Policy.new(pos_opts)
52
+ print_policy(policy, pos_opts)
53
+ policy.to_json
54
+ end
55
+ end
56
+ end
57
+ end