Created
October 31, 2020 12:13
-
-
Save zeroFruit/2277640e0442430eb20e9a3dbf465384 to your computer and use it in GitHub Desktop.
Modeling the Internet from the scratch: Link-layer, LAN, Switch - Code snippet
This file contains 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 characters
package link | |
type Addr string |
This file contains 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 characters
package na | |
// Card is abstracted network adapter part to simulate bytes transport on | |
// physical cable. Node's interface uses this interface to send frame | |
// between nodes. | |
type Card interface { | |
Send(buf []byte, addr string) (time.Time, error) | |
Recv() <-chan *FrameData | |
} |
This file contains 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 characters
package link | |
type Link struct { | |
cost uint | |
ep1 EndPoint | |
ep2 EndPoint | |
} | |
func (l *Link) AttachEndpoint(ep EndPoint) error { | |
... | |
} | |
// Opposite returns other endpoint of given id. If other endpoint does not exist, | |
// then return error | |
func (l *Link) Opposite(id Id) (EndPoint, error) { | |
... | |
} | |
// EndPoint represents point of link. Link is the channel to pass data to end-point | |
// either side to the opposite | |
type EndPoint interface { | |
Id() Id | |
GetLink() *Link | |
AttachLink(link *Link) error | |
} |
This file contains 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 characters
package link | |
type Transmitter interface { | |
Transmit(frame []byte) error | |
} | |
type Interface interface { | |
Transmitter | |
EndPoint | |
Address() types.HwAddr | |
} | |
// NetHandler receives serialized frame payload. With this, doing some high-level protocol | |
type NetHandler interface { | |
Handle(pl []byte) | |
} | |
type Host struct { | |
Interface Interface | |
netHandler NetHandler | |
frmEnc *FrameEncoder | |
frmDec *FrameDecoder | |
} |
This file contains 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 characters
func Build() (host1 *link.Host, host2 *link.Host, host3 *link.Host, | |
swch1 *link.Switch, swch2 *link.Switch) { | |
// setup node | |
host1 = link.NewHost() | |
host2 = link.NewHost() | |
host3 = link.NewHost() | |
swch1 = link.NewSwitch() | |
swch2 = link.NewSwitch() | |
} |
This file contains 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 characters
func Build() (host1 *link.Host, host2 *link.Host, host3 *link.Host, | |
swch1 *link.Switch, swch2 *link.Switch) { | |
// setup node | |
... | |
// setup interface | |
intf1 := link.NewInterface(40001, link.AddrFromStr("11-11-11-11-11-11"), host1) | |
attachInterface(host1, intf1) | |
intf2 := link.NewInterface(40002, link.AddrFromStr("22-22-22-22-22-22"), host2) | |
attachInterface(host2, intf2) | |
intf3 := link.NewInterface(40003, link.AddrFromStr("33-33-33-33-33-33"), host3) | |
attachInterface(host3, intf3) | |
sp11 := link.NewSwitchPort(40004, swch1) | |
sp12 := link.NewSwitchPort(40005, swch1) | |
sp13 := link.NewSwitchPort(40006, swch1) | |
attachSwchInterface(swch1, sp11, "1") | |
attachSwchInterface(swch1, sp12, "2") | |
attachSwchInterface(swch1, sp13, "3") | |
sp21 := link.NewSwitchPort(40007, swch2) | |
sp22 := link.NewSwitchPort(40008, swch2) | |
attachSwchInterface(swch2, sp21, "1") | |
attachSwchInterface(swch2, sp22, "2") | |
} |
This file contains 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 characters
func Build() (host1 *link.Host, host2 *link.Host, host3 *link.Host, | |
swch1 *link.Switch, swch2 *link.Switch) { | |
// setup node | |
// setup interface | |
... | |
// setup link | |
link1 := link.NewLink(1) | |
attachLink(intf1, link1) | |
attachLink(sp11, link1) | |
link2 := link.NewLink(1) | |
attachLink(intf2, link2) | |
attachLink(sp12, link2) | |
link3 := link.NewLink(1) | |
attachLink(sp13, link3) | |
attachLink(sp21, link3) | |
link4 := link.NewLink(1) | |
attachLink(sp22, link4) | |
attachLink(intf3, link4) | |
return | |
} |
This file contains 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 characters
// Port can transmit data and can be point of link. But it has no hardware | |
// address. Before using Port, it must register its own Id | |
type Port interface { | |
Transmitter | |
EndPoint | |
Register(id Id) | |
Registered() bool | |
} |
This file contains 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 characters
type ForwardEntry struct { | |
// Incoming is port id attached to switch | |
Incoming Id | |
// Addr is destination node address | |
Addr types.HwAddr | |
// Time is timestamp when this entry is created | |
Time time.Time | |
} | |
type FrameForwardTable struct { | |
entries []ForwardEntry | |
} | |
type Switch struct { | |
PortList map[Id]Port | |
Table *FrameForwardTable | |
frmDec *FrameDecoder | |
frmEnc *FrameEncoder | |
} |
This file contains 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 characters
// Forward receives id of port it receives frame, address of sender | |
// and frame to send to receiver. Based on id and address it determines whether to | |
// broadcast frame or forward it to others, otherwise just discard frame. | |
func (s *Switch) Forward(incoming Id, frame na.Frame) error { | |
s.Table.Update(incoming, frame.Src) | |
frm, err := s.frmEnc.Encode(frame) | |
if err != nil { | |
return err | |
} | |
entry, ok := s.Table.LookupByAddr(frame.Dest) | |
if !ok { | |
return s.broadcastExcept(incoming, frm) | |
} | |
if entry.Incoming.Equal(incoming) { | |
log.Printf("discard frame from id: %s, src: %s, dest: %s\n", incoming, frame.Src, frame.Dest) | |
return nil | |
} | |
p := s.PortList[entry.Incoming] | |
if err := p.Transmit(frm); err != nil { | |
return err | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment