trema 0.2.7 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. data/Rakefile +1 -0
  2. data/Rantfile +14 -13
  3. data/features/example.openflow_message.echo.feature +59 -0
  4. data/features/{example.message.hello.feature → example.openflow_message.hello.feature} +0 -0
  5. data/ruby/trema/mac.rb +2 -0
  6. data/ruby/trema/set-eth-dst-addr.rb +3 -2
  7. data/ruby/trema/set-eth-src-addr.rb +3 -2
  8. data/ruby/trema/version.rb +1 -1
  9. data/spec/spec_helper.rb +1 -0
  10. data/spec/trema/set-eth-dst-addr_spec.rb +6 -0
  11. data/spec/trema/set-eth-src-addr_spec.rb +6 -0
  12. data/src/examples/openflow_message/{echo_request.c → echo.c} +12 -2
  13. data/src/examples/openflow_message/{echo-request.rb → echo.rb} +2 -2
  14. data/src/examples/openflow_switch/echo_switch.c +89 -0
  15. data/src/examples/openflow_switch/hello_switch.c +24 -20
  16. data/src/examples/simple_router/arp-table.rb +92 -0
  17. data/src/examples/simple_router/interface.rb +99 -0
  18. data/src/examples/simple_router/router-utils.rb +211 -0
  19. data/src/examples/simple_router/routing-table.rb +67 -0
  20. data/src/examples/simple_router/simple-router.rb +180 -0
  21. data/src/examples/simple_router/simple_router.conf +18 -0
  22. data/src/examples/simple_router/simple_router_netns.conf +15 -0
  23. data/src/examples/simple_router/simple_router_network.conf +6 -0
  24. data/src/tremashark/plugin/packet-trema/packet-trema.c +8 -8
  25. metadata +17 -11
  26. data/features/example.message.echo_reply.feature +0 -26
  27. data/features/example.message.echo_request.feature +0 -25
  28. data/src/examples/openflow_message/echo-reply.rb +0 -59
  29. data/src/examples/openflow_message/echo_reply.c +0 -70
data/Rakefile CHANGED
@@ -53,6 +53,7 @@ begin
53
53
  RSpec::Core::RakeTask.new( :rcov ) do | spec |
54
54
  spec.pattern = "spec/**/*_spec.rb"
55
55
  spec.rcov = true
56
+ spec.rcov_opts = [ "-x", "gems" ]
56
57
  end
57
58
  rescue LoadError
58
59
  $stderr.puts $!.to_s
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 => Trema.objects do
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
- "echo_reply",
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/
data/ruby/trema/mac.rb CHANGED
@@ -63,6 +63,8 @@ module Trema
63
63
  when Integer
64
64
  @value = value
65
65
  validate_value_range
66
+ when Mac
67
+ @value = create_from( value.to_s )
66
68
  else
67
69
  raise TypeError, "Invalid MAC address: #{ value.inspect }"
68
70
  end
@@ -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
@@ -17,7 +17,7 @@
17
17
 
18
18
 
19
19
  module Trema
20
- VERSION = "0.2.7"
20
+ VERSION = "0.2.8"
21
21
  end
22
22
 
23
23
 
data/spec/spec_helper.rb CHANGED
@@ -25,6 +25,7 @@ $LOAD_PATH.unshift File.expand_path( File.join File.dirname( __FILE__ ), "..", "
25
25
  require "rubygems"
26
26
 
27
27
  require "rspec"
28
+ require "rspec/autorun"
28
29
  require "trema"
29
30
  require "trema/dsl/configuration"
30
31
  require "trema/dsl/context"
@@ -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 EchoRequestController < Controller
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
- EchoRequestController.run ARGV
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 tid, void *user_data ) {
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
- buffer *msg = create_features_reply( tid, get_datapath_id(), 0, 1, 0, supported, NULL );
45
-
46
- switch_send_openflow_message( msg );
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 tid, uint8_t version, void *user_data ) {
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( tid ) );
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: