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.
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: