trema 0.1.3.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rantfile +87 -80
- data/VERSION +1 -1
- data/cruise.rb +3 -3
- data/features/step_definitions/misc_steps.rb +2 -2
- data/features/support/env.rb +3 -3
- data/ruby/trema/command/kill.rb +1 -1
- data/ruby/trema/daemon.rb +3 -3
- data/ruby/trema/executables.rb +36 -54
- data/ruby/trema/link.rb +4 -1
- data/ruby/trema/monkey-patch/module.rb +2 -0
- data/ruby/trema/monkey-patch/module/class-method.rb +40 -0
- data/ruby/trema/open-vswitch.rb +1 -1
- data/ruby/trema/packet_in.c +96 -0
- data/ruby/trema/path.rb +42 -92
- data/ruby/trema/util.rb +6 -1
- data/spec/trema/dsl/runner_spec.rb +31 -8
- data/spec/trema/echo-request_spec.rb +1 -1
- data/spec/trema/executables_spec.rb +22 -41
- data/spec/trema/packet-in_spec.rb +375 -67
- data/spec/trema/packet-out_spec.rb +2 -1
- data/spec/trema/queue-get-config-request_spec.rb +1 -1
- data/src/lib/ipv4.h +18 -1
- data/src/lib/packet_info.h +1 -1
- data/src/lib/packet_parser.c +2 -2
- data/trema +3 -4
- data/trema.gemspec +3 -2
- data/unittests/lib/openflow_message_test.c +1 -1
- data/unittests/lib/packet_parser_test.c +1 -1
- data/unittests/lib/utility_test.c +2 -2
- metadata +5 -5
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/cruise.rb
CHANGED
@@ -366,9 +366,9 @@ def init_cruise
|
|
366
366
|
$start_time = Time.now
|
367
367
|
sh "./build.rb distclean"
|
368
368
|
sh "bundle install"
|
369
|
-
mkdir_p Trema.
|
370
|
-
mkdir_p Trema.
|
371
|
-
mkdir_p Trema.
|
369
|
+
mkdir_p Trema.log
|
370
|
+
mkdir_p Trema.pid
|
371
|
+
mkdir_p Trema.sock
|
372
372
|
end
|
373
373
|
|
374
374
|
|
@@ -25,10 +25,10 @@ end
|
|
25
25
|
|
26
26
|
When /^wait until "([^"]*)" is up$/ do | process |
|
27
27
|
nloop = 0
|
28
|
-
pid_file = File.join( Trema.
|
28
|
+
pid_file = File.join( Trema.pid, "#{ process }.pid" )
|
29
29
|
loop do
|
30
30
|
nloop += 1
|
31
|
-
raise "Timeout" if nloop >
|
31
|
+
raise "Timeout" if nloop > 50 # FIXME
|
32
32
|
break if FileTest.exists?( pid_file ) and not ps_entry_of( process ).nil?
|
33
33
|
sleep 0.1
|
34
34
|
end
|
data/features/support/env.rb
CHANGED
@@ -48,13 +48,13 @@ end
|
|
48
48
|
|
49
49
|
|
50
50
|
def cucumber_log name
|
51
|
-
File.join Trema.
|
51
|
+
File.join Trema.log, name
|
52
52
|
end
|
53
53
|
|
54
54
|
|
55
55
|
def new_tmp_log
|
56
|
-
system "rm #{ Trema.
|
57
|
-
`mktemp --tmpdir=#{ Trema.
|
56
|
+
system "rm #{ Trema.log }/tmp.*" # cleanup
|
57
|
+
`mktemp --tmpdir=#{ Trema.log }`.chomp
|
58
58
|
end
|
59
59
|
|
60
60
|
|
data/ruby/trema/command/kill.rb
CHANGED
@@ -47,7 +47,7 @@ module Trema
|
|
47
47
|
context = Trema::DSL::Context.load_current
|
48
48
|
|
49
49
|
# [FIXME] Trema apps does not appear in context.apps. why?
|
50
|
-
pid_file = File.join( Trema.
|
50
|
+
pid_file = File.join( Trema.pid, "#{ ARGV[ 0 ] }.pid" )
|
51
51
|
if FileTest.exist?( pid_file )
|
52
52
|
Trema::Process.read( pid_file ).kill!
|
53
53
|
end
|
data/ruby/trema/daemon.rb
CHANGED
@@ -111,9 +111,9 @@ module Trema
|
|
111
111
|
def pid_file
|
112
112
|
prefix = self.class.name.demodulize.underscore
|
113
113
|
if self.class.class_eval { class_variable_get :@@singleton_daemon }
|
114
|
-
File.join Trema.
|
114
|
+
File.join Trema.pid, "#{ prefix }.pid"
|
115
115
|
else
|
116
|
-
File.join Trema.
|
116
|
+
File.join Trema.pid, "#{ prefix }.#{ daemon_id }.pid"
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
@@ -134,7 +134,7 @@ module Trema
|
|
134
134
|
end
|
135
135
|
return nil if log_file_block.nil?
|
136
136
|
name = log_file_block.call( self )
|
137
|
-
File.join Trema.
|
137
|
+
File.join Trema.log, name
|
138
138
|
end
|
139
139
|
|
140
140
|
|
data/ruby/trema/executables.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
#
|
2
|
-
# Trema executables.
|
3
|
-
#
|
4
2
|
# Author: Yasuhito Takamiya <yasuhito@gmail.com>
|
5
3
|
#
|
6
4
|
# Copyright (C) 2008-2012 NEC Corporation
|
@@ -20,71 +18,55 @@
|
|
20
18
|
#
|
21
19
|
|
22
20
|
|
21
|
+
require "trema/monkey-patch/module"
|
22
|
+
require "trema/monkey-patch/string"
|
23
23
|
require "trema/path"
|
24
24
|
|
25
25
|
|
26
|
+
#
|
27
|
+
# Holds the list of executalbes found in {Trema.objects} directory.
|
28
|
+
#
|
26
29
|
class Trema::Executables
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
File.join Trema.objects, "tremashark/packet_capture"
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
def self.syslog_relay
|
38
|
-
File.join Trema.objects, "tremashark/syslog_relay"
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
def self.stdin_relay
|
43
|
-
File.join Trema.objects, "tremashark/stdin_relay"
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
def self.switch_manager
|
48
|
-
File.join Trema.objects, "switch_manager/switch_manager"
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
def self.switch
|
53
|
-
File.join Trema.objects, "switch_manager/switch"
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
def self.packetin_filter
|
58
|
-
File.join Trema.objects, "packetin_filter/packetin_filter"
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
|
-
def self.phost
|
63
|
-
File.join Trema.objects, "phost/phost"
|
64
|
-
end
|
30
|
+
class << self
|
31
|
+
def compiled?
|
32
|
+
@list.each do | each |
|
33
|
+
return false if not FileTest.executable?( __send__ each )
|
34
|
+
end
|
35
|
+
end
|
65
36
|
|
66
37
|
|
67
|
-
|
68
|
-
|
69
|
-
|
38
|
+
############################################################################
|
39
|
+
private
|
40
|
+
############################################################################
|
70
41
|
|
71
42
|
|
72
|
-
|
73
|
-
|
74
|
-
|
43
|
+
def add name
|
44
|
+
@list ||= []
|
45
|
+
@list << name
|
46
|
+
end
|
75
47
|
|
76
48
|
|
77
|
-
|
78
|
-
|
49
|
+
def path path
|
50
|
+
name = File.basename( path ).underscore
|
51
|
+
define_class_method( name ) do
|
52
|
+
File.join Trema.objects, path
|
53
|
+
end
|
54
|
+
add name
|
55
|
+
end
|
79
56
|
end
|
80
57
|
|
81
58
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
59
|
+
path "openvswitch/bin/ovs-ofctl"
|
60
|
+
path "openvswitch/bin/ovs-openflowd"
|
61
|
+
path "packetin_filter/packetin_filter"
|
62
|
+
path "phost/cli"
|
63
|
+
path "phost/phost"
|
64
|
+
path "switch_manager/switch"
|
65
|
+
path "switch_manager/switch_manager"
|
66
|
+
path "tremashark/packet_capture"
|
67
|
+
path "tremashark/stdin_relay"
|
68
|
+
path "tremashark/syslog_relay"
|
69
|
+
path "tremashark/tremashark"
|
88
70
|
end
|
89
71
|
|
90
72
|
|
data/ruby/trema/link.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# Author: Yasuhito Takamiya <yasuhito@gmail.com>
|
3
|
+
#
|
4
|
+
# Copyright (C) 2008-2012 NEC Corporation
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License, version 2, as
|
8
|
+
# published by the Free Software Foundation.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License along
|
16
|
+
# with this program; if not, write to the Free Software Foundation, Inc.,
|
17
|
+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
18
|
+
#
|
19
|
+
|
20
|
+
|
21
|
+
module MonkeyPatch
|
22
|
+
module Module
|
23
|
+
module ClassMethod
|
24
|
+
def define_class_method name, &block
|
25
|
+
self.extend ::Module.new {
|
26
|
+
define_method name.to_s do
|
27
|
+
block.call
|
28
|
+
end
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
### Local variables:
|
37
|
+
### mode: Ruby
|
38
|
+
### coding: utf-8-unix
|
39
|
+
### indent-tabs-mode: nil
|
40
|
+
### End:
|
data/ruby/trema/open-vswitch.rb
CHANGED
data/ruby/trema/packet_in.c
CHANGED
@@ -26,6 +26,7 @@
|
|
26
26
|
|
27
27
|
extern VALUE mTrema;
|
28
28
|
VALUE cPacketIn;
|
29
|
+
VALUE mPacketInVTAG;
|
29
30
|
VALUE mPacketInARP;
|
30
31
|
VALUE mPacketInIPv4;
|
31
32
|
VALUE mPacketInICMPv4;
|
@@ -213,6 +214,77 @@ packet_in_eth_type( VALUE self ) {
|
|
213
214
|
}
|
214
215
|
|
215
216
|
|
217
|
+
/*
|
218
|
+
* Is a packet with VLAN tag?
|
219
|
+
*
|
220
|
+
* @return [bool] vtag? Is a packet with VLAN tag?
|
221
|
+
*/
|
222
|
+
static VALUE
|
223
|
+
packet_in_is_vtag( VALUE self ) {
|
224
|
+
if ( ( get_packet_in_info( self )->format & ETH_8021Q ) ) {
|
225
|
+
return Qtrue;
|
226
|
+
}
|
227
|
+
else {
|
228
|
+
return Qfalse;
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
232
|
+
|
233
|
+
/*
|
234
|
+
* The vlan tpid.
|
235
|
+
*
|
236
|
+
* @return [integer] vlan_tpid The vlan tpid
|
237
|
+
*/
|
238
|
+
static VALUE
|
239
|
+
packet_in_vlan_tpid( VALUE self ) {
|
240
|
+
return UINT2NUM( get_packet_in_info( self )->vlan_tpid );
|
241
|
+
}
|
242
|
+
|
243
|
+
|
244
|
+
/*
|
245
|
+
* The vlan tci.
|
246
|
+
*
|
247
|
+
* @return [integer] vlan_tci The vlan tci
|
248
|
+
*/
|
249
|
+
static VALUE
|
250
|
+
packet_in_vlan_tci( VALUE self ) {
|
251
|
+
return UINT2NUM( get_packet_in_info( self )->vlan_tci );
|
252
|
+
}
|
253
|
+
|
254
|
+
|
255
|
+
/*
|
256
|
+
* The vlan prio.
|
257
|
+
*
|
258
|
+
* @return [integer] vlan_prio The vlan prio
|
259
|
+
*/
|
260
|
+
static VALUE
|
261
|
+
packet_in_vlan_prio( VALUE self ) {
|
262
|
+
return UINT2NUM( ( unsigned int ) get_packet_in_info( self )->vlan_prio );
|
263
|
+
}
|
264
|
+
|
265
|
+
|
266
|
+
/*
|
267
|
+
* The vlan cfi.
|
268
|
+
*
|
269
|
+
* @return [integer] vlan_cfi The vlan cfi
|
270
|
+
*/
|
271
|
+
static VALUE
|
272
|
+
packet_in_vlan_cfi( VALUE self ) {
|
273
|
+
return UINT2NUM( ( unsigned int ) get_packet_in_info( self )->vlan_cfi );
|
274
|
+
}
|
275
|
+
|
276
|
+
|
277
|
+
/*
|
278
|
+
* The vlan vid.
|
279
|
+
*
|
280
|
+
* @return [integer] vlan_vid The vlan vid
|
281
|
+
*/
|
282
|
+
static VALUE
|
283
|
+
packet_in_vlan_vid( VALUE self ) {
|
284
|
+
return UINT2NUM( get_packet_in_info( self )->vlan_vid );
|
285
|
+
}
|
286
|
+
|
287
|
+
|
216
288
|
/*
|
217
289
|
* Is an ARP packet?
|
218
290
|
*
|
@@ -621,6 +693,17 @@ packet_in_igmp_group( VALUE self ) {
|
|
621
693
|
}
|
622
694
|
|
623
695
|
|
696
|
+
/*
|
697
|
+
* The IGMP checksum.
|
698
|
+
*
|
699
|
+
* @return [Integer] igmp_checksum a IGMP checksum.
|
700
|
+
*/
|
701
|
+
static VALUE
|
702
|
+
packet_in_igmp_checksum( VALUE self ) {
|
703
|
+
return UINT2NUM( get_packet_in_info( self )->igmp_checksum );
|
704
|
+
}
|
705
|
+
|
706
|
+
|
624
707
|
/*
|
625
708
|
* Is a TCP packet?
|
626
709
|
*
|
@@ -835,6 +918,7 @@ Init_packet_in() {
|
|
835
918
|
rb_define_method( cPacketIn, "macda", packet_in_macda, 0 );
|
836
919
|
rb_define_method( cPacketIn, "eth_type", packet_in_eth_type, 0 );
|
837
920
|
|
921
|
+
rb_define_method( cPacketIn, "vtag?", packet_in_is_vtag, 0 );
|
838
922
|
rb_define_method( cPacketIn, "arp?", packet_in_is_arp, 0 );
|
839
923
|
rb_define_method( cPacketIn, "ipv4?", packet_in_is_ipv4, 0 );
|
840
924
|
rb_define_method( cPacketIn, "icmpv4?", packet_in_is_icmpv4, 0 );
|
@@ -842,6 +926,13 @@ Init_packet_in() {
|
|
842
926
|
rb_define_method( cPacketIn, "tcp?", packet_in_is_tcp, 0 );
|
843
927
|
rb_define_method( cPacketIn, "udp?", packet_in_is_udp, 0 );
|
844
928
|
|
929
|
+
mPacketInVTAG = rb_define_module_under( mTrema, "PacketInVTAG" );
|
930
|
+
rb_define_method( mPacketInVTAG, "vlan_tpid", packet_in_vlan_tpid, 0 );
|
931
|
+
rb_define_method( mPacketInVTAG, "vlan_tci", packet_in_vlan_tci, 0 );
|
932
|
+
rb_define_method( mPacketInVTAG, "vlan_prio", packet_in_vlan_prio, 0 );
|
933
|
+
rb_define_method( mPacketInVTAG, "vlan_cfi", packet_in_vlan_cfi, 0 );
|
934
|
+
rb_define_method( mPacketInVTAG, "vlan_vid", packet_in_vlan_vid, 0 );
|
935
|
+
|
845
936
|
mPacketInARP = rb_define_module_under( mTrema, "PacketInARP" );
|
846
937
|
rb_define_method( mPacketInARP, "arp_oper", packet_in_arp_oper, 0 );
|
847
938
|
rb_define_method( mPacketInARP, "arp_sha", packet_in_arp_sha, 0 );
|
@@ -873,6 +964,7 @@ Init_packet_in() {
|
|
873
964
|
mPacketInIGMP = rb_define_module_under( mTrema, "PacketInIGMP" );
|
874
965
|
rb_define_method( mPacketInIGMP, "igmp_type", packet_in_igmp_type, 0 );
|
875
966
|
rb_define_method( mPacketInIGMP, "igmp_group", packet_in_igmp_group, 0 );
|
967
|
+
rb_define_method( mPacketInIGMP, "igmp_checksum", packet_in_igmp_checksum, 0 );
|
876
968
|
rb_define_method( mPacketInIGMP, "igmp_membership_query?", packet_in_is_igmp_membership_query, 0 );
|
877
969
|
rb_define_method( mPacketInIGMP, "igmp_v1_membership_report?", packet_in_is_igmp_v1_membership_report, 0 );
|
878
970
|
rb_define_method( mPacketInIGMP, "igmp_v2_membership_report?", packet_in_is_igmp_v2_membership_report, 0 );
|
@@ -916,6 +1008,10 @@ handle_packet_in( uint64_t datapath_id, packet_in message ) {
|
|
916
1008
|
|
917
1009
|
packet_info* info = ( packet_info * ) tmp->data->user_data;
|
918
1010
|
|
1011
|
+
if ( ( info->format & ETH_8021Q ) ) {
|
1012
|
+
rb_funcall( cPacketIn, rb_intern( "include" ), 1, mPacketInVTAG );
|
1013
|
+
}
|
1014
|
+
|
919
1015
|
if ( ( info->format & NW_ARP ) ) {
|
920
1016
|
rb_funcall( cPacketIn, rb_intern( "include" ), 1, mPacketInARP );
|
921
1017
|
}
|
data/ruby/trema/path.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
#
|
2
|
-
# Trema paths.
|
3
|
-
#
|
4
2
|
# Author: Yasuhito Takamiya <yasuhito@gmail.com>
|
5
3
|
#
|
6
4
|
# Copyright (C) 2008-2012 NEC Corporation
|
@@ -20,111 +18,63 @@
|
|
20
18
|
#
|
21
19
|
|
22
20
|
|
23
|
-
module
|
24
|
-
def self.home
|
25
|
-
File.expand_path File.join( File.dirname( __FILE__ ), "..", ".." )
|
26
|
-
end
|
21
|
+
require "trema/monkey-patch/module"
|
27
22
|
|
28
23
|
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
def self.cmockery
|
35
|
-
File.join objects, "cmockery"
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
def self.openvswitch
|
40
|
-
File.join objects, "openvswitch"
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
def self.cmockery_h
|
45
|
-
File.join cmockery, "include/google/cmockery.h"
|
46
|
-
end
|
47
|
-
|
48
|
-
|
49
|
-
def self.libcmockery_a
|
50
|
-
File.join cmockery, "lib/libcmockery.a"
|
51
|
-
end
|
52
|
-
|
53
|
-
|
54
|
-
def self.openflow
|
55
|
-
File.join objects, "openflow"
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
|
-
def self.openflow_h
|
60
|
-
File.join openflow, "openflow.h"
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
def self.oflops
|
65
|
-
File.join objects, "oflops"
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
|
-
def self.tmp
|
70
|
-
if ENV.key?( "TREMA_TMP" )
|
71
|
-
File.expand_path ENV[ "TREMA_TMP" ]
|
72
|
-
else
|
73
|
-
File.join home, "tmp"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
def self.log_directory
|
79
|
-
File.join tmp, "log"
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
|
-
def self.pid_directory
|
84
|
-
File.join tmp, "pid"
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
def self.sock_directory
|
89
|
-
File.join tmp, "sock"
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
module Vendor
|
94
|
-
def self.path
|
95
|
-
File.join Trema.home, "vendor"
|
96
|
-
end
|
97
|
-
|
98
|
-
|
99
|
-
def self.cmockery
|
100
|
-
File.join path, "cmockery-20110428"
|
101
|
-
end
|
24
|
+
module Trema
|
25
|
+
HOME = File.expand_path( File.join( File.dirname( __FILE__ ), "..", ".." ) )
|
102
26
|
|
103
27
|
|
104
|
-
|
105
|
-
|
28
|
+
class << self
|
29
|
+
def home
|
30
|
+
HOME
|
106
31
|
end
|
107
32
|
|
108
33
|
|
109
|
-
def
|
110
|
-
|
34
|
+
def tmp
|
35
|
+
if ENV.key?( "TREMA_TMP" )
|
36
|
+
File.expand_path ENV[ "TREMA_TMP" ]
|
37
|
+
else
|
38
|
+
File.join home, "tmp"
|
39
|
+
end
|
111
40
|
end
|
112
41
|
|
113
42
|
|
114
|
-
|
115
|
-
|
116
|
-
|
43
|
+
############################################################################
|
44
|
+
private
|
45
|
+
############################################################################
|
117
46
|
|
118
47
|
|
119
|
-
def
|
120
|
-
File.
|
48
|
+
def file base, path, name = nil
|
49
|
+
define_class_method( name || File.basename( path ).gsub( ".", "_" ) ) do
|
50
|
+
File.join __send__( base ), path
|
51
|
+
end
|
121
52
|
end
|
53
|
+
alias :dir :file
|
54
|
+
end
|
122
55
|
|
123
56
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
57
|
+
dir :home, "objects"
|
58
|
+
dir :home, "src/lib", :include
|
59
|
+
dir :home, "vendor"
|
60
|
+
dir :objects, "cmockery"
|
61
|
+
dir :objects, "lib"
|
62
|
+
dir :objects, "oflops"
|
63
|
+
dir :objects, "openflow"
|
64
|
+
dir :objects, "openvswitch"
|
65
|
+
dir :tmp, "log"
|
66
|
+
dir :tmp, "pid"
|
67
|
+
dir :tmp, "sock"
|
68
|
+
dir :vendor, "cmockery-20110428", :vendor_cmockery
|
69
|
+
dir :vendor, "oflops-0.03", :vendor_oflops
|
70
|
+
dir :vendor, "openflow-1.0.0", :vendor_openflow
|
71
|
+
dir :vendor, "openflow.git", :vendor_openflow_git
|
72
|
+
dir :vendor, "openvswitch-1.2.2", :vendor_openvswitch
|
73
|
+
dir :vendor, "phost", :vendor_phost
|
74
|
+
dir :vendor, "ruby-ifconfig-1.2", :vendor_ruby_ifconfig
|
75
|
+
file :cmockery, "include/google/cmockery.h"
|
76
|
+
file :cmockery, "lib/libcmockery.a"
|
77
|
+
file :openflow, "openflow.h"
|
128
78
|
end
|
129
79
|
|
130
80
|
|