Class: DIY::MacLearner

Inherits:
Object
  • Object
show all
Defined in:
lib/diy/mac_learner.rb

Constant Summary collapse

BROAD_MAC =

ff:ff:ff:ff:ff:ff

"\377" * 6
GROUP_MAC =
1
LEARN_TIME =

five minutes

60 * 5

Instance Method Summary collapse

Constructor Details

#initialize(default_host = :A) ⇒ MacLearner

Returns a new instance of MacLearner.



6
7
8
9
# File 'lib/diy/mac_learner.rb', line 6

def initialize(default_host = :A)
  @default_host = default_host
  @table = {}
end

Instance Method Details

#_learn(mac, where) ⇒ Object



18
19
20
21
22
23
# File 'lib/diy/mac_learner.rb', line 18

def _learn(mac, where)
  # 除去组播与广播
  return if mac == BROAD_MAC
  return if mac[0] & GROUP_MAC == 1
  set(mac, where)
end

#clear(mac) ⇒ Object



45
46
47
# File 'lib/diy/mac_learner.rb', line 45

def clear(mac)
  @table[mac] = nil
end

#dumpObject



101
102
103
104
105
106
107
108
109
110
# File 'lib/diy/mac_learner.rb', line 101

def dump
  ret = "begin dumpping...\n"
  @table.each do |k, v|
    mac = Utils.pp_mac(k)
    ret += "#{mac} -> "
    ret += "#{v[0]}, "
    ret += "created at: #{ v[1].strftime("%H:%M:%S") }\n"
  end
  ret += "end dump...\n"
end

#get(mac) ⇒ Object



25
26
27
# File 'lib/diy/mac_learner.rb', line 25

def get(mac)
  @table[mac] && @table[mac][0]
end

#get_time(mac) ⇒ Object



29
30
31
# File 'lib/diy/mac_learner.rb', line 29

def get_time(mac)
  @table[mac] && @table[mac][1]
end

#learn(packet, where) ⇒ Object



12
13
14
15
16
# File 'lib/diy/mac_learner.rb', line 12

def learn(packet, where)
  raise "Only receive :A or B for where argument" unless where == :A or where == :B
  #~ @table.delete( src(packet) )
  _learn( src(packet), where)
end

#other(where) ⇒ Object



87
88
89
90
91
92
93
94
95
# File 'lib/diy/mac_learner.rb', line 87

def other(where)
  if where == :A
    return :B
  elsif where == :B
    return :A
  else
    raise "Argument error"
  end
end

#set(mac, where) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/diy/mac_learner.rb', line 33

def set(mac, where)
  time_now = Time.now
  if @table[mac]
    if @table[mac][0] != where
      if (time_now - @table[mac][1]) <= LEARN_TIME
        raise DIY::MacLearnConflictError, "Found mac learn port confict when set #{Utils.pp_mac(mac)} to #{where}"
      end
    end
  end
  @table[mac] = [ where, time_now ]
end

#sizeObject



97
98
99
# File 'lib/diy/mac_learner.rb', line 97

def size
  @table.size
end

#tellme(packet) ⇒ Object

报告包所在的端口 A or B 如果包不在学习表内, 返回缺省端口(默认为A)



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/diy/mac_learner.rb', line 51

def tellme(packet)
  valid!(packet)
  src_p = src(packet)
  dst_p = dst(packet)
  
  if src_p == dst_p
    DIY::Logger.debug("Found SRC mac is the same with DST mac: #{Utils.pp(packet)}")
    #~ where = @default_host
    #~ _learn(src_p, where)
    #~ return where
  end
  
  if src_p != dst_p && get(src_p) && get(src_p) == get(dst_p)
    #~ if (get_time(src_p) - get_time(dst_p)).abs <= LEARN_TIME
      #~ DIY::Logger.warn "Found the same mac learner: packet is #{Utils.pp(packet)}"
      raise DIY::MacLearnConflictError, "Found mac learn port confict"
    #~ else
      #~ cls = get_time(src_p) > get_time(dst_p) ? dst_p : src_p
      #~ clear(cls)
    #~ end
  end
  
  if get(src_p)
    where =  get(src_p)
    _learn( src_p, where )
  elsif get(dst_p)
    where = other( get(dst_p) )
    _learn( src_p, where )
  else
    where = @default_host
    _learn( src_p, where )
  end
  _learn( dst_p, other(where) )
  where
end