diff options
author | sotech117 <michael_foiani@brown.edu> | 2023-10-23 03:42:05 -0400 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2023-10-23 03:42:05 -0400 |
commit | 512c4c2785e6dbf53106b5a6f60e0e1992977016 (patch) | |
tree | 284ede052af9a1efc2a962d7da6f9abde588b7ac | |
parent | 7ec4f310ec01100f648a42dd52cb0ac635ac0b10 (diff) |
add RIP request and reponse
-rw-r--r-- | cmd/vhost/main.go | 9 | ||||
-rw-r--r-- | cmd/vrouter/main.go | 4 | ||||
-rw-r--r-- | pkg/ipstack/ipstack.go | 130 | ||||
-rwxr-xr-x | vhost | bin | 3104785 -> 3104388 bytes | |||
-rwxr-xr-x | vrouter | bin | 3104857 -> 3104404 bytes |
5 files changed, 88 insertions, 55 deletions
diff --git a/cmd/vhost/main.go b/cmd/vhost/main.go index 17b4a02..468409d 100644 --- a/cmd/vhost/main.go +++ b/cmd/vhost/main.go @@ -58,14 +58,21 @@ func main() { messageToSendBytes := []byte(messageToSend) hop, err := ipstack.LongestPrefix(netip.MustParseAddr(ipAddr)) + if err != nil { + fmt.Println(err) + continue + } myAddr := hop.Interface.IpPrefix.Addr() for _, neighbor := range ipstack.GetNeighbors()[hop.Interface.Name] { // TODO: fix multiple send bug here on static route if neighbor.VipAddr == netip.MustParseAddr(ipAddr) || neighbor.VipAddr == hop.VIP && hop.Type == "S" { - err = ipstack.SendIP(&myAddr, neighbor, ipstack.TEST_PROTOCOL, messageToSendBytes, ipAddr, nil) + bytesWritten, err := ipstack.SendIP(&myAddr, neighbor, ipstack.TEST_PROTOCOL, messageToSendBytes, ipAddr, nil) if err != nil { fmt.Println(err) + } else { + fmt.Printf("Sent %d bytes to %s\n", bytesWritten, neighbor.VipAddr.String()) + } } } diff --git a/cmd/vrouter/main.go b/cmd/vrouter/main.go index aacf786..7998e5d 100644 --- a/cmd/vrouter/main.go +++ b/cmd/vrouter/main.go @@ -80,9 +80,11 @@ func main() { for _, neighbor := range ipstack.GetNeighbors()[hop.Interface.Name] { if neighbor.VipAddr == netip.MustParseAddr(ipAddr) || neighbor.VipAddr == hop.VIP { - err = ipstack.SendIP(&myAddr, neighbor, ipstack.TEST_PROTOCOL, messageToSendBytes, ipAddr, nil) + bytesWritten, err := ipstack.SendIP(&myAddr, neighbor, ipstack.TEST_PROTOCOL, messageToSendBytes, ipAddr, nil) if err != nil { fmt.Println(err) + } else { + fmt.Printf("Sent %d bytes to %s\n", bytesWritten, neighbor.VipAddr.String()) } } } diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go index 8983ef8..2116403 100644 --- a/pkg/ipstack/ipstack.go +++ b/pkg/ipstack/ipstack.go @@ -68,7 +68,7 @@ var myVIP Interface var myInterfaces []*Interface var myNeighbors = make(map[string][]*Neighbor) -var myRIPNeighbors = make(map[string]bool) +var myRIPNeighbors = make(map[string]*Neighbor) type HandlerFunc func(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error @@ -141,7 +141,7 @@ func Initialize(lnxFilePath string) error { for _, iface := range myInterfaces { for _, neighbor := range myNeighbors[iface.Name] { if neighbor.VipAddr == route { - myRIPNeighbors[neighbor.VipAddr.String()] = true + myRIPNeighbors[neighbor.VipAddr.String()] = neighbor break } } @@ -383,7 +383,7 @@ 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) error { +func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, destIP string, hdr *ipv4header.IPv4Header) (int, error) { if hdr == nil { hdr = &ipv4header.IPv4Header{ Version: 4, @@ -421,7 +421,7 @@ func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, de // Assemble the header into a byte array headerBytes, err := hdr.Marshal() if err != nil { - return err + return -1, err } // Compute the checksum (see below) @@ -442,7 +442,7 @@ func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, de // tmpConn, err := net.DialUDP("udp4", nil, sendAddr) // get the interface of this neighbor if err != nil { - return errors.WithMessage(err, "Could not bind to UDP port->\t"+dest.UdpAddr.String()) + return -1, errors.WithMessage(err, "Could not bind to UDP port->\t"+dest.UdpAddr.String()) } // bytesWritten, err := tmpConn.Write(bytesToSend) @@ -451,12 +451,10 @@ func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, de bytesWritten, err := iface.RecvSocket.WriteToUDP(bytesToSend, sendAddr) if err != nil { fmt.Println("Error writing to UDP socket") - return errors.WithMessage(err, "Error writing to UDP socket") + return -1, errors.WithMessage(err, "Error writing to UDP socket") } - fmt.Printf("Sent %d bytes to %s\n", bytesWritten, dest.VipAddr.String()) - - return nil + return bytesWritten, nil } func RecvIP(iface *Interface, isOpen *bool) error { @@ -517,20 +515,20 @@ func RecvIP(iface *Interface, isOpen *bool) error { // check if the checksum is valid if checksumState == "FAIL" { // drop the packet - fmt.Println("checksum failed, dropping packet") + // fmt.Println("checksum failed, dropping packet") return nil } // 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 if handler, ok := protocolHandlers[hdr.Protocol]; ok { if hdr.Protocol != RIP_PROTOCOL { - fmt.Println("this test packet is exactly for me") + // fmt.Println("this test packet is exactly for me") } err := handler(iface, nil, message, hdr) if err != nil { @@ -543,10 +541,10 @@ func RecvIP(iface *Interface, isOpen *bool) error { // 4) check forwarding table. // 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") + // fmt.Println("checking routing table") hop, err := LongestPrefix(hdr.Dst) if err == nil { // on no err, found a match - fmt.Println("found route", hop.VIP) + // fmt.Println("found route", hop.VIP) if hop.Type == "S" { // default, static route // drop in this case @@ -558,7 +556,7 @@ func RecvIP(iface *Interface, isOpen *bool) error { // if it's a local route, then the name is the interface name for _, neighbor := range myNeighbors[hop.Interface.Name] { if neighbor.VipAddr == hdr.Dst { - err2 := SendIP(&hdr.Src, neighbor, hdr.Protocol, message, hdr.Dst.String(), hdr) + _, err2 := SendIP(&hdr.Src, neighbor, hdr.Protocol, message, hdr.Dst.String(), hdr) if err2 != nil { return err2 } @@ -571,7 +569,7 @@ func RecvIP(iface *Interface, isOpen *bool) error { // if it's a rip route, then the check is against the hop vip for _, neighbor := range myNeighbors[hop.Interface.Name] { if neighbor.VipAddr == hop.VIP { - err2 := SendIP(&hdr.Src, neighbor, hdr.Protocol, message, hdr.Dst.String(), hdr) + _, err2 := SendIP(&hdr.Src, neighbor, hdr.Protocol, message, hdr.Dst.String(), hdr) if err2 != nil { return err2 } @@ -627,10 +625,10 @@ func periodicUpdateRoutine() { // TODO: consider making this multithreaded and loops above more efficient // if we're here, we are sending this to a rip neighbor - entries := make([]RIPEntry, len(routingTable)) + entries := make([]RIPEntry, 0) for prefix, hop := range routingTable { // implement split horizon + poison reverse at entry level - fmt.Println("prefix: ", prefix) + // fmt.Println("prefix: ", prefix) var cost uint32 if hop.VIP == n.VipAddr { cost = INFINITY @@ -646,7 +644,7 @@ func periodicUpdateRoutine() { message := makeRipMessage(2, entries) addr := iface.IpPrefix.Addr() - err := SendIP(&addr, n, RIP_PROTOCOL, message, n.VipAddr.String(), nil) + _, 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()) continue @@ -667,22 +665,34 @@ func manageTimeoutsRoutine() { for { time.Sleep(time.Second) - wg := &sync.WaitGroup{} - wg.Add(len(timeoutTable)) + // note: waitgroup causes deadlock then crashing + //wg := &sync.WaitGroup{} + //wg.Add(len(timeoutTable)) + //mu.Lock() + //for prefix, _ := range timeoutTable { + // go func(p netip.Prefix) { + // timeoutTable[p]++ + // if timeoutTable[p] == MAX_TIMEOUT { + // delete(routingTable, p) + // delete(timeoutTable, p) + // // TODO: send triggered update + // } + // + // wg.Done() + // }(prefix) + //} + //wg.Wait() + //mu.Unlock() + mu.Lock() for prefix, _ := range timeoutTable { - go func(p netip.Prefix) { - timeoutTable[p]++ - if timeoutTable[p] == MAX_TIMEOUT { - delete(routingTable, p) - delete(timeoutTable, p) - // TODO: send triggered update - } - - wg.Done() - }(prefix) + timeoutTable[prefix]++ + if timeoutTable[prefix] == MAX_TIMEOUT { + delete(routingTable, prefix) + delete(timeoutTable, prefix) + // TODO: send triggered update + } } - wg.Wait() mu.Unlock() // fmt.Println("Timeout table: ", timeoutTable) @@ -701,7 +711,7 @@ func startRipRoutines() { // send a request message := makeRipMessage(1, nil) addr := iface.IpPrefix.Addr() - err := SendIP(&addr, neighbor, RIP_PROTOCOL, message, neighbor.VipAddr.String(), nil) + _, err := SendIP(&addr, neighbor, RIP_PROTOCOL, message, neighbor.VipAddr.String(), nil) if err != nil { return } @@ -738,15 +748,44 @@ func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.I command := int(binary.BigEndian.Uint16(message[0:2])) switch command { case 1: - // request - // SendUpdates() + //fmt.Println("Received RIP command for specific info") + // only send if the person asking is a RIP neighbor + neighbor, in := myRIPNeighbors[hdr.Src.String()] + if !in { + break + } + + // fmt.Println("he is my rip neighbor ", hdr.Src.String()) + + // build the entries + entries := make([]RIPEntry, 0) + for prefix, hop := range routingTable { + // implement split horizon + poison reverse at entry level + // fmt.Println("prefix: ", prefix) + var cost uint32 + if hop.VIP == hdr.Src { + cost = INFINITY + } else { + cost = hop.Cost + } + entries = append(entries, + RIPEntry{ + prefix: prefix, + cost: cost, + }) + } + res := makeRipMessage(2, nil) + _, err := SendIP(&hdr.Dst, neighbor, RIP_PROTOCOL, res, hdr.Src.String(), nil) + if err != nil { + return err + } break case 2: numEntries := int(binary.BigEndian.Uint16(message[2:4])) - fmt.Println("Received RIP response with", numEntries, "entries") + // fmt.Println("Received RIP response with", numEntries, "entries") // parse the entries - entries := make([]RIPEntry, 0, numEntries) + entries := make([]RIPEntry, 0) for i := 0; i < numEntries; i++ { offset := SIZE_OF_RIP_HEADER + i*SIZE_OF_RIP_ENTRY @@ -762,7 +801,7 @@ func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.I prefix := netip.PrefixFrom(address, 24) entries = append(entries, RIPEntry{prefix, cost}) - fmt.Println("Received RIP update: ", prefix.String(), cost) + // fmt.Println("Received RIP update: ", prefix.String(), cost) } // add to routing table @@ -1026,21 +1065,6 @@ func LongestPrefix(src netip.Addr) (Hop, error) { // } //} -func ifaceContainsIP(iface Interface, ip netip.Addr) bool { - // check if the ip is in the interface's prefix - if iface.IpPrefix.Contains(netip.MustParseAddr(ip.String())) { - return true - } - return false -} - -func ConvertIPToUint32(ip string) uint32 { - netIP := net.ParseIP(ip) - ipBytes := netIP.To4() - ipUint32 := uint32(ipBytes[0])<<24 | uint32(ipBytes[1])<<16 | uint32(ipBytes[2])<<8 | uint32(ipBytes[3]) - return ipUint32 -} - // TODO @ MICHEAL: Handle links going down and link recovery // func CheckAndUpdateRoutingTable() { // for { Binary files differBinary files differ |