From 1f926271bc80bcd6ff5ed52bb76a9ade347367b8 Mon Sep 17 00:00:00 2001 From: sotech117 Date: Mon, 23 Oct 2023 22:31:26 +0000 Subject: refactor and comment code. add more descriptive error message. --- README.md | 35 ++++++++--------------------- cmd/vhost/main.go | 2 +- cmd/vrouter/main.go | 4 ++-- pkg/ipstack/ipstack.go | 60 ++++++++++++++++++++++++------------------------- vhost | Bin 3105370 -> 3105122 bytes vrouter | Bin 3105378 -> 3105138 bytes 6 files changed, 42 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index e097c82..76f4ca4 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,23 @@ This project is an implementation of IP pipelines in Go. The project is split in ## Vrouter and Vhost Design Vrouter and Vhost follow similar designs, with a check to ensure than an lnxconfig file is passed into, to initialize the node with the parsed information from the lnxfiles. For both nodes we register the test protocol handler, and the rip protocol handler specifically for routers. We then listen for command line interfaces, while threads were initialized in the initialization. We follow the specifications of the handout having the following functions and functionality: +``` li: List interfaces lr: List routes ln: List available neighbors up: Enable an interface down: Disable an interface send: Send test packet +q/exit: Quit program +``` + Because the vhost and vrouter are so similar, we maintain most of the logic within the IPStack in which the vrouter and vhost call when necessary. -## IPStack Design -We build our abstractions for the IP layer and interfaces with the following structs: +## Abstractions + + +Using these two struct below, we abstract for the IP layer and interfaces with the following structs: type Interface struct { @@ -37,30 +43,7 @@ type Neighbor struct { } -type RIPHeader struct { - - command uint16 - numEntries uint16 - -} - -type RIPEntry struct { - - prefix netip.Prefix - cost uint32 - -} - -type Hop struct { - - Cost uint32 - Type string - Interface *Interface - VIP netip.Addr - -} - -With these structs, we are able to maintain the information necessary for the IPStack to function and for the vhost and vrouter to interact with its interfaces, neighbors, and routes when applicable. +With these structs, # Initialization/Main Thread diff --git a/cmd/vhost/main.go b/cmd/vhost/main.go index 3c35792..e83d1bf 100644 --- a/cmd/vhost/main.go +++ b/cmd/vhost/main.go @@ -61,7 +61,7 @@ func main() { messageToSendBytes := []byte(messageToSend) address, _ := netip.ParseAddr(ipAddr) - hop, err := ipstack.LongestPrefix(address) + hop, err := ipstack.Route(address) if err != nil { fmt.Println(err) continue diff --git a/cmd/vrouter/main.go b/cmd/vrouter/main.go index 0bc4d98..bc8cb2b 100644 --- a/cmd/vrouter/main.go +++ b/cmd/vrouter/main.go @@ -77,12 +77,12 @@ func main() { // get the longest prefix match for the destination address, _ := netip.ParseAddr(ipAddr) - hop, err := ipstack.LongestPrefix(address) + hop, err := ipstack.Route(address) if err != nil { fmt.Println(err) continue } - + myAddr := hop.Interface.IpPrefix.Addr() // attempt to send the message to the destination for _, neighbor := range ipstack.GetNeighbors()[hop.Interface.Name] { diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go index 6c2330d..983ef5c 100644 --- a/pkg/ipstack/ipstack.go +++ b/pkg/ipstack/ipstack.go @@ -69,7 +69,7 @@ var myNeighbors = make(map[string][]*Neighbor) var myRIPNeighbors = make(map[string]*Neighbor) -type HandlerFunc func(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error +type HandlerFunc func(src *Interface, message []byte, hdr *ipv4header.IPv4Header) error var protocolHandlers = make(map[int]HandlerFunc) @@ -236,11 +236,11 @@ func InterfaceUp(iface *Interface) { if _, ok := protocolHandlers[RIP_PROTOCOL]; ok { ripEntries := make([]RIPEntry, 0) ripEntries = append(ripEntries, RIPEntry{iface.IpPrefix.Masked(), LOCAL_COST}) - sendTriggeredUpdates(ripEntries) + SendTriggeredUpdates(ripEntries) // send a request to all neighbors of this iface to get info ASAP for _, neighbor := range myNeighbors[iface.Name] { - message := makeRipMessage(1, nil) + message := MakeRipMessage(1, nil) addr := iface.IpPrefix.Addr() _, err := SendIP(&addr, neighbor, RIP_PROTOCOL, message, neighbor.VipAddr.String(), nil) if err != nil { @@ -271,7 +271,7 @@ func InterfaceDown(iface *Interface) { if _, ok := protocolHandlers[RIP_PROTOCOL]; ok { ripEntries := make([]RIPEntry, 0) ripEntries = append(ripEntries, RIPEntry{iface.IpPrefix.Masked(), INFINITY}) - sendTriggeredUpdates(ripEntries) + SendTriggeredUpdates(ripEntries) } } @@ -358,7 +358,7 @@ func SprintRoutingTable() string { } // prints the test packet as per the spec -func handleTestPackets(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error { +func HandleTestPackets(src *Interface, message []byte, hdr *ipv4header.IPv4Header) error { fmt.Printf("Received test packet: Src: %s, Dst: %s, TTL: %d, Data: %s\n", hdr.Src.String(), hdr.Dst.String(), hdr.TTL, string(message)) return nil @@ -540,7 +540,7 @@ func RecvIP(iface *Interface, isOpen *bool) error { if hdr.Protocol != RIP_PROTOCOL { // fmt.Println("this test packet is exactly for me") } - err := handler(myIface, nil, message, hdr) + err := handler(myIface, message, hdr) if err != nil { fmt.Println(err) } @@ -553,7 +553,7 @@ func RecvIP(iface *Interface, isOpen *bool) error { // if it's a local hop, send to that iface // if it's a RIP hop, send to the neighbor with that VIP // fmt.Println("checking routing table") - hop, err := LongestPrefix(hdr.Dst) + hop, err := Route(hdr.Dst) if err == nil { // on no err, found a match // fmt.Println("found route", hop.VIP) if hop.Type == "S" { @@ -596,7 +596,7 @@ func RecvIP(iface *Interface, isOpen *bool) error { // ************************************** RIP Routines ******************************************************* // creates a byte array that represents a RIP message -func makeRipMessage(command uint16, entries []RIPEntry) []byte { +func MakeRipMessage(command uint16, entries []RIPEntry) []byte { if command == 1 { // request message buf := make([]byte, SIZE_OF_RIP_HEADER) binary.BigEndian.PutUint16(buf[0:2], command) @@ -631,8 +631,8 @@ func makeRipMessage(command uint16, entries []RIPEntry) []byte { return buf } -// sends updates to neighbors every 5 seconds -func periodicUpdateRoutine() { +// PeriodicUpdateRoutine sends updates to neighbors every 5 seconds +func PeriodicUpdateRoutine() { for { // for each periodic update, we want to send our nodes in the table for _, iface := range myInterfaces { @@ -663,7 +663,7 @@ func periodicUpdateRoutine() { } // make the message and send it - message := makeRipMessage(2, entries) + message := MakeRipMessage(2, entries) addr := iface.IpPrefix.Addr() _, err := SendIP(&addr, n, RIP_PROTOCOL, message, n.VipAddr.String(), nil) if err != nil { @@ -678,8 +678,8 @@ func periodicUpdateRoutine() { } } -// when triggered, sends updates to neighbors -func sendTriggeredUpdates(newEntries []RIPEntry) { +// SendTriggeredUpdates sends updates to ALL neighbors +func SendTriggeredUpdates(newEntries []RIPEntry) { for _, iface := range myInterfaces { for _, n := range myNeighbors[iface.Name] { // only send to RIP neighbors, else skip @@ -689,7 +689,7 @@ func sendTriggeredUpdates(newEntries []RIPEntry) { } // send the made entries to the neighbor - message := makeRipMessage(2, newEntries) + message := MakeRipMessage(2, newEntries) addr := iface.IpPrefix.Addr() _, err := SendIP(&addr, n, RIP_PROTOCOL, message, n.VipAddr.String(), nil) if err != nil { @@ -701,7 +701,7 @@ func sendTriggeredUpdates(newEntries []RIPEntry) { } // manages the timeout table go routine -func manageTimeoutsRoutine() { +func ManageTimeoutsRoutine() { for { time.Sleep(time.Second) @@ -719,7 +719,7 @@ func manageTimeoutsRoutine() { // send triggered update on timeout if len(newEntries) > 0 { - sendTriggeredUpdates(newEntries) + SendTriggeredUpdates(newEntries) } } } @@ -728,8 +728,8 @@ func manageTimeoutsRoutine() { } } -// go routine to send rip requests to neighbors -func startRipRoutines() { +// StartRipRoutines routine to send rip requests to neighbors +func StartRipRoutines() { // send a request to every neighbor go func() { for _, iface := range myInterfaces { @@ -740,7 +740,7 @@ func startRipRoutines() { continue } // send a request - message := makeRipMessage(1, nil) + message := MakeRipMessage(1, nil) addr := iface.IpPrefix.Addr() _, err := SendIP(&addr, neighbor, RIP_PROTOCOL, message, neighbor.VipAddr.String(), nil) if err != nil { @@ -751,10 +751,10 @@ func startRipRoutines() { }() // start a routine that sends updates every 5 seconds - go periodicUpdateRoutine() + go PeriodicUpdateRoutine() // make a "timeout" table, for each response we add to the table via rip - go manageTimeoutsRoutine() + go ManageTimeoutsRoutine() } // ************************************** Protocol Handlers ******************************************************* @@ -762,18 +762,18 @@ func startRipRoutines() { // registers a protocol handler func RegisterProtocolHandler(protocolNum int) bool { if protocolNum == RIP_PROTOCOL { - protocolHandlers[protocolNum] = handleRIP - go startRipRoutines() + protocolHandlers[protocolNum] = HandleRIP + go StartRipRoutines() return true } if protocolNum == TEST_PROTOCOL { - protocolHandlers[protocolNum] = handleTestPackets + protocolHandlers[protocolNum] = HandleTestPackets return true } return false } -func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error { +func HandleRIP(src *Interface, message []byte, hdr *ipv4header.IPv4Header) error { // parse the RIP message command := int(binary.BigEndian.Uint16(message[0:2])) switch command { @@ -804,7 +804,7 @@ func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.I }) } // send the entries - res := makeRipMessage(2, entries) + res := MakeRipMessage(2, entries) _, err := SendIP(&hdr.Dst, neighbor, RIP_PROTOCOL, res, hdr.Src.String(), nil) if err != nil { return err @@ -914,7 +914,7 @@ func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.I // send out triggered updates if len(triggeredEntries) > 0 { - sendTriggeredUpdates(triggeredEntries) + SendTriggeredUpdates(triggeredEntries) } } @@ -938,8 +938,8 @@ func ValidateChecksum(b []byte, fromHeader uint16) uint16 { // ******************************************* RIP HELPERS ********************************************************** -// returns the longest prefix match for a given ip -func LongestPrefix(src netip.Addr) (Hop, error) { +// Route returns the next HOP, based on longest prefix match for a given ip +func Route(src netip.Addr) (Hop, error) { possibleBits := [2]int{32, 24} for _, bits := range possibleBits { cmpPrefix := netip.PrefixFrom(src, bits) @@ -949,5 +949,5 @@ func LongestPrefix(src netip.Addr) (Hop, error) { } } } - return Hop{}, errors.Errorf("No route to ip %s on table.", src) + return Hop{}, errors.Errorf("error ROUTE: destination %s does not exist on routing table.", src) } diff --git a/vhost b/vhost index 5cbef76..e790ecf 100755 Binary files a/vhost and b/vhost differ diff --git a/vrouter b/vrouter index b7bf03d..97ea68a 100755 Binary files a/vrouter and b/vrouter differ -- cgit v1.2.3-70-g09d2