diff options
author | sotech117 <michael_foiani@brown.edu> | 2023-10-23 04:52:43 -0400 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2023-10-23 04:52:43 -0400 |
commit | fce81b0ba78d52427fc2ba43af63732d3205dcf1 (patch) | |
tree | b0c763d85ab96022fd2cada375eefdaa01d0b409 | |
parent | 512c4c2785e6dbf53106b5a6f60e0e1992977016 (diff) |
implement basic triggered updates, but there is still a small bug with rerouting after a router goes down I need to fix. also, fixed the print functions and returned them to sprint so I can test.
-rw-r--r-- | cmd/vhost/main.go | 6 | ||||
-rw-r--r-- | cmd/vrouter/main.go | 6 | ||||
-rw-r--r-- | pkg/ipstack/ipstack.go | 156 | ||||
-rwxr-xr-x | vhost | bin | 3104388 -> 3104927 bytes | |||
-rwxr-xr-x | vrouter | bin | 3104404 -> 3104919 bytes |
5 files changed, 101 insertions, 67 deletions
diff --git a/cmd/vhost/main.go b/cmd/vhost/main.go index 468409d..dbf899a 100644 --- a/cmd/vhost/main.go +++ b/cmd/vhost/main.go @@ -30,13 +30,13 @@ func main() { switch line { case "li": fmt.Println("Name\tAddr/Prefix\tState") - ipstack.SprintInterfaces() + fmt.Println(ipstack.SprintInterfaces()) case "ln": fmt.Println("Iface\tVIP\tUDPAddr") - ipstack.SprintNeighbors() + fmt.Println(ipstack.SprintNeighbors()) case "lr": fmt.Println("T\tPrefix\tNext Hop\tCost") - ipstack.SprintRoutingTable() + fmt.Println(ipstack.SprintRoutingTable()) case "q": ipstack.CleanUp() os.Exit(0) diff --git a/cmd/vrouter/main.go b/cmd/vrouter/main.go index 7998e5d..cde49a8 100644 --- a/cmd/vrouter/main.go +++ b/cmd/vrouter/main.go @@ -44,13 +44,13 @@ func main() { switch line { case "li": fmt.Println("Name\tAddr/Prefix\tState") - ipstack.SprintInterfaces() + fmt.Println(ipstack.SprintInterfaces()) case "ln": fmt.Println("Iface\tVIP\tUDPAddr") - ipstack.SprintNeighbors() + fmt.Println(ipstack.SprintNeighbors()) case "lr": fmt.Println("T\tPrefix\tNext Hop\tCost") - ipstack.SprintRoutingTable() + fmt.Println(ipstack.SprintRoutingTable()) case "q": ipstack.CleanUp() os.Exit(0) diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go index 2116403..e949824 100644 --- a/pkg/ipstack/ipstack.go +++ b/pkg/ipstack/ipstack.go @@ -176,7 +176,7 @@ func InterfaceListenerRoutine(i *Interface) { closed := false // go routine that hangs on the recv - fmt.Println("MAKING GO ROUTINE TO LISTEN:\t", socket.LocalAddr().String()) + // fmt.Println("MAKING GO ROUTINE TO LISTEN:\t", socket.LocalAddr().String()) go func() { defer func() { fmt.Println("exiting go routine that listens on ", socket.LocalAddr().String()) @@ -193,8 +193,8 @@ func InterfaceListenerRoutine(i *Interface) { time.Sleep(1 * time.Millisecond) err := RecvIP(i, &isUp) if err != nil { - fmt.Println("Error receiving IP packet", err) - return + // fmt.Println("Error receiving IP packet", err) + continue } } }() @@ -207,7 +207,7 @@ func InterfaceListenerRoutine(i *Interface) { closed = true return } - fmt.Println("received isUP SIGNAL with value", sig) + // fmt.Println("received isUP SIGNAL with value", sig) isUp = sig default: continue @@ -220,6 +220,13 @@ func InterfaceListenerRoutine(i *Interface) { func InterfaceUp(iface *Interface) { iface.State = true iface.SocketChannel <- true + + // if were a router, send triggered updates on up + if _, ok := protocolHandlers[RIP_PROTOCOL]; ok { + ripEntries := make([]RIPEntry, 0) + ripEntries = append(ripEntries, RIPEntry{iface.IpPrefix.Masked(), LOCAL_COST}) + sendTriggeredUpdates(ripEntries) + } } func InterfaceUpREPL(ifaceName string) { @@ -236,6 +243,13 @@ func InterfaceUpREPL(ifaceName string) { func InterfaceDown(iface *Interface) { iface.SocketChannel <- false iface.State = false + + // if were a router, send triggered updates on down + if _, ok := protocolHandlers[RIP_PROTOCOL]; ok { + ripEntries := make([]RIPEntry, 0) + ripEntries = append(ripEntries, RIPEntry{iface.IpPrefix.Masked(), INFINITY}) + sendTriggeredUpdates(ripEntries) + } } func InterfaceDownREPL(ifaceName string) { @@ -297,66 +311,45 @@ func GetRoutes() map[netip.Prefix]Hop { // ************************************** PRINT FUNCTIONS ********************************************************** -func SprintInterfaces() { +func SprintInterfaces() string { + tmp := "" for _, iface := range myInterfaces { if iface.State { - fmt.Printf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "UP") + tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "UP") } else { - fmt.Printf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "DOWN") + tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "DOWN") } } + return tmp } -func SprintNeighbors() { - for ifaceName, neighbor := range myNeighbors { - for _, n := range neighbor { - fmt.Printf("%s\t%s\t%s\n", ifaceName, n.VipAddr.String(), n.UdpAddr.String()) +func SprintNeighbors() string { + tmp := "" + for _, iface := range myInterfaces { + if !iface.State { + continue + } + for _, n := range myNeighbors[iface.Name] { + tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, n.VipAddr.String(), n.UdpAddr.String()) } } + return tmp } -func SprintRoutingTable() { +func SprintRoutingTable() string { + tmp := "" for prefix, hop := range routingTable { if hop.Type == "L" { - fmt.Printf("%s\t%s\tLOCAL:%s\t%d\n", hop.Type, prefix.String(), hop.Interface.Name, 0) + tmp += fmt.Sprintf("%s\t%s\tLOCAL:%s\t%d\n", hop.Type, prefix.String(), hop.Interface.Name, 0) } else if hop.Type == "S" { - fmt.Printf("%s\t%s\t%s\t%s\n", hop.Type, prefix.String(), hop.VIP.String(), "-") + tmp += fmt.Sprintf("%s\t%s\t%s\t%s\n", hop.Type, prefix.String(), hop.VIP.String(), "-") } else { - fmt.Printf("%s\t%s\t%s\t%d\n", hop.Type, prefix.String(), hop.VIP.String(), hop.Cost) + tmp += fmt.Sprintf("%s\t%s\t%s\t%d\n", hop.Type, prefix.String(), hop.VIP.String(), hop.Cost) } } + return tmp } -func DebugNeighbors() { - for ifaceName, neighbor := range myNeighbors { - for _, n := range neighbor { - fmt.Printf("%s\t%s\t%s\n", ifaceName, n.UdpAddr.String(), n.VipAddr.String()) - } - } -} - -//// TODO @ MICHAEL: -//func RemoveNeighbor(neighbor Neighbor) { -// // TODO: remove from routing table -// myRoutes := GetRoutes() -// for prefix, hop := range myRoutes { -// if hop.VipAsStr == neighbor.VipAddr.String() { -// delete(myRoutes, prefix) -// } -// } -// -// // TODO: remove from myNeighbors -// myNeighbors[neighbor.VipAddr.String()] = nil -// -// // TODO: close the UDP socket -// err := neighbor.SendSocket.Close() -// if err != nil { -// fmt.Println("Error closing UDP socket", err) -// } -// -//} -// untested function above - // ************************************** BASIC FUNCTIONS ********************************************************** func CleanUp() { @@ -384,6 +377,11 @@ func CleanUp() { // TODO: have it take TTL so we can decrement it when forwarding func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, destIP string, hdr *ipv4header.IPv4Header) (int, error) { + iface, err := GetInterfaceByName(dest.Name) + if !iface.State { + return -1, errors.New("error: interface is down") + } + if hdr == nil { hdr = &ipv4header.IPv4Header{ Version: 4, @@ -447,7 +445,6 @@ func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, de // bytesWritten, err := tmpConn.Write(bytesToSend) // TODO: make this faster by removing call - iface, err := GetInterfaceByName(dest.Name) bytesWritten, err := iface.RecvSocket.WriteToUDP(bytesToSend, sendAddr) if err != nil { fmt.Println("Error writing to UDP socket") @@ -467,7 +464,6 @@ func RecvIP(iface *Interface, isOpen *bool) error { // Read on the UDP port // Too much printing so I commented it out // fmt.Println("wating to read from UDP socket") - // TODO: this is erroring here!! _, _, err := conn.ReadFromUDP(buffer) if err != nil { return err @@ -522,7 +518,7 @@ func RecvIP(iface *Interface, isOpen *bool) error { // at this point, the packet is valid. next steps consider the forwarding of the packet // 2) check if the message is for me, if so, sendUP (aka call the correct handler) if hdr.Protocol != RIP_PROTOCOL { - // fmt.Println("I see a non-rip packet") + fmt.Println("I see a non-rip packet") } if hdr.Dst == prefix.Addr() { // see if there is a handler for this protocol @@ -646,7 +642,7 @@ func periodicUpdateRoutine() { addr := iface.IpPrefix.Addr() _, err := SendIP(&addr, n, RIP_PROTOCOL, message, n.VipAddr.String(), nil) if err != nil { - fmt.Printf("Error sending RIP message to %s\n", n.VipAddr.String()) + // fmt.Printf("Error sending RIP message to %s\n", n.VipAddr.String()) continue } } @@ -661,6 +657,25 @@ var mu sync.Mutex var timeoutTable = make(map[netip.Prefix]int) var MAX_TIMEOUT = 12 +func sendTriggeredUpdates(newEntries []RIPEntry) { + for _, iface := range myInterfaces { + for _, n := range myNeighbors[iface.Name] { + _, in := myRIPNeighbors[n.VipAddr.String()] + if !in { + continue + } + + message := makeRipMessage(2, newEntries) + addr := iface.IpPrefix.Addr() + _, err := SendIP(&addr, n, RIP_PROTOCOL, message, n.VipAddr.String(), nil) + if err != nil { + // fmt.Printf("Error sending RIP triggered update to %s\n", n.VipAddr.String()) + continue + } + } + } +} + func manageTimeoutsRoutine() { for { time.Sleep(time.Second) @@ -690,9 +705,15 @@ func manageTimeoutsRoutine() { if timeoutTable[prefix] == MAX_TIMEOUT { delete(routingTable, prefix) delete(timeoutTable, prefix) - // TODO: send triggered update + // send triggered update on timeout + go func(p netip.Prefix) { + newEntries := make([]RIPEntry, 0) + newEntries = append(newEntries, RIPEntry{p, INFINITY}) + sendTriggeredUpdates(newEntries) + }(prefix) } } + // fmt.Println("timeout table: ", timeoutTable) mu.Unlock() // fmt.Println("Timeout table: ", timeoutTable) @@ -816,27 +837,40 @@ func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.I // potentially, may have to apply mask first // fmt.Println(address) - prefix := entry.prefix + destination := entry.prefix.Masked() // fmt.Println(prefix.String()) // check if the entry is already in the routing table and update if need be - if node, ok := routingTable[prefix.Masked()]; ok { - if entry.cost < node.Cost { - routingTable[prefix.Masked()] = Hop{entry.cost + 1, "R", src, hdr.Src} + if hop, ok := routingTable[destination]; ok { + // if the hop is the same as the incoming neighbor, + // then we can increase the cost by that new value + if hop.VIP == hdr.Src && + entry.cost > hop.Cost { + routingTable[destination] = Hop{entry.cost + 1, "R", src, hdr.Src} } - if node.Type == "R" { + + // if there is a shorter route for this destination on a different (or same) neighbor + // then update to use that one + if entry.cost < hop.Cost { + routingTable[destination] = Hop{entry.cost + 1, "R", src, hdr.Src} + } + + // upon an update from this prefix, reset its timeout + if hop.Type == "R" { mu.Lock() - timeoutTable[prefix.Masked()] = 0 + timeoutTable[destination] = 0 mu.Unlock() } continue } - if entry.cost == 17 { - routingTable[prefix.Masked()] = Hop{0, "R", src, hdr.Src} - } else { - routingTable[prefix.Masked()] = Hop{entry.cost + 1, "R", src, hdr.Src} - } + // fmt.Println("Adding new route to routing table: ", destination.String(), entry.cost) + // @ david, where did the 17 come from + //if entry.cost == 17 { + // routingTable[destination] = Hop{0, "R", src, hdr.Src} + //} else { + routingTable[destination] = Hop{entry.cost + 1, "R", src, hdr.Src} + // } } } |