2014年1月8日水曜日

Tremaを試す ~simple-ruter その3~

今回はarp-table.rbを見ていきいます。
ソースの内容は前にlearning_switchのところで見たfdb.rbとよく似ています。

(arp-table.rb)
 1  class ARPEntry
 2    include Trema::DefaultLogger
 3  
 4    attr_reader :port
 5    attr_reader :hwaddr
 6    attr_writer :age_max
 7  
 8    def initialize port, hwaddr, age_max
 9      @port = port
10      @hwaddr = hwaddr
11      @age_max = age_max
12      @last_updated = Time.now
13      info "New entry: MAC addr = #{ @hwaddr.to_s }, port = #{ @port }"
14    end
15  
16    def update port, hwaddr
17      @port = port
18      @hwaddr = hwaddr
19      @last_updated = Time.now
20      info "Update entry: MAC addr = #{ @hwaddr.to_s }, port = #{ @port }"
21    end
22  
23    def aged_out?
24      aged_out = Time.now - @last_updated > @age_max
25      info "Age out: An ARP entry (MAC address = #{ @hwaddr.to_s }, port number = #{ @port }) has been aged-out" if aged_out
26      aged_out
27    end
28  end
29  
30  class ARPTable
31    DEFAULT_AGE_MAX = 300
32  
33    def initialize
34      @db = {}
35    end
36  
37    def update port, ipaddr, hwaddr
38      entry = @db[ ipaddr.to_i ]
39      if entry
40        entry.update( port, hwaddr )
41      else
42        new_entry = ARPEntry.new( port, hwaddr, DEFAULT_AGE_MAX )
43        @db[ ipaddr.to_i ] = new_entry
44      end
45    end
46  
47    def lookup ipaddr
48      @db[ ipaddr.to_i ]
49    end
50  
51    def age
52      @db.delete_if do | ipaddr, entry |
53        entry.aged_out?
54      end
55    end
56  end

このソースプログラムにはARPEntryクラスとARPTableクラスが書かれています。
ARPEntryクラスはARPTableクラスが使っているクラスなので、まずARPTableクラスから見ていきます。

31行目
DEFAULT_AGE_MAXは定数です。
ARPEntryクラスに渡され、arp情報の有効期限として指定されます。

33~35行目
initializeはクラスのオブジェクトが作成される時に実行されるメソッドです。
処理の内容は@db変数に空のハッシュを定義しています。
後の処理で@db変数のハッシュ値にARPEntryオブジェクトが代入されます。

37~45行目
updateメソッドは@db変数にハッシュ要素を追加、もしくはハッシュ値を更新するメソッドです。
まず、引数のIPアドレスをハッシュキーにして@db変数からハッシュ値を取得し、entry変数にセットしています。

ハッシュ値が取得できた場合は、ARPEntryクラスのupdateメソッドを実行して変数の値を更新します。
ハッシュ値が取得できなかった場合は、引数の物理ポート番号、macアドレス、DEFAULT_AGE_MAX定数を元に新たにARPEntryオブジェクトを作り、IPアドレスをハッシュキーにして@db変数にハッシュ要素を追加しています。

47~49行目
lookupメソッドは引数のIPアドレスに紐づくハッシュ値であるARPEntryのオブジェクトを返すメソッドです。

51~55行目
ageメソッドは@db変数から一定時間が経過したハッシュ要素を削除します。
ここでの一定時間は、定数「DEFAULT_AGE_MAX」の値で300秒になります。

ハッシュ値の削除はdelete_ifメソッドで行っています。
delete_ifは指定した条件にマッチした場合、ハッシュから要素を削除するメソッドです。
ここでの条件はARPEntryクラスのage_out?メソッドの結果です。

ipaddr変数にはハッシュキー、entry変数にはハッシュ値が入り、@dbの全ての要素に対して条件にマッチするか評価をします。

続いてARPEntryクラスを見ていきます。

2行目
includeでモジュールを読み込みます。
DefaultLoggerモジュールが使えるようになります。

4~6行目
アクセサの宣言をしています。
これで、クラスの外からインスタンス変数にアクセスすることができます。

8~14行目
initializeはARPEntryオブジェクトが作成される時に実行されます。
ここではオブジェクトを作成するときに指定した引数をインスタンス変数に代入しています。

@last_update変数にはRuby組み込みメソッドのTimeメソッドを使い現在時刻を代入しています。 infoメソッドでmacアドレスと物理ポート番号をログに出力します。

16~21行目
updateメソッドは、引数を元にインスタンス変数の値を更新します。
@port_no変数と@hwaddr変数の値は引数の物理ポート番号とmacアドレスの値に更新し、@last_update変数の値は現在時刻に書き換えます。
infoでmacアドレスと物理ポート番号をログに出力します。

23~27行目
aged_out?メソッドは、ARPEntryオブジェクトを作成、もしくはupdateメソッドを実行してから所定の時間が経過しているか否かを返します。
現在時刻から@last_update変数を引いた値が、FDBクラスの「DEFAULT_AGE_MAX」定数である300より大きい場合はaged_out変数にはtrueがセットされます。

25行目は、末尾に書かれたifの式がTrueの場合、左側の式が実行されます。
ここでは、age_out変数の値がTrueの場合は、infoメソッドでmacアドレスと物理ポート番号をログに出力します。
26行目は、24行目の式の結果(trueかfalse)をaged_out?メソッドの戻り値にしています。

今回は以上です。

0 件のコメント:

コメントを投稿