aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2023-10-23 22:31:26 +0000
committersotech117 <michael_foiani@brown.edu>2023-10-23 22:31:26 +0000
commit1f926271bc80bcd6ff5ed52bb76a9ade347367b8 (patch)
tree30729c78765f6e1f9edba5fc6c1ef9cb94f25a6d
parent93416359403895d1dd1584c316d9e3dbfcc7a673 (diff)
refactor and comment code. add more descriptive error message.
-rw-r--r--README.md35
-rw-r--r--cmd/vhost/main.go2
-rw-r--r--cmd/vrouter/main.go4
-rw-r--r--pkg/ipstack/ipstack.go60
-rwxr-xr-xvhostbin3105370 -> 3105122 bytes
-rwxr-xr-xvrouterbin3105378 -> 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
--- a/vhost
+++ b/vhost
Binary files differ
diff --git a/vrouter b/vrouter
index b7bf03d..97ea68a 100755
--- a/vrouter
+++ b/vrouter
Binary files differ