From 9a947b32a74e5f2866f12d9552e1265c3e3650a6 Mon Sep 17 00:00:00 2001 From: Nat Lasseter Date: Wed, 8 May 2024 14:23:26 +0100 Subject: Demo ends. For now... --- 03-switch3.rb | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 03-switch3.rb (limited to '03-switch3.rb') diff --git a/03-switch3.rb b/03-switch3.rb new file mode 100644 index 0000000..7cbdc2f --- /dev/null +++ b/03-switch3.rb @@ -0,0 +1,61 @@ +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 + frames = {} + @interfaces.each do |iface| + next if rand < 0.3 + + 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? + + frames[@count.to_s] = Frame2.new(iface, src, dst) + @count += 1 + end + frames + end + + def click + @fib = @next_fib + @next_fib = @fib.dup + end +end -- cgit v1.2.1