blob: f8809d7db264026bfef8a6d863ba4932400585db (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
require './level'
require './frame2'
$levels << Level.new do
@interfaces = %w(1 2 3)
@description = <<~EOD
You are now a three-port switch.
When a frame comes in on a port, you should keep track of the source address,
and any frames destined for that address in future clicks should only be
forwarded to that port. All other frames should be broadcast as before.
EOD
@clicks = 8
@fib = @interfaces.product([nil]).to_h
@next_fib = @fib.dup
def target(frame)
ifib = @fib.invert
if ifib.keys.include?(frame.dst_addr)
[frame.to(ifib[frame.dst_addr])]
else
case frame.iface
when ?1
[frame.to(?2), frame.to(?3)]
when ?2
[frame.to(?1), frame.to(?3)]
when ?3
[frame.to(?1), frame.to(?2)]
else
[]
end
end
end
def generate
iface = interfaces.sample
if rand < 0.4 || @fib[iface].nil?
src = Frame2.gen_addr
@next_fib[iface] = src
else
src = @fib[iface]
end
dst = nil
dst = (@fib.values.compact - [src]).sample if rand < 0.5
dst = Frame2.gen_addr if dst.nil?
frame = Frame2.new(iface, src, dst)
@count += 1
frame
end
def click
@fib = @next_fib
@next_fib = @fib.dup
end
end
|