Last active
April 16, 2016 23:40
-
-
Save smihir/2d5446314a431b953760 to your computer and use it in GitHub Desktop.
Revisions
-
smihir revised this gist
Oct 20, 2015 . 2 changed files with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes.File renamed without changes. -
smihir revised this gist
Oct 20, 2015 . 2 changed files with 17 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -64,7 +64,11 @@ def run(self): self.net.send_packet(intf.name, packet) def learn(self, mac_addr, interface, time): if mac_addr == "ff:ff:ff:ff:ff:ff": log_debug("Do not learn BCAST mac") else: self.lookup_table[mac_addr] = (interface, time) def lookup(self, mac_addr): if mac_addr in self.lookup_table: @@ -84,4 +88,4 @@ def start(self): def switchy_main(net): ls = LearningSwitch(net) ls.start() This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -150,6 +150,17 @@ def switch_tests(): testpkt = mk_pkt("30:00:00:00:00:02", "20:00:00:00:00:03", "172.16.42.2", "192.168.1.101") s.expect(PacketInputEvent("eth1", testpkt, display=Ethernet), "An Ethernet frame with 20:00:00:00:00:03 destination address should arrive on eth1") s.expect(PacketOutputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame should arrive on eth0") # test case 3: a frame with dest address of one of the interfaces should # result in nothing happening reqpkt = mk_pkt("ff:ff:ff:ff:ff:ff", "10:00:00:00:00:03", '255.255.255.255','172.16.42.2') s.expect(PacketInputEvent("eth0", reqpkt, display=Ethernet), "Negative test case: packet with bcast destination on eth0") s.expect(PacketInputTimeoutEvent(1.0), "The hub should not do anything in response to a frame arriving with a destination address referring to the hub itself.") testpkt = mk_pkt("20:00:00:00:00:03", "ff:ff:ff:ff:ff:ff", '192.168.1.101', '255.255.255.255') s.expect(PacketInputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth2") s.expect(PacketOutputEvent("eth1", testpkt, "eth2", testpkt, display=Ethernet), "An Ethernet frame should be flooded on eth1 and eth2") return s scenario = switch_tests() -
smihir revised this gist
Oct 19, 2015 . 1 changed file with 155 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,155 @@ #!/usr/bin/env python import sys from switchyard.lib.address import * from switchyard.lib.packet import * from switchyard.lib.common import * from switchyard.lib.testing import * def mk_pkt(hwsrc, hwdst, ipsrc, ipdst, reply=False): ether = Ethernet() ether.src = EthAddr(hwsrc) ether.dst = EthAddr(hwdst) ether.ethertype = EtherType.IP ippkt = IPv4() ippkt.srcip = IPAddr(ipsrc) ippkt.dstip = IPAddr(ipdst) ippkt.protocol = IPProtocol.ICMP ippkt.ttl = 32 icmppkt = ICMP() if reply: icmppkt.icmptype = ICMPType.EchoReply else: icmppkt.icmptype = ICMPType.EchoRequest return ether + ippkt + icmppkt def switch_tests(): s = Scenario("switch tests") s.add_interface('eth0', '10:00:00:00:00:01') s.add_interface('eth1', '10:00:00:00:00:02') s.add_interface('eth2', '10:00:00:00:00:03') # test case 1: a frame with broadcast destination should get sent out # all ports except ingress testpkt = mk_pkt("30:00:00:00:00:02", "ff:ff:ff:ff:ff:ff", "172.16.42.2", "255.255.255.255") s.expect(PacketInputEvent("eth1", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth1") s.expect(PacketOutputEvent("eth0", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth0 and eth2") # test case 2: a frame with any unicast address except one assigned to learning switch # interface should be sent out all ports except ingress reqpkt = mk_pkt("20:00:00:00:00:01", "30:00:00:00:00:02", '192.168.1.100','172.16.42.2') s.expect(PacketInputEvent("eth0", reqpkt, display=Ethernet), "An Ethernet frame from 20:00:00:00:00:01 to 30:00:00:00:00:02 should arrive on eth0") s.expect(PacketOutputEvent("eth1", reqpkt, display=Ethernet), "Ethernet frame destined for 30:00:00:00:00:02 should be sent out on eth1") resppkt = mk_pkt("30:00:00:00:00:02", "20:00:00:00:00:01", '172.16.42.2', '192.168.1.100', reply=True) s.expect(PacketInputEvent("eth1", resppkt, display=Ethernet), "An Ethernet frame from 30:00:00:00:00:02 to 20:00:00:00:00:01 should arrive on eth1") s.expect(PacketOutputEvent("eth0", resppkt, display=Ethernet), "Ethernet frame destined to 20:00:00:00:00:01 should be sent out on eth0") # test case 3: a frame with dest address of one of the interfaces should # result in nothing happening reqpkt = mk_pkt("20:00:00:00:00:02", "10:00:00:00:00:03", '192.168.1.100','172.16.42.2') s.expect(PacketInputEvent("eth2", reqpkt, display=Ethernet), "An Ethernet frame should arrive on eth2 with destination address the same as eth2's MAC address") s.expect(PacketInputTimeoutEvent(1.0), "The hub should not do anything in response to a frame arriving with a destination address referring to the hub itself.") s.expect(PacketInputTimeoutEvent(10), "Silence") testpkt = mk_pkt("30:00:00:00:00:02", "ff:ff:ff:ff:ff:ff", "172.16.42.2", "255.255.255.255") s.expect(PacketInputEvent("eth1", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth1") s.expect(PacketOutputEvent("eth0", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth0 and eth2") resppkt = mk_pkt("20:00:00:00:00:01", "ff:ff:ff:ff:ff:ff", '172.16.42.2', '255.255.255.255') s.expect(PacketInputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth0") s.expect(PacketOutputEvent("eth1", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth1 and eth2") s.expect(PacketInputTimeoutEvent(10), "Silence") testpkt = mk_pkt("30:00:00:00:00:02", "ff:ff:ff:ff:ff:ff", "172.16.42.2", "255.255.255.255") s.expect(PacketInputEvent("eth1", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth1") s.expect(PacketOutputEvent("eth0", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth0 and eth2") resppkt = mk_pkt("20:00:00:00:00:01", "ff:ff:ff:ff:ff:ff", '172.16.42.2', '255.255.255.255') s.expect(PacketInputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth0") s.expect(PacketOutputEvent("eth1", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth1 and eth2") s.expect(PacketInputTimeoutEvent(10), "Silence") testpkt = mk_pkt("30:00:00:00:00:02", "ff:ff:ff:ff:ff:ff", "172.16.42.2", "255.255.255.255") s.expect(PacketInputEvent("eth1", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth1") s.expect(PacketOutputEvent("eth0", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth0 and eth2") resppkt = mk_pkt("20:00:00:00:00:01", "ff:ff:ff:ff:ff:ff", '172.16.42.2', '255.255.255.255') s.expect(PacketInputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth0") s.expect(PacketOutputEvent("eth1", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth1 and eth2") s.expect(PacketInputTimeoutEvent(10), "Silence") testpkt = mk_pkt("30:00:00:00:00:02", "ff:ff:ff:ff:ff:ff", "172.16.42.2", "255.255.255.255") s.expect(PacketInputEvent("eth1", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth1") s.expect(PacketOutputEvent("eth0", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth0 and eth2") resppkt = mk_pkt("20:00:00:00:00:01", "ff:ff:ff:ff:ff:ff", '172.16.42.2', '255.255.255.255') s.expect(PacketInputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth0") s.expect(PacketOutputEvent("eth1", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth1 and eth2") s.expect(PacketInputTimeoutEvent(10), "Silence") testpkt = mk_pkt("30:00:00:00:00:02", "ff:ff:ff:ff:ff:ff", "172.16.42.2", "255.255.255.255") s.expect(PacketInputEvent("eth1", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth1") s.expect(PacketOutputEvent("eth0", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth0 and eth2") testpkt = mk_pkt("20:00:00:00:00:01", "ff:ff:ff:ff:ff:ff", '172.16.42.2', '255.255.255.255') s.expect(PacketInputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth0") s.expect(PacketOutputEvent("eth1", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth1 and eth2") s.expect(PacketInputTimeoutEvent(10), "Silence") testpkt = mk_pkt("30:00:00:00:00:02", "ff:ff:ff:ff:ff:ff", "172.16.42.2", "255.255.255.255") s.expect(PacketInputEvent("eth1", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth1") s.expect(PacketOutputEvent("eth0", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth0 and eth2") testpkt = mk_pkt("20:00:00:00:00:01", "ff:ff:ff:ff:ff:ff", '172.16.42.2', '255.255.255.255') s.expect(PacketInputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth0") s.expect(PacketOutputEvent("eth1", testpkt, "eth2", testpkt, display=Ethernet), "The Ethernet frame with a broadcast destination address should be forwarded out ports eth1 and eth2") s.expect(PacketInputTimeoutEvent(10), "Silence") reqpkt = mk_pkt("20:00:00:00:00:01", "20:00:00:00:00:02", '192.168.100.1','192.168.1.100') s.expect(PacketInputEvent("eth0", reqpkt, display=Ethernet), "An Ethernet frame should arrive on eth0 with destination address for eth2") s.expect(PacketOutputEvent("eth1", reqpkt, "eth2", reqpkt, display=Ethernet), "The ethernet frame should be flooded in eth1 and eth2") reqpkt = mk_pkt("20:00:00:00:00:02", "20:00:00:00:00:01", '192.168.1.100','192.168.100.1', reply=True) s.expect(PacketInputEvent("eth2", reqpkt, display=Ethernet), "An Ethernet frame should arrive on eth2 destined for eth0") s.expect(PacketOutputEvent("eth0", reqpkt, display=Ethernet), "The reply ethernet frame should be sent on eth0") testpkt = mk_pkt("20:00:00:00:00:03", "ff:ff:ff:ff:ff:ff", '192.168.1.101', '255.255.255.255') s.expect(PacketInputEvent("eth2", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth2") s.expect(PacketOutputEvent("eth0", testpkt, "eth1", testpkt, display=Ethernet), "The reply ethernet frame should be flooded on eth0 and eth1") reqpkt = mk_pkt("20:00:00:00:00:01", "20:00:00:00:00:03", '192.168.100.1','192.168.1.101') s.expect(PacketInputEvent("eth0", reqpkt, display=Ethernet), "An Ethernet frame should arrive on eth0 with destination address for eth2") s.expect(PacketOutputEvent("eth2", reqpkt, display=Ethernet), "The ethernet frame should be sent on eth2") testpkt = mk_pkt("20:00:00:00:00:03", "ff:ff:ff:ff:ff:ff", '192.168.1.101', '255.255.255.255') s.expect(PacketInputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame with a broadcast destination address should arrive on eth2") s.expect(PacketOutputEvent("eth1", testpkt, "eth2", testpkt, display=Ethernet), "An Ethernet frame should be flooded on eth1 and eth2") testpkt = mk_pkt("30:00:00:00:00:02", "20:00:00:00:00:03", "172.16.42.2", "192.168.1.101") s.expect(PacketInputEvent("eth1", testpkt, display=Ethernet), "An Ethernet frame with 20:00:00:00:00:03 destination address should arrive on eth1") s.expect(PacketOutputEvent("eth0", testpkt, display=Ethernet), "An Ethernet frame should arrive on eth0") return s scenario = switch_tests() -
smihir revised this gist
Oct 16, 2015 . 1 changed file with 71 additions and 38 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,45 +10,78 @@ from switchyard.lib.address import * from switchyard.lib.packet import * from switchyard.lib.common import * import time class LearningSwitch: def __init__(self, net): self.lookup_table = {} self.texpire = 24 self.net = net self.interfaces = net.interfaces() self.macs = [intf.ethaddr for intf in self.interfaces] def run(self): while True: try: # Don't use the timestamp in recv_packet # it looks like the timestamp is just representing # the packet number received while running in test mode dev,packet = self.net.recv_packet(timeout=self.texpire/3) except NoPackets: self.timeout += 1 if self.timeout == 3: self.purge_lookup() continue except Shutdown: return ts = time.time() self.timeout = 0 self.learn(packet[0].src, dev, ts) log_debug ("In {} received packet {} on {}".format(self.net.name, packet, dev)) if packet[0].dst in self.macs: log_debug ("Packet intended for me") else: entry = self.lookup(packet[0].dst) log_debug ("lookup on {}: {}".format(packet[0].dst, entry)) if entry: if ts < entry[1] + self.texpire: dst_dev = entry[0] log_debug ("Sending packet {} to {}".format(packet, dst_dev)) self.net.send_packet(dst_dev, packet) continue else: # Clear entry from lookup and Flood!!! self.del_lookup_entry(packet[0].dst) for intf in self.interfaces: if dev != intf.name: log_debug ("Flooding packet {} to {}".format(packet, intf.name)) self.net.send_packet(intf.name, packet) def learn(self, mac_addr, interface, time): self.lookup_table[mac_addr] = (interface, time) def lookup(self, mac_addr): if mac_addr in self.lookup_table: return self.lookup_table[mac_addr] else: return None def del_lookup_entry(self, mac_addr): del self.lookup_table[mac_addr] def purge_lookup(self): self.lookup_table.clear() def start(self): self.run() self.net.shutdown() def switchy_main(net): ls = LearningSwitch(net) ls.start() -
smihir created this gist
Oct 11, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,54 @@ #!/usr/bin/env python3 ''' Ethernet learning switch in Python: HW3. Note that this file currently has the code to implement a "hub" in it, not a learning switch. (I.e., it's currently a switch that doesn't learn.) ''' from switchyard.lib.address import * from switchyard.lib.packet import * from switchyard.lib.common import * def learn(dev, packet, lookuptable): lookuptable[packet[0].src] = dev def switchy_main(net): my_interfaces = net.interfaces() mymacs = [intf.ethaddr for intf in my_interfaces] lookuptable = dict() quite_time = 0 tm = 9 while True: try: dev,packet = net.recv_packet(timeout=7) except NoPackets: quite_time += tm if quite_time >= 3*tm: lookuptable.clear() continue except Shutdown: return quite_time = 0 learn(dev, packet, lookuptable) log_failure ("In {} received packet {} on {}".format(net.name, packet, dev)) if packet[0].dst in mymacs: log_failure ("Packet intended for me") else: if packet[0].dst in lookuptable: dst_dev = lookuptable[packet[0].dst] for intf in my_interfaces: if dst_dev == intf.name: log_failure ("Sending packet {} to {}".format(packet, intf.name)) net.send_packet(intf.name, packet) continue for intf in my_interfaces: if dev != intf.name: log_failure ("Flooding packet {} to {}".format(packet, intf.name)) net.send_packet(intf.name, packet) net.shutdown()