trema 0.2.7 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -0
- data/Rantfile +14 -13
- data/features/example.openflow_message.echo.feature +59 -0
- data/features/{example.message.hello.feature → example.openflow_message.hello.feature} +0 -0
- data/ruby/trema/mac.rb +2 -0
- data/ruby/trema/set-eth-dst-addr.rb +3 -2
- data/ruby/trema/set-eth-src-addr.rb +3 -2
- data/ruby/trema/version.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/trema/set-eth-dst-addr_spec.rb +6 -0
- data/spec/trema/set-eth-src-addr_spec.rb +6 -0
- data/src/examples/openflow_message/{echo_request.c → echo.c} +12 -2
- data/src/examples/openflow_message/{echo-request.rb → echo.rb} +2 -2
- data/src/examples/openflow_switch/echo_switch.c +89 -0
- data/src/examples/openflow_switch/hello_switch.c +24 -20
- data/src/examples/simple_router/arp-table.rb +92 -0
- data/src/examples/simple_router/interface.rb +99 -0
- data/src/examples/simple_router/router-utils.rb +211 -0
- data/src/examples/simple_router/routing-table.rb +67 -0
- data/src/examples/simple_router/simple-router.rb +180 -0
- data/src/examples/simple_router/simple_router.conf +18 -0
- data/src/examples/simple_router/simple_router_netns.conf +15 -0
- data/src/examples/simple_router/simple_router_network.conf +6 -0
- data/src/tremashark/plugin/packet-trema/packet-trema.c +8 -8
- metadata +17 -11
- data/features/example.message.echo_reply.feature +0 -26
- data/features/example.message.echo_request.feature +0 -25
- data/src/examples/openflow_message/echo-reply.rb +0 -59
- data/src/examples/openflow_message/echo_reply.c +0 -70
data/Rakefile
CHANGED
data/Rantfile
CHANGED
@@ -235,8 +235,9 @@ task :distclean => [
|
|
235
235
|
gen Directory, Trema.objects
|
236
236
|
|
237
237
|
task "vendor:openflow" => Trema.openflow_h
|
238
|
-
file Trema.openflow_h
|
238
|
+
file Trema.openflow_h do
|
239
239
|
sys.unpack_tgz "#{ Trema.vendor_openflow }.tar.gz", :in => Trema.vendor
|
240
|
+
sys.mkdir_p Trema.objects
|
240
241
|
sys.cp_r "#{ Trema.vendor_openflow }/include/openflow", Trema.objects
|
241
242
|
sys "chmod -R +r #{ File.join Trema.objects, "openflow" }"
|
242
243
|
end
|
@@ -379,7 +380,7 @@ end
|
|
379
380
|
task dependency( "libtrema" ) => "vendor:openflow"
|
380
381
|
gen C::Dependencies, dependency( "libtrema" ),
|
381
382
|
:search => [ Trema.include, objects( "openflow" ) ],
|
382
|
-
:sources => sys[ "#{ Trema.include }/*.c" ]
|
383
|
+
:sources => sys[ "#{ Trema.include }/*.{c,h}" ]
|
383
384
|
|
384
385
|
gen Action do
|
385
386
|
source dependency( "libtrema" )
|
@@ -448,7 +449,7 @@ end
|
|
448
449
|
switch_manager_objects_dir = objects( "switch_manager" )
|
449
450
|
|
450
451
|
gen C::Dependencies, dependency( "switch_manager" ),
|
451
|
-
:search => [ "src/switch_manager", Trema.include ], :sources => sys[ "src/switch_manager/*.c" ]
|
452
|
+
:search => [ "src/switch_manager", Trema.include ], :sources => sys[ "src/switch_manager/*.{c,h}" ]
|
452
453
|
|
453
454
|
gen Action do
|
454
455
|
source dependency( "switch_manager" )
|
@@ -502,7 +503,7 @@ end
|
|
502
503
|
################################################################################
|
503
504
|
|
504
505
|
gen C::Dependencies, dependency( "packetin_filter" ),
|
505
|
-
:search => [ "src/packetin_filter", Trema.include ], :sources => sys[ "src/packetin_filter/*.c" ]
|
506
|
+
:search => [ "src/packetin_filter", Trema.include ], :sources => sys[ "src/packetin_filter/*.{c,h}" ]
|
506
507
|
|
507
508
|
gen Action do
|
508
509
|
source dependency( "packetin_filter" )
|
@@ -529,7 +530,7 @@ end
|
|
529
530
|
tremashark_objects_dir = objects( "tremashark" )
|
530
531
|
|
531
532
|
gen C::Dependencies, dependency( "tremashark" ),
|
532
|
-
:search => [ "src/tremashark", Trema.include ], :sources => sys[ "src/tremashark/*.c" ]
|
533
|
+
:search => [ "src/tremashark", Trema.include ], :sources => sys[ "src/tremashark/*.{c,h}" ]
|
533
534
|
|
534
535
|
gen Action do
|
535
536
|
source dependency( "tremashark" )
|
@@ -613,7 +614,7 @@ management_source_dir = "src/management"
|
|
613
614
|
management_objects_dir = objects( "management" )
|
614
615
|
|
615
616
|
gen C::Dependencies, dependency( "management" ),
|
616
|
-
:search => [ Trema.include ], :sources => sys[ "#{ management_source_dir }/*.c" ]
|
617
|
+
:search => [ Trema.include ], :sources => sys[ "#{ management_source_dir }/*.{c,h}" ]
|
617
618
|
|
618
619
|
gen Action do
|
619
620
|
source dependency( "management" )
|
@@ -660,7 +661,7 @@ standalone_examples.each do | each |
|
|
660
661
|
target = objects( "examples/#{ each }/#{ each }" )
|
661
662
|
|
662
663
|
gen C::Dependencies, dependency( each ),
|
663
|
-
:search => [ "src/examples/#{ each }", Trema.include ], :sources => sys[ "src/examples/#{ each }/*.c" ]
|
664
|
+
:search => [ "src/examples/#{ each }", Trema.include ], :sources => sys[ "src/examples/#{ each }/*.{c,h}" ]
|
664
665
|
|
665
666
|
gen Action do
|
666
667
|
source dependency( each )
|
@@ -688,13 +689,14 @@ end
|
|
688
689
|
|
689
690
|
openflow_switches = [
|
690
691
|
"hello_switch",
|
692
|
+
"echo_switch",
|
691
693
|
]
|
692
694
|
|
693
695
|
openflow_switch_source_dir = "src/examples/openflow_switch"
|
694
696
|
openflow_switch_objects_dir = objects( "examples/openflow_switch" )
|
695
697
|
|
696
698
|
gen C::Dependencies, dependency( "openflow_switch" ),
|
697
|
-
:search => [ Trema.include ], :sources => sys[ "#{ openflow_switch_source_dir }/*.c" ]
|
699
|
+
:search => [ Trema.include ], :sources => sys[ "#{ openflow_switch_source_dir }/*.{c,h}" ]
|
698
700
|
|
699
701
|
gen Action do
|
700
702
|
source dependency( "openflow_switch" )
|
@@ -722,8 +724,7 @@ end
|
|
722
724
|
################################################################################
|
723
725
|
|
724
726
|
openflow_messages = [
|
725
|
-
"
|
726
|
-
"echo_request",
|
727
|
+
"echo",
|
727
728
|
"features_request",
|
728
729
|
"hello",
|
729
730
|
"set_config",
|
@@ -734,7 +735,7 @@ openflow_message_source_dir = "src/examples/openflow_message"
|
|
734
735
|
openflow_message_objects_dir = objects( "examples/openflow_message" )
|
735
736
|
|
736
737
|
gen C::Dependencies, dependency( "openflow_message" ),
|
737
|
-
:search => [ Trema.include ], :sources => sys[ "#{ openflow_message_source_dir }/*.c" ]
|
738
|
+
:search => [ Trema.include ], :sources => sys[ "#{ openflow_message_source_dir }/*.{c,h}" ]
|
738
739
|
|
739
740
|
gen Action do
|
740
741
|
source dependency( "openflow_message" )
|
@@ -773,7 +774,7 @@ packetin_filter_config_source_dir = "src/examples/packetin_filter_config"
|
|
773
774
|
packetin_filter_config_objects_dir = objects( "examples/packetin_filter_config" )
|
774
775
|
|
775
776
|
gen C::Dependencies, dependency( "packetin_filter_config" ),
|
776
|
-
:search => [ Trema.include ], :sources => sys[ "#{ packetin_filter_config_source_dir }/*.c" ]
|
777
|
+
:search => [ Trema.include ], :sources => sys[ "#{ packetin_filter_config_source_dir }/*.{c,h}" ]
|
777
778
|
|
778
779
|
gen Action do
|
779
780
|
source dependency( "packetin_filter_config" )
|
@@ -836,7 +837,7 @@ end
|
|
836
837
|
|
837
838
|
|
838
839
|
gen C::Dependencies, dependency( "unittests" ),
|
839
|
-
:search => [ Trema.include, "unittests" ], :sources => sys[ "unittests/lib/*.c", "src/lib/*.c" ]
|
840
|
+
:search => [ Trema.include, "unittests" ], :sources => sys[ "unittests/lib/*.c", "src/lib/*.{c,h}" ]
|
840
841
|
|
841
842
|
gen Action do
|
842
843
|
source dependency( "unittests" )
|
@@ -0,0 +1,59 @@
|
|
1
|
+
Feature: Send echo request and receive echo reply messages
|
2
|
+
|
3
|
+
In order to hear heart beats from openflow switches
|
4
|
+
As a Trema user
|
5
|
+
I want to send echo request messages to openflow switches and receive echo replies
|
6
|
+
|
7
|
+
@slow_process
|
8
|
+
Scenario: Echo request and reply in C
|
9
|
+
Given a file named "echo.conf" with:
|
10
|
+
"""
|
11
|
+
custom_switch("echo") {
|
12
|
+
datapath_id "0xabc"
|
13
|
+
path "./objects/examples/openflow_switch/echo_switch"
|
14
|
+
}
|
15
|
+
"""
|
16
|
+
When I run `trema run "../../objects/examples/openflow_message/echo 10" -c echo.conf -d`
|
17
|
+
And wait until "echo" is up
|
18
|
+
And I run `trema killall`
|
19
|
+
Then the file "../../tmp/log/customswitch.echo.log" should contain:
|
20
|
+
"""
|
21
|
+
received: OFPT_ECHO_REQUEST
|
22
|
+
received: OFPT_ECHO_REQUEST
|
23
|
+
received: OFPT_ECHO_REQUEST
|
24
|
+
received: OFPT_ECHO_REQUEST
|
25
|
+
received: OFPT_ECHO_REQUEST
|
26
|
+
received: OFPT_ECHO_REQUEST
|
27
|
+
received: OFPT_ECHO_REQUEST
|
28
|
+
received: OFPT_ECHO_REQUEST
|
29
|
+
received: OFPT_ECHO_REQUEST
|
30
|
+
received: OFPT_ECHO_REQUEST
|
31
|
+
"""
|
32
|
+
And the file "../../tmp/log/echo.log" should match /received: OFPT_ECHO_REPLY/
|
33
|
+
|
34
|
+
@slow_process
|
35
|
+
Scenario: Echo request and reply in Ruby
|
36
|
+
Given a file named "echo.ruby.conf" with:
|
37
|
+
"""
|
38
|
+
custom_switch("echo.ruby") {
|
39
|
+
datapath_id "0xabc"
|
40
|
+
path "./objects/examples/openflow_switch/echo_switch"
|
41
|
+
}
|
42
|
+
"""
|
43
|
+
When I run `trema run "../../src/examples/openflow_message/echo.rb 0xabc, 10" -c echo.ruby.conf -d`
|
44
|
+
And wait until "EchoController" is up
|
45
|
+
And I run `trema killall`
|
46
|
+
Then the file "../../tmp/log/customswitch.echo.ruby.log" should contain:
|
47
|
+
"""
|
48
|
+
received: OFPT_ECHO_REQUEST
|
49
|
+
received: OFPT_ECHO_REQUEST
|
50
|
+
received: OFPT_ECHO_REQUEST
|
51
|
+
received: OFPT_ECHO_REQUEST
|
52
|
+
received: OFPT_ECHO_REQUEST
|
53
|
+
received: OFPT_ECHO_REQUEST
|
54
|
+
received: OFPT_ECHO_REQUEST
|
55
|
+
received: OFPT_ECHO_REQUEST
|
56
|
+
received: OFPT_ECHO_REQUEST
|
57
|
+
received: OFPT_ECHO_REQUEST
|
58
|
+
"""
|
59
|
+
# And the file "../../tmp/log/EchoController.log" should match /received: OFPT_ECHO_REPLY/
|
File without changes
|
data/ruby/trema/mac.rb
CHANGED
@@ -30,12 +30,13 @@ module Trema
|
|
30
30
|
# @example
|
31
31
|
# SetEthDstAddr.new("11:22:33:44:55:66")
|
32
32
|
# SetEthDstAddr.new(0x112233445566)
|
33
|
+
# SetEthDstAddr.new(mac)
|
33
34
|
#
|
34
|
-
# @param [String,Integer] mac_address
|
35
|
+
# @param [String,Integer,Mac] mac_address
|
35
36
|
# the Ethernet address to create this action with.
|
36
37
|
#
|
37
38
|
# @raise [ArgumentError] if invalid format is detected.
|
38
|
-
# @raise [TypeError] if supplied argument is not a String or Integer.
|
39
|
+
# @raise [TypeError] if supplied argument is not a String or Integer or Mac.
|
39
40
|
#
|
40
41
|
def initialize mac_address
|
41
42
|
super mac_address
|
@@ -30,12 +30,13 @@ module Trema
|
|
30
30
|
# @example
|
31
31
|
# SetEthSrcAddr.new("11:22:33:44:55:66")
|
32
32
|
# SetEthSrcAddr.new(0x112233445566)
|
33
|
+
# SetEthSrcAddr.new(mac)
|
33
34
|
#
|
34
|
-
# @param [String,Integer] mac_address
|
35
|
+
# @param [String,Integer,Mac] mac_address
|
35
36
|
# the Ethernet address to create this action with.
|
36
37
|
#
|
37
38
|
# @raise [ArgumentError] if invalid format is detected.
|
38
|
-
# @raise [TypeError] if supplied argument is not a String or Integer.
|
39
|
+
# @raise [TypeError] if supplied argument is not a String or Integer or Mac.
|
39
40
|
#
|
40
41
|
def initialize mac_address
|
41
42
|
super mac_address
|
data/ruby/trema/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -26,6 +26,12 @@ describe SetEthDstAddr, %{.new( "52:54:00:a8:ad:8c" )} do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
|
29
|
+
describe SetEthDstAddr, %{.new( Mac.new( "52:54:00:a8:ad:8c" ) )} do
|
30
|
+
subject { SetEthDstAddr.new( Mac.new( "52:54:00:a8:ad:8c" ) )}
|
31
|
+
its( :mac_address ) { should == Mac.new( "52:54:00:a8:ad:8c" ) }
|
32
|
+
end
|
33
|
+
|
34
|
+
|
29
35
|
describe SetEthDstAddr, %{.new( "INVALID MAC STRING" )} do
|
30
36
|
it { expect { SetEthDstAddr.new( "INVALID MAC STRING" ) }.to raise_error( ArgumentError ) }
|
31
37
|
end
|
@@ -26,6 +26,12 @@ describe SetEthSrcAddr, %{.new( "52:54:00:a8:ad:8c" )} do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
|
29
|
+
describe SetEthSrcAddr, %{.new( Mac.new( "52:54:00:a8:ad:8c" ) )} do
|
30
|
+
subject { SetEthSrcAddr.new( Mac.new( "52:54:00:a8:ad:8c" ) )}
|
31
|
+
its( :mac_address ) { should == Mac.new( "52:54:00:a8:ad:8c" ) }
|
32
|
+
end
|
33
|
+
|
34
|
+
|
29
35
|
describe SetEthSrcAddr, %{.new( "INVALID MAC STRING" )} do
|
30
36
|
it { expect { SetEthSrcAddr.new( "INVALID MAC STRING" ) }.to raise_error( ArgumentError ) }
|
31
37
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Sends echo_request messages to the specified datapath ID.
|
3
3
|
*
|
4
|
-
* Author: Shin-ya Zenke, Yasuhito Takamiya <yasuhito@gmail.com>
|
5
|
-
*
|
6
4
|
* Copyright (C) 2008-2012 NEC Corporation
|
7
5
|
*
|
8
6
|
* This program is free software; you can redistribute it and/or modify
|
@@ -44,6 +42,17 @@ send_echo_requests( uint64_t datapath_id, void *count ) {
|
|
44
42
|
}
|
45
43
|
|
46
44
|
|
45
|
+
static void
|
46
|
+
handle_echo_reply( uint64_t datapath_id, uint32_t xid, const buffer *data, void *user_data ) {
|
47
|
+
UNUSED( datapath_id );
|
48
|
+
UNUSED( xid );
|
49
|
+
UNUSED( data );
|
50
|
+
UNUSED( user_data );
|
51
|
+
|
52
|
+
info( "received: OFPT_ECHO_REPLY" );
|
53
|
+
}
|
54
|
+
|
55
|
+
|
47
56
|
int
|
48
57
|
main( int argc, char *argv[] ) {
|
49
58
|
init_trema( &argc, &argv );
|
@@ -55,6 +64,7 @@ main( int argc, char *argv[] ) {
|
|
55
64
|
|
56
65
|
int count = atoi( argv[ 1 ] );
|
57
66
|
set_switch_ready_handler( send_echo_requests, &count );
|
67
|
+
set_echo_reply_handler( handle_echo_reply, NULL );
|
58
68
|
|
59
69
|
start_trema();
|
60
70
|
|
@@ -23,7 +23,7 @@
|
|
23
23
|
require "example"
|
24
24
|
|
25
25
|
|
26
|
-
class
|
26
|
+
class EchoController < Controller
|
27
27
|
include Example
|
28
28
|
|
29
29
|
|
@@ -48,7 +48,7 @@ class EchoRequestController < Controller
|
|
48
48
|
end
|
49
49
|
|
50
50
|
|
51
|
-
|
51
|
+
EchoController.run ARGV
|
52
52
|
|
53
53
|
|
54
54
|
### Local variables:
|
@@ -0,0 +1,89 @@
|
|
1
|
+
/*
|
2
|
+
* A simple switch that has minimum function to test echo message.
|
3
|
+
*
|
4
|
+
* Copyright (C) 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
|
+
#include "chibach.h"
|
22
|
+
|
23
|
+
|
24
|
+
// FIXME: Copy & Paste from hello_switch.c
|
25
|
+
static void
|
26
|
+
handle_features_request( uint32_t xid, void *user_data ) {
|
27
|
+
UNUSED( user_data );
|
28
|
+
|
29
|
+
uint32_t supported = ( ( 1 << OFPAT_OUTPUT ) |
|
30
|
+
( 1 << OFPAT_SET_VLAN_VID ) |
|
31
|
+
( 1 << OFPAT_SET_VLAN_PCP ) |
|
32
|
+
( 1 << OFPAT_STRIP_VLAN ) |
|
33
|
+
( 1 << OFPAT_SET_DL_SRC ) |
|
34
|
+
( 1 << OFPAT_SET_DL_DST ) |
|
35
|
+
( 1 << OFPAT_SET_NW_SRC ) |
|
36
|
+
( 1 << OFPAT_SET_NW_DST ) |
|
37
|
+
( 1 << OFPAT_SET_NW_TOS ) |
|
38
|
+
( 1 << OFPAT_SET_TP_SRC ) |
|
39
|
+
( 1 << OFPAT_SET_TP_DST ) );
|
40
|
+
|
41
|
+
buffer *msg = create_features_reply( xid, get_datapath_id(), 0, 1, 0, supported, NULL );
|
42
|
+
|
43
|
+
switch_send_openflow_message( msg );
|
44
|
+
}
|
45
|
+
|
46
|
+
|
47
|
+
// FIXME: Copy & Paste from hello_switch.c
|
48
|
+
static void
|
49
|
+
handle_hello( uint32_t xid, uint8_t version, void *user_data ) {
|
50
|
+
UNUSED( version );
|
51
|
+
UNUSED( user_data );
|
52
|
+
|
53
|
+
switch_send_openflow_message( create_hello( xid ) );
|
54
|
+
}
|
55
|
+
|
56
|
+
|
57
|
+
static void
|
58
|
+
handle_echo_request( uint32_t xid, const buffer *body, void *user_data ) {
|
59
|
+
UNUSED( body );
|
60
|
+
UNUSED( user_data );
|
61
|
+
|
62
|
+
info( "received: OFPT_ECHO_REQUEST" );
|
63
|
+
|
64
|
+
switch_send_openflow_message( create_echo_reply( xid, NULL ) );
|
65
|
+
}
|
66
|
+
|
67
|
+
|
68
|
+
int
|
69
|
+
main( int argc, char **argv ) {
|
70
|
+
init_chibach( &argc, &argv );
|
71
|
+
|
72
|
+
set_hello_handler( handle_hello, NULL );
|
73
|
+
set_features_request_handler( handle_features_request, NULL );
|
74
|
+
set_echo_request_handler( handle_echo_request, NULL );
|
75
|
+
|
76
|
+
start_chibach();
|
77
|
+
|
78
|
+
stop_chibach();
|
79
|
+
|
80
|
+
return 0;
|
81
|
+
}
|
82
|
+
|
83
|
+
|
84
|
+
/*
|
85
|
+
* Local variables:
|
86
|
+
* c-basic-offset: 2
|
87
|
+
* indent-tabs-mode: nil
|
88
|
+
* End:
|
89
|
+
*/
|
@@ -21,40 +21,44 @@
|
|
21
21
|
#include "chibach.h"
|
22
22
|
|
23
23
|
|
24
|
-
static void handle_features_request( uint32_t, void * );
|
25
|
-
static void handle_hello( uint32_t, uint8_t, void * );
|
26
|
-
|
27
|
-
|
28
24
|
static void
|
29
|
-
handle_features_request( uint32_t
|
25
|
+
handle_features_request( uint32_t xid, void *user_data ) {
|
30
26
|
UNUSED( user_data );
|
31
27
|
|
32
|
-
uint32_t supported = ( ( 1 << OFPAT_OUTPUT ) |
|
33
|
-
( 1 << OFPAT_SET_VLAN_VID ) |
|
34
|
-
( 1 << OFPAT_SET_VLAN_PCP ) |
|
35
|
-
( 1 << OFPAT_STRIP_VLAN ) |
|
36
|
-
( 1 << OFPAT_SET_DL_SRC ) |
|
37
|
-
( 1 << OFPAT_SET_DL_DST ) |
|
38
|
-
( 1 << OFPAT_SET_NW_SRC ) |
|
39
|
-
( 1 << OFPAT_SET_NW_DST ) |
|
40
|
-
( 1 << OFPAT_SET_NW_TOS ) |
|
41
|
-
( 1 << OFPAT_SET_TP_SRC ) |
|
28
|
+
uint32_t supported = ( ( 1 << OFPAT_OUTPUT ) |
|
29
|
+
( 1 << OFPAT_SET_VLAN_VID ) |
|
30
|
+
( 1 << OFPAT_SET_VLAN_PCP ) |
|
31
|
+
( 1 << OFPAT_STRIP_VLAN ) |
|
32
|
+
( 1 << OFPAT_SET_DL_SRC ) |
|
33
|
+
( 1 << OFPAT_SET_DL_DST ) |
|
34
|
+
( 1 << OFPAT_SET_NW_SRC ) |
|
35
|
+
( 1 << OFPAT_SET_NW_DST ) |
|
36
|
+
( 1 << OFPAT_SET_NW_TOS ) |
|
37
|
+
( 1 << OFPAT_SET_TP_SRC ) |
|
42
38
|
( 1 << OFPAT_SET_TP_DST ) );
|
43
39
|
|
44
|
-
|
45
|
-
|
46
|
-
|
40
|
+
buffer *features_reply = create_features_reply(
|
41
|
+
xid,
|
42
|
+
get_datapath_id(),
|
43
|
+
0,
|
44
|
+
1,
|
45
|
+
0,
|
46
|
+
supported,
|
47
|
+
NULL
|
48
|
+
);
|
49
|
+
|
50
|
+
switch_send_openflow_message( features_reply );
|
47
51
|
}
|
48
52
|
|
49
53
|
|
50
54
|
static void
|
51
|
-
handle_hello( uint32_t
|
55
|
+
handle_hello( uint32_t xid, uint8_t version, void *user_data ) {
|
52
56
|
UNUSED( version );
|
53
57
|
UNUSED( user_data );
|
54
58
|
|
55
59
|
info( "received: OFPT_HELLO" );
|
56
60
|
|
57
|
-
switch_send_openflow_message( create_hello(
|
61
|
+
switch_send_openflow_message( create_hello( xid ) );
|
58
62
|
}
|
59
63
|
|
60
64
|
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#
|
2
|
+
# ARP processing routines
|
3
|
+
#
|
4
|
+
# Copyright (C) 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
|
+
class ARPEntry
|
22
|
+
include Trema::Logger
|
23
|
+
|
24
|
+
|
25
|
+
attr_reader :port
|
26
|
+
attr_reader :hwaddr
|
27
|
+
attr_writer :age_max
|
28
|
+
|
29
|
+
|
30
|
+
def initialize port, hwaddr, age_max
|
31
|
+
@port = port
|
32
|
+
@hwaddr = hwaddr
|
33
|
+
@age_max = age_max
|
34
|
+
@last_updated = Time.now
|
35
|
+
info "New entry: MAC addr = #{ @hwaddr.to_s }, port = #{ @port }"
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def update port, hwaddr
|
40
|
+
@port = port
|
41
|
+
@hwaddr = hwaddr
|
42
|
+
@last_updated = Time.now
|
43
|
+
info "Update entry: MAC addr = #{ @hwaddr.to_s }, port = #{ @port }"
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def aged_out?
|
48
|
+
aged_out = Time.now - @last_updated > @age_max
|
49
|
+
info "Age out: An ARP entry (MAC address = #{ @hwaddr.to_s }, port number = #{ @port }) has been aged-out" if aged_out
|
50
|
+
aged_out
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
class ARPTable
|
56
|
+
DEFAULT_AGE_MAX = 300
|
57
|
+
|
58
|
+
|
59
|
+
def initialize
|
60
|
+
@db = {}
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def update port, ipaddr, hwaddr
|
65
|
+
entry = @db[ ipaddr.to_i ]
|
66
|
+
if entry
|
67
|
+
entry.update( port, hwaddr )
|
68
|
+
else
|
69
|
+
new_entry = ARPEntry.new( port, hwaddr, DEFAULT_AGE_MAX )
|
70
|
+
@db[ ipaddr.to_i ] = new_entry
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def lookup ipaddr
|
76
|
+
@db[ ipaddr.to_i ]
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def age
|
81
|
+
@db.delete_if do | ipaddr, entry |
|
82
|
+
entry.aged_out?
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
### Local variables:
|
89
|
+
### mode: Ruby
|
90
|
+
### coding: utf-8-unix
|
91
|
+
### indent-tabs-mode: nil
|
92
|
+
### End:
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#
|
2
|
+
# A router implementation in Trema
|
3
|
+
#
|
4
|
+
# Copyright (C) 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
|
+
require "arp-table"
|
22
|
+
require "routing-table"
|
23
|
+
|
24
|
+
|
25
|
+
class Interface
|
26
|
+
attr_reader :hwaddr
|
27
|
+
attr_reader :ipaddr
|
28
|
+
attr_reader :masklen
|
29
|
+
attr_reader :port
|
30
|
+
|
31
|
+
|
32
|
+
def initialize options
|
33
|
+
@port = options[ :port ]
|
34
|
+
@hwaddr = Mac.new( options[ :hwaddr ] )
|
35
|
+
@ipaddr = IPAddr.new( options[ :ipaddr ] )
|
36
|
+
@masklen = options[ :masklen ]
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def has? mac
|
41
|
+
mac == hwaddr
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
class Interfaces
|
47
|
+
def initialize interfaces = []
|
48
|
+
@list = []
|
49
|
+
interfaces.each do | each |
|
50
|
+
@list << Interface.new( each )
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def find_by_port port
|
56
|
+
@list.find do | each |
|
57
|
+
each.port == port
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def find_by_ipaddr ipaddr
|
63
|
+
@list.find do | each |
|
64
|
+
each.ipaddr == ipaddr
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def find_by_prefix ipaddr
|
70
|
+
@list.find do | each |
|
71
|
+
masklen = each.masklen
|
72
|
+
each.ipaddr.mask( masklen ) == ipaddr.mask( masklen )
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def find_by_port_and_ipaddr port, ipaddr
|
78
|
+
@list.find do | each |
|
79
|
+
each.port == port and each.ipaddr == ipaddr
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def ours? port, macda
|
85
|
+
return true if macda.broadcast?
|
86
|
+
|
87
|
+
interface = find_by_port( port )
|
88
|
+
if not interface.nil? and interface.has?( macda )
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
### Local variables:
|
96
|
+
### mode: Ruby
|
97
|
+
### coding: utf-8
|
98
|
+
### indent-tabs-mode: nil
|
99
|
+
### End:
|