From bb4eefb4fc928b1e681966167c60a4bc79c5b55b Mon Sep 17 00:00:00 2001 From: David Doan Date: Mon, 23 Oct 2023 19:15:09 -0400 Subject: moving sections --- pkg/ipstack/ipstack.go | 315 +++++++++++++++++++++++++------------------------ vhost | Bin 3095650 -> 3110473 bytes vrouter | Bin 3095650 -> 3110473 bytes 3 files changed, 158 insertions(+), 157 deletions(-) diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go index c843bee..6bce6e8 100644 --- a/pkg/ipstack/ipstack.go +++ b/pkg/ipstack/ipstack.go @@ -4,13 +4,14 @@ package ipstack // This class is divided as follows: // 1) INIT FUNCTIONS // 2) DOWN/UP FUNCTIONS -// 3) GETTER FUNCTIONS -// 4) PRINT FUNCTIONS -// 5) ROUTE FUNCTIONS -// 6) RIP FUNCTIONS -// 7) PROTOCOL HANDLERS -// 8) CHECKSUM FUNCTIONS -// 9) HELPERS +// 3) SEND/RECV FUNCTIONS +// 4) CHECKSUM FUNCTIONS +// 5) RIP FUNCTIONS +// 6) PROTOCOL HANDLERS +// 7) HELPER FUNCTIONS +// 8) GETTER FUNCTIONS +// 9) PRINT FUNCTIONS +// 10) CLEANUP FUNCTION import ( "encoding/binary" @@ -317,108 +318,7 @@ func InterfaceDownREPL(ifaceName string) { InterfaceDown(iface) } -// ************************************** GETTER FUNCTIONS ********************************************************** -func GetInterfaceByName(ifaceName string) (*Interface, error) { - // iterate through the interfaces and return the one with the same name - for _, iface := range myInterfaces { - if iface.Name == ifaceName { - return iface, nil - } - } - return nil, errors.Errorf("No interface with name %s", ifaceName) -} - -func GetInterfaces() []*Interface { - return myInterfaces -} - -func GetNeighbors() map[string][]*Neighbor { - return myNeighbors -} - -func GetRoutes() map[netip.Prefix]Hop { - return routingTable -} - -// ************************************** PRINT FUNCTIONS ********************************************************** - -// SprintInterfaces returns a string representation of the interfaces data structure -func SprintInterfaces() string { - tmp := "" - for _, iface := range myInterfaces { - if iface.State { - // if the state is up, print UP - tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "UP") - } else { - // if the state is down, print DOWN - tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "DOWN") - } - } - return tmp -} - -// SprintNeighbors returns a string representation of the neighbors data structure -func SprintNeighbors() string { - tmp := "" - for _, iface := range myInterfaces { - if !iface.State { - // if the interface is down, skip it - 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 -} - -// SprintRoutingTable returns a string representation of the routing table -func SprintRoutingTable() string { - tmp := "" - for prefix, hop := range routingTable { - if hop.Type == "L" { - // if the hop is local, print LOCAL - tmp += fmt.Sprintf("%s\t%s\tLOCAL:%s\t%d\n", hop.Type, prefix.String(), hop.Interface.Name, hop.Cost) - } else if hop.Type == "S" { - // if the hop is static, don't print the cost - tmp += fmt.Sprintf("%s\t%s\t%s\t%s\n", hop.Type, prefix.String(), hop.VIP.String(), "-") - } else { - tmp += fmt.Sprintf("%s\t%s\t%s\t%d\n", hop.Type, prefix.String(), hop.VIP.String(), hop.Cost) - } - } - return tmp -} - -// ************************************** BASIC FUNCTIONS ********************************************************** - -// CleanUp cleans up the data structures and closes the UDP sockets -func CleanUp() { - fmt.Print("Cleaning up...\n") - - // go through the interfaces, pop thread & close the UDP FDs - for _, iface := range myInterfaces { - // close the channel - if iface.SocketChannel != nil { - close(iface.SocketChannel) - } - // close the UDP FD - err := iface.Socket.Close() - if err != nil { - continue - } - } - - // delete all the neighbors - myNeighbors = make(map[string][]*Neighbor) - // delete all the interfaces - myInterfaces = nil - // delete the routing table - routingTable = make(map[netip.Prefix]Hop) - - time.Sleep(5 * time.Millisecond) -} - -// ************************************** ROUTE FUNCTIONS ********************************************************** +// ************************************** SEND/RECV FUNCTIONS ******************************************************* // SendIP sends an IP packet to a destination // @@ -630,44 +530,23 @@ func RecvIP(iface *Interface, isOpen *bool) error { return nil } -// ************************************** RIP FUNCTIONS ******************************************************* - -// MakeRipMessage returns the byte array to be used in SendIp for a RIP packet -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) - binary.BigEndian.PutUint16(buf[2:4], uint16(0)) - return buf - } - - // command == 2, response message - - // create the buffer - bufLen := SIZE_OF_RIP_HEADER + // sizeof uint16 is 2, we have two of them - len(entries)*SIZE_OF_RIP_ENTRY // each entry is 12 - - buf := make([]byte, bufLen) - - // fill in the header - binary.BigEndian.PutUint16(buf[0:2], command) - binary.BigEndian.PutUint16(buf[2:4], uint16(len(entries))) +// ************************************** CHECKSUM FUNCTIONS ****************************************************** +// reference: https://github.com/brown-csci1680/lecture-examples/blob/main/ip-demo/cmd/udp-ip-recv/main.go +func ComputeChecksum(b []byte) uint16 { + checksum := header.Checksum(b, 0) + checksumInv := checksum ^ 0xffff - // fill in the entries - for i, entry := range entries { - offset := SIZE_OF_RIP_HEADER + i*SIZE_OF_RIP_ENTRY - binary.BigEndian.PutUint32(buf[offset:offset+4], entry.cost) // 0-3 = 4 bytes - copy(buf[offset+4:offset+8], entry.prefix.Addr().AsSlice()) // 4-7 = 4 bytes + return checksumInv +} - // convert the prefix to a uint32 - ipv4Netmask := uint32(0xffffffff) - ipv4Netmask <<= 32 - entry.prefix.Bits() - binary.BigEndian.PutUint32(buf[offset+8:offset+12], ipv4Netmask) - } +func ValidateChecksum(b []byte, fromHeader uint16) uint16 { + checksum := header.Checksum(b, fromHeader) - return buf + return checksum } +// ************************************** RIP FUNCTIONS ******************************************************* + // PeriodicUpdateRoutine sends RIP updates to neighbors every 5 seconds // TODO: (performace) consider making this multithreaded and loops above more efficient func PeriodicUpdateRoutine() { @@ -973,21 +852,6 @@ func HandleTestPackets(src *Interface, message []byte, hdr *ipv4header.IPv4Heade return nil } -// ************************************** CHECKSUM FUNCTIONS ****************************************************** -// reference: https://github.com/brown-csci1680/lecture-examples/blob/main/ip-demo/cmd/udp-ip-recv/main.go -func ComputeChecksum(b []byte) uint16 { - checksum := header.Checksum(b, 0) - checksumInv := checksum ^ 0xffff - - return checksumInv -} - -func ValidateChecksum(b []byte, fromHeader uint16) uint16 { - checksum := header.Checksum(b, fromHeader) - - return checksum -} - // *********************************************** HELPERS ********************************************************** // Route returns the next HOP, based on longest prefix match for a given ip @@ -1004,3 +868,140 @@ func Route(src netip.Addr) (Hop, error) { } return Hop{}, errors.Errorf("error ROUTE: destination %s does not exist on routing table.", src) } + +// MakeRipMessage returns the byte array to be used in SendIp for a RIP packet +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) + binary.BigEndian.PutUint16(buf[2:4], uint16(0)) + return buf + } + + // command == 2, response message + + // create the buffer + bufLen := SIZE_OF_RIP_HEADER + // sizeof uint16 is 2, we have two of them + len(entries)*SIZE_OF_RIP_ENTRY // each entry is 12 + + buf := make([]byte, bufLen) + + // fill in the header + binary.BigEndian.PutUint16(buf[0:2], command) + binary.BigEndian.PutUint16(buf[2:4], uint16(len(entries))) + + // fill in the entries + for i, entry := range entries { + offset := SIZE_OF_RIP_HEADER + i*SIZE_OF_RIP_ENTRY + binary.BigEndian.PutUint32(buf[offset:offset+4], entry.cost) // 0-3 = 4 bytes + copy(buf[offset+4:offset+8], entry.prefix.Addr().AsSlice()) // 4-7 = 4 bytes + + // convert the prefix to a uint32 + ipv4Netmask := uint32(0xffffffff) + ipv4Netmask <<= 32 - entry.prefix.Bits() + binary.BigEndian.PutUint32(buf[offset+8:offset+12], ipv4Netmask) + } + + return buf +} + +// ************************************** GETTER FUNCTIONS ********************************************************** +func GetInterfaceByName(ifaceName string) (*Interface, error) { + // iterate through the interfaces and return the one with the same name + for _, iface := range myInterfaces { + if iface.Name == ifaceName { + return iface, nil + } + } + return nil, errors.Errorf("No interface with name %s", ifaceName) +} + +func GetInterfaces() []*Interface { + return myInterfaces +} + +func GetNeighbors() map[string][]*Neighbor { + return myNeighbors +} + +func GetRoutes() map[netip.Prefix]Hop { + return routingTable +} + +// ************************************** PRINT FUNCTIONS ********************************************************** + +// SprintInterfaces returns a string representation of the interfaces data structure +func SprintInterfaces() string { + tmp := "" + for _, iface := range myInterfaces { + if iface.State { + // if the state is up, print UP + tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "UP") + } else { + // if the state is down, print DOWN + tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "DOWN") + } + } + return tmp +} + +// SprintNeighbors returns a string representation of the neighbors data structure +func SprintNeighbors() string { + tmp := "" + for _, iface := range myInterfaces { + if !iface.State { + // if the interface is down, skip it + 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 +} + +// SprintRoutingTable returns a string representation of the routing table +func SprintRoutingTable() string { + tmp := "" + for prefix, hop := range routingTable { + if hop.Type == "L" { + // if the hop is local, print LOCAL + tmp += fmt.Sprintf("%s\t%s\tLOCAL:%s\t%d\n", hop.Type, prefix.String(), hop.Interface.Name, hop.Cost) + } else if hop.Type == "S" { + // if the hop is static, don't print the cost + tmp += fmt.Sprintf("%s\t%s\t%s\t%s\n", hop.Type, prefix.String(), hop.VIP.String(), "-") + } else { + tmp += fmt.Sprintf("%s\t%s\t%s\t%d\n", hop.Type, prefix.String(), hop.VIP.String(), hop.Cost) + } + } + return tmp +} + +// ************************************** CLEANUP FUNCTIONS ********************************************************** + +// CleanUp cleans up the data structures and closes the UDP sockets +func CleanUp() { + fmt.Print("Cleaning up...\n") + + // go through the interfaces, pop thread & close the UDP FDs + for _, iface := range myInterfaces { + // close the channel + if iface.SocketChannel != nil { + close(iface.SocketChannel) + } + // close the UDP FD + err := iface.Socket.Close() + if err != nil { + continue + } + } + + // delete all the neighbors + myNeighbors = make(map[string][]*Neighbor) + // delete all the interfaces + myInterfaces = nil + // delete the routing table + routingTable = make(map[netip.Prefix]Hop) + + time.Sleep(5 * time.Millisecond) +} \ No newline at end of file diff --git a/vhost b/vhost index 90cbbf2..8d82e3e 100755 Binary files a/vhost and b/vhost differ diff --git a/vrouter b/vrouter index e8727c5..3f5c0b2 100755 Binary files a/vrouter and b/vrouter differ -- cgit v1.2.3-70-g09d2