trema 0.2.7 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|