Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:hsheth2/gonet into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
hsheth2 committed Jun 24, 2016
2 parents b463fe3 + 74086fe commit b290691
Show file tree
Hide file tree
Showing 20 changed files with 350 additions and 53 deletions.
16 changes: 16 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
sudo: required

language: go

go:
- 1.6

services:
- docker

before_install:
- docker pull hsheth2/gonet-base
- docker run --privileged -v `pwd`:/go/src/github.com/hsheth2/gonet hsheth2/gonet-base:latest /bin/bash -c "cd /go/src/github.com/hsheth2/gonet && make && make test"

script:
- make depend build
7 changes: 7 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Copyright (c) 2015-2016 Harshal Sheth and Aashish Welling.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15 changes: 9 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ PKGS := $(shell go list ./...) # tr '\n' ' ' ?

# Basic building
install: clean setup depend build
reinstall: clean setup build
list:
@echo $(PKGS)

Expand All @@ -17,6 +18,7 @@ depend:
go get -u github.com/pkg/profile
go get -u github.com/hsheth2/water
go get -u github.com/hsheth2/water/waterutil
go get golang.org/x/tools/cmd/...
-go get -t ./...
build:
go clean ./...
Expand All @@ -28,10 +30,11 @@ clean:
-rm -f *.cover
-rm -f *.html
-rm -f httpTest
-rm -rf tapip
go clean ./...
setup:
-./tap_setup.sh
-./arp_setup.sh
./tap_setup.sh
./arp_setup.sh

# line counting
lines:
Expand All @@ -41,13 +44,13 @@ lines:
check: fmt lint vet errcheck

fmt:
go get golang.org/x/tools/cmd/goimports
@echo "Formatting Files..."
goimports -l -w ./
@echo "Finished Formatting"
vet:
go vet ./...
lint:
go get github.com/golang/lint/golint
golint ./...
errcheck:
errcheck $(PKGS)
Expand All @@ -57,8 +60,8 @@ doc:
godoc -http=:6060

# Different tests that could be run on the network's code
test: test_others test_network
test_others:
test: test_network
test_deps:
./run_test.sh github.com/hsheth2/logs
./run_test.sh github.com/hsheth2/notifiers
test_network: test_udp test_tcp test_ping
Expand All @@ -70,4 +73,4 @@ test_ping:
./run_test.sh github.com/hsheth2/gonet/ping
test_tap:
# for testing water
./run_test.sh github.com/hsheth2/gonet/ethernet
./run_test.sh github.com/hsheth2/gonet/physical
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
# GoNet
[![GoDoc](https://godoc.org/github.com/hsheth2/gonet?status.svg)](https://godoc.org/github.com/hsheth2/gonet)
[![Build Status](https://travis-ci.org/hsheth2/gonet.svg?branch=master)](https://travis-ci.org/hsheth2/gonet)
[![Go Report Card](https://goreportcard.com/badge/github.com/hsheth2/gonet)](https://goreportcard.com/report/github.com/hsheth2/gonet)
[![Code Climate](https://codeclimate.com/github/hsheth2/gonet/badges/gpa.svg)](https://codeclimate.com/github/hsheth2/gonet)
[![License](http://img.shields.io/:license-MIT-blue.svg)](http://www.opensource.org/licenses/MIT)

A network stack written in Go with the CSP style.

Note: This project only works on linux machines (because of its dependency on the tap device).

Warning: This project is still under development.

## Usage
*Note: This project only works on linux machines (because of its dependency on the tap device).*

To install `GoNet`:

1. Run `go get github.com/hsheth2/gonet`
2. In the directory, run `make`.

You can use its functionallity by importing it in your own projects. See the GoDoc for documentation.

We also included a simple demo application: a basic HTTP server. Once you have run `make` in the `GoNet` source directory, there will be an executable called `gohttp` in your Go bin. This executable will run the HTTP server, and will serve the files in whatever directory it is run in.

Because `GoNet` runs on the tap interface, it will be accessible at `10.0.0.2`.

## Contributors
This project was created by [Harshal Sheth](https://github.com/hsheth2)
and [Aashish Welling](https://github.com/omegablitz).


## License
GoNet is released under the [MIT License](http://www.opensource.org/licenses/MIT).
2 changes: 1 addition & 1 deletion arp_setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ echo '00:34:45:de:ca:de' > ethernet/external_mac.static
echo '10.0.0.3' > ipv4/external_ip.static
echo '10.0.0.2' > ipv4/external_gateway.static

IFACE=wlan1
IFACE=$(netstat -rn | grep ^0.0.0.0 | sed 's/.* //g' | sed 's/\s//g')

sudo sysctl net.ipv4.ip_forward=1
sudo iptables -t nat -A PREROUTING -p tcp -d `/sbin/ifconfig ${IFACE} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` --dport 23280 -j DNAT --to 10.0.0.3:80
Expand Down
7 changes: 7 additions & 0 deletions docker-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash

docker rm gonet

# should be run in gonet source directory
docker pull hsheth2/gonet-base
docker run -it --privileged --name gonet -v `pwd`:/go/src/github.com/hsheth2/gonet hsheth2/gonet-base:latest
8 changes: 6 additions & 2 deletions ethernet/network_read_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ func Bind(proto EtherType) (Reader, error) {

// Unbind allows clients to unbind from specific EtherTypes
func Unbind(proto EtherType) error {
// TODO write the unbind ethernet proto function
return nil
_, exists := protoBufs[proto]
if exists {
delete(protoBufs, proto)
return nil
}
return errors.New("That protocol is not bound!")
}

func readFrame() (d []byte, err error) {
Expand Down
11 changes: 7 additions & 4 deletions ethernet/network_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (ethr *ethernetReader) readAll() {
for {
//logs.Trace.Println("Ethernet reader attempting to get work")
data := <-ethr.input
//logs.Trace.Println("Ethernet reader recieved packet")
//logs.Trace.Println("Ethernet reader received packet")

ethHead := &FrameHeader{
//Rmac: &MAC_Address{Data: data[ETH_MAC_ADDR_SZ : 2*ETH_MAC_ADDR_SZ]},
Expand All @@ -55,8 +55,11 @@ func (ethr *ethernetReader) Read() (*FrameHeader, error) {
}

func (ethr *ethernetReader) Close() error {
// TODO unbind
// TODO close input channel
// TODO close output channel
err := Unbind(ethr.ethertype)
if err != nil {
return err
}
close(ethr.input)
close(ethr.processed)
return nil
}
8 changes: 7 additions & 1 deletion physical/loopback.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package physical

import (
"errors"

"github.com/hsheth2/logs"
)

Expand Down Expand Up @@ -39,7 +41,11 @@ func (lo *loopbackIO) Write(data []byte) (int, error) {

func (lo *loopbackIO) Read() ([]byte, error) {
///*logs*/logs.Trace.Println("read packet off network_tap")
return <-lo.readBuf, nil // TODO check if chan is closed
res := <-lo.readBuf
if len(res) == 0 {
return nil, errors.New("Channel is closed!")
}
return <-lo.readBuf, nil
}

func (lo *loopbackIO) Close() error {
Expand Down
44 changes: 25 additions & 19 deletions ping/ping_echo_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (

"github.com/hsheth2/gonet/ipv4"

"sync/atomic"

"github.com/hsheth2/logs"
)

Expand All @@ -25,7 +27,7 @@ func (pm *Ping_Manager) ping_response_dealer() {
}
}

func sendSinglePing(writer ipv4.Writer, id, seq uint16, timeout time.Duration, reply chan *icmp.Packet) {
func sendSinglePing(writer ipv4.Writer, id uint16, seq uint16, timeout time.Duration, reply chan *icmp.Packet) {
// prepare packet
packet := &icmp.Header{
Tp: icmp.EchoRequest,
Expand All @@ -40,17 +42,18 @@ func sendSinglePing(writer ipv4.Writer, id, seq uint16, timeout time.Duration, r
time1 := time.Now()
timeoutTimer := time.NewTimer(timeout)
go func(seqChan chan *icmp.Packet, header *icmp.Header, time1 *time.Time, timer *time.Timer) {
defer close(seqChan)
for {
select {
case pingResonse := <-seqChan:
if !bytes.Equal(pingResonse.Header.Data, header.Data) {
case pingResponse := <-seqChan:
if !bytes.Equal(pingResponse.Header.Data, header.Data) {
/*logs*/ logs.Info.Println("Dropped packet because header data not equal to ping sent")
continue
}
time2 := time.Now()
logs.Info.Printf("%d bytes from %v: icmp_seq=%d time=%f ms",
len(header.Data)+icmp.HeaderMinSize,
pingResonse.RIP.IP,
pingResponse.RIP.IP,
uint16(header.Opt),
float32(time2.Sub(*time1).Nanoseconds())/1000000) // put ttl
return
Expand All @@ -62,22 +65,22 @@ func sendSinglePing(writer ipv4.Writer, id, seq uint16, timeout time.Duration, r
}(reply, packet, &time1, timeoutTimer)
}

func (pm *Ping_Manager) initIdentifier(terminate chan bool) (id uint16, seqChannel map[uint16](chan *icmp.Packet), err error) {
func (pm *Ping_Manager) initIdentifier(terminate chan bool, numPings uint16, pingCount *uint32) (uint16, [](chan *icmp.Packet), error) {
// get identifier
pm.currentIdentifier++
id = pm.currentIdentifier
id := pm.currentIdentifier

// setup sequence number dealer
pm.identifiers[id] = make(chan *icmp.Packet)
seqChannel = make(map[uint16](chan *icmp.Packet))
seqChannel := make([](chan *icmp.Packet), numPings)

// create go routine function to deal packets
go sequenceDealer(pm.identifiers[id], seqChannel, terminate)
go sequenceDealer(pm.identifiers[id], seqChannel, terminate, pingCount)

return id, seqChannel, nil
}

func sequenceDealer(idInput chan *icmp.Packet, seqChan map[uint16](chan *icmp.Packet), terminate chan bool) {
func sequenceDealer(idInput chan *icmp.Packet, seqChan [](chan *icmp.Packet), terminate chan bool, pingCount *uint32) {
// TODO verify IPs
for {
select {
Expand All @@ -86,21 +89,23 @@ func sequenceDealer(idInput chan *icmp.Packet, seqChan map[uint16](chan *icmp.Pa
return
case packet := <-idInput:
// /*logs*/logs.Info.Println("icmp in =", packet.Header.Opt)
seqNum := uint16(packet.Header.Opt)
if _, ok := seqChan[seqNum]; ok { // FIXME data race
seqChan[seqNum] <- packet
seqNum := packet.Header.Opt << 16 >> 16
pingC := atomic.LoadUint32(pingCount)
if seqNum <= pingC {
seqChan[seqNum-1] <- packet
} else {
/*logs*/ logs.Info.Println("Dropping bad seq num packet with existing identifier")
/*logs*/ logs.Info.Println("Dropping bad seq num packet with existing identifier, seqNum-id:", seqNum, "pingcount:", pingC)
}
}
}
}

const FLOOD_INTERVAL = 0
const FLOOD_INTERVAL = 0 // TODO add a flood option

func (pm *Ping_Manager) SendPing(ip *ipv4.Address, interval, timeout time.Duration, numPings uint16) error {
terminate := make(chan bool)
id, seqChannel, err := pm.initIdentifier(terminate)
pingCount := uint32(0)
id, seqChannel, err := pm.initIdentifier(terminate, numPings, &pingCount)
if err != nil {
logs.Error.Println(err)
return err
Expand All @@ -114,13 +119,14 @@ func (pm *Ping_Manager) SendPing(ip *ipv4.Address, interval, timeout time.Durati
return err
}

for i := uint16(1); i <= numPings; i++ {
seqChannel[i] = make(chan *icmp.Packet) // FIXME data race
for pingCount < uint32(numPings) {
seqChannel[pingCount] = make(chan *icmp.Packet)
atomic.AddUint32(&pingCount, 1)

sendSinglePing(writer, id, i, timeout, seqChannel[i]) // function is non-blocking
sendSinglePing(writer, id, uint16(pingCount), timeout, seqChannel[pingCount-1]) // function is non-blocking

// not last
if i != numPings {
if uint16(pingCount) != numPings {
time.Sleep(interval)
}
}
Expand Down
8 changes: 6 additions & 2 deletions run_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

export name=`basename $1`
go test -race -c -v $1
sudo setcap CAP_NET_RAW=epi ./${name}.test
sudo setcap CAP_NET_ADMIN=epi ./${name}.test
if [ ! -f /.dockerenv ]; then
# not inside docker
# see https://github.com/docker/docker/issues/5650
sudo setcap CAP_NET_RAW=epi ./${name}.test
sudo setcap CAP_NET_ADMIN=epi ./${name}.test
fi
./${name}.test -test.v
#rm ${name}.test
Loading

0 comments on commit b290691

Please sign in to comment.