aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2023-10-23 04:52:43 -0400
committersotech117 <michael_foiani@brown.edu>2023-10-23 04:52:43 -0400
commitfce81b0ba78d52427fc2ba43af63732d3205dcf1 (patch)
treeb0c763d85ab96022fd2cada375eefdaa01d0b409
parent512c4c2785e6dbf53106b5a6f60e0e1992977016 (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.go6
-rw-r--r--cmd/vrouter/main.go6
-rw-r--r--pkg/ipstack/ipstack.go156
-rwxr-xr-xvhostbin3104388 -> 3104927 bytes
-rwxr-xr-xvrouterbin3104404 -> 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}
+ // }
}
}
diff --git a/vhost b/vhost
index aa6346f..c61fd2b 100755
--- a/vhost
+++ b/vhost
Binary files differ
diff --git a/vrouter b/vrouter
index 0dc05d1..88ed19c 100755
--- a/vrouter
+++ b/vrouter
Binary files differ