Skip to content

Commit c3de4e6

Browse files
committed
adding test cases for ipv4 parsing
1 parent 31d4bf6 commit c3de4e6

File tree

5 files changed

+151
-41
lines changed

5 files changed

+151
-41
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ controller.RegisterApplication(NewDemoInstance)
1515

1616
### Receive
1717
To receive OpenFlow messages, applications should implement the interfaces
18-
found in `protocol/ofp10/interface.go` or `protocol/ofp13/interface.go`. You
19-
only need to implement the interfaces you're interested in.
18+
found in `protocol/ofp10/interface.go` or `protocol/ofp13/interface.go`.
2019
```
2120
func (b *DemoInstance) ConnectionUp(dpid net.HardwareAddr) {
2221
log.Println("Switch connected:", dpid)
@@ -39,7 +38,7 @@ req := ofp10.NewEchoRequest()
3938
4039
// If switch dpid is known, returns its OFPSwitch struct. The
4140
// switch is not guaranteed to have an active connection.
42-
if sw, ok := core.Switch(dpid string); ok {
41+
if sw, ok := ogo.Switch(dpid string); ok {
4342
sw.Send(req)
4443
}
4544
```

protocol/eth/ethernet.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,7 @@ func (e *Ethernet) UnmarshalBinary(data []byte) error {
121121
default:
122122
e.Data = new(util.Buffer)
123123
}
124-
err := e.Data.UnmarshalBinary(data[n:])
125-
126-
return err
124+
return e.Data.UnmarshalBinary(data[n:])
127125
}
128126

129127
const (

protocol/ipv4/ip.go

Lines changed: 71 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"encoding/binary"
55
"errors"
66
"net"
7-
7+
88
"github.com/jonstout/ogo/protocol/icmp"
99
"github.com/jonstout/ogo/protocol/udp"
1010
"github.com/jonstout/ogo/protocol/util"
@@ -36,71 +36,109 @@ type IPv4 struct {
3636
Data util.Message
3737
}
3838

39+
func New() *IPv4 {
40+
ip := new(IPv4)
41+
ip.NWSrc = make([]byte, 4)
42+
ip.NWDst = make([]byte, 4)
43+
ip.Options = *new(util.Buffer)
44+
return ip
45+
}
46+
3947
func (i *IPv4) Len() (n uint16) {
48+
i.IHL = 5
4049
if i.Data != nil {
4150
return uint16(i.IHL*4) + i.Data.Len()
4251
}
4352
return uint16(i.IHL * 4)
4453
}
4554

4655
func (i *IPv4) MarshalBinary() (data []byte, err error) {
47-
data = make([]byte, int(i.IHL * 4))
56+
data = make([]byte, int(i.Len()))
57+
b := make([]byte, 0)
58+
n := 0
59+
4860
var ihl uint8 = (i.Version << 4) + i.IHL
49-
data[0] = ihl
61+
data[n] = ihl
62+
n += 1
5063
var ecn uint8 = (i.DSCP << 2) + i.ECN
51-
data[1] = ecn
52-
binary.BigEndian.PutUint16(data[2:4], i.Length)
53-
binary.BigEndian.PutUint16(data[4:6], i.Id)
64+
data[n] = ecn
65+
n += 1
66+
binary.BigEndian.PutUint16(data[n:], i.Length)
67+
n += 2
68+
binary.BigEndian.PutUint16(data[n:], i.Id)
69+
n += 2
5470
var flg uint16 = (i.Flags << 13) + i.FragmentOffset
55-
binary.BigEndian.PutUint16(data[6:8], flg)
56-
data[8] = i.TTL
57-
data[9] = i.Protocol
58-
binary.BigEndian.PutUint16(data[10:12], i.Checksum)
59-
copy(data[12:16], i.NWSrc)
60-
copy(data[16:20], i.NWDst)
61-
n := 20 + i.Options.Len()
62-
i.Options.Read(data[20:n])
63-
64-
bytes, err := i.Data.MarshalBinary()
65-
if err != nil {
66-
return
71+
binary.BigEndian.PutUint16(data[n:], flg)
72+
n += 2
73+
data[n] = i.TTL
74+
n += 1
75+
data[n] = i.Protocol
76+
n += 1
77+
binary.BigEndian.PutUint16(data[n:], i.Checksum)
78+
n += 2
79+
80+
copy(data[n:], i.NWSrc.To4())
81+
n += 4 // Underlying rep can be 16 bytes.
82+
copy(data[n:], i.NWDst.To4())
83+
n += 4 // Underlying rep can be 16 bytes.
84+
85+
b, err = i.Options.MarshalBinary()
86+
copy(data[n:], b)
87+
n += len(b)
88+
89+
if i.Data != nil {
90+
b, err = i.Data.MarshalBinary()
91+
if err != nil {
92+
return
93+
}
94+
copy(data[n:], b)
95+
n += len(b)
6796
}
68-
data = append(data, bytes...)
6997
return
7098
}
7199

72100
func (i *IPv4) UnmarshalBinary(data []byte) error {
73101
if len(data) < 20 {
74102
return errors.New("The []byte is too short to unmarshal a full IPv4 message.")
75103
}
104+
n := 0
105+
76106
var ihl uint8
77-
ihl = data[0]
107+
ihl = data[n]
78108
i.Version = ihl >> 4
79109
i.IHL = ihl & 0x0f
110+
n += 1
80111

81112
var ecn uint8
82-
ecn = data[1]
113+
ecn = data[n]
83114
i.DSCP = ecn >> 2
84115
i.ECN = ecn & 0x03
116+
n += 1
85117

86-
i.Length = binary.BigEndian.Uint16(data[2:4])
87-
i.Id = binary.BigEndian.Uint16(data[4:6])
118+
i.Length = binary.BigEndian.Uint16(data[n:])
119+
n += 2
120+
i.Id = binary.BigEndian.Uint16(data[n:])
121+
n += 2
88122

89123
var flg uint16
90-
flg = binary.BigEndian.Uint16(data[6:8])
124+
flg = binary.BigEndian.Uint16(data[n:])
91125
i.Flags = flg >> 13
92126
i.FragmentOffset = flg & 0x1fff
127+
n += 2
93128

94-
i.TTL = data[8]
95-
i.Protocol = data[9]
96-
i.Checksum = binary.BigEndian.Uint16(data[10:12])
97-
i.NWSrc = data[12:16]
98-
i.NWDst = data[16:20]
99-
n := 20
129+
i.TTL = data[n]
130+
n += 1
131+
i.Protocol = data[n]
132+
n += 1
133+
i.Checksum = binary.BigEndian.Uint16(data[n:])
134+
n += 2
135+
i.NWSrc = data[n:n+4]
136+
n += 4
137+
i.NWDst = data[n:n+4]
138+
n += 4
100139

101-
i.Options = *new(util.Buffer)
102140
i.Options.UnmarshalBinary(data[n:int(i.IHL * 4)])
103-
n += int(i.IHL *4)
141+
n += int(i.IHL * 4) - n
104142

105143
switch i.Protocol {
106144
case Type_ICMP:
@@ -110,6 +148,5 @@ func (i *IPv4) UnmarshalBinary(data []byte) error {
110148
default:
111149
i.Data = new(util.Buffer)
112150
}
113-
err := i.Data.UnmarshalBinary(data[n:])
114-
return err
151+
return i.Data.UnmarshalBinary(data[n:])
115152
}

protocol/ipv4/ip_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package ipv4
2+
3+
import (
4+
"bytes"
5+
"encoding/hex"
6+
"net"
7+
"strings"
8+
"testing"
9+
)
10+
11+
func TestIPv4MarshalBinary(t *testing.T) {
12+
b := " 55 " + // Version, IHL
13+
"00 " + // DSCP, ECN
14+
"00 14 " + // Length
15+
"00 00 " + // Id
16+
"00 00 " + // Flags, FragmentOffset
17+
"01 " + // TTL
18+
"06 " + // Protocol
19+
"00 00 " + // Checksum
20+
"7f 00 00 01 " + // NWSrc
21+
"08 08 08 08 " // NWDst
22+
b = strings.Replace(b, " ", "", -1)
23+
24+
ip := New()
25+
ip.NWSrc = net.ParseIP("127.0.0.1")
26+
ip.NWDst = net.ParseIP("8.8.8.8")
27+
ip.Version = 5
28+
ip.Length = 20
29+
ip.TTL = 1
30+
ip.Protocol = Type_TCP
31+
32+
data, _ := ip.MarshalBinary()
33+
d := hex.EncodeToString(data)
34+
if (len(b) != len(d)) || (b != d) {
35+
t.Log("Exp:", b)
36+
t.Log("Rec:", d)
37+
t.Errorf("Received length of %d, expected %d", len(d), len(b))
38+
}
39+
}
40+
41+
func TestIPv4UnmarshalBinary(t *testing.T) {
42+
b := " 55 " + // Version, IHL
43+
"00 " + // DSCP, ECN
44+
"00 14 " + // Length
45+
"00 00 " + // Id
46+
"00 00 " + // Flags, FragmentOffset
47+
"01 " + // TTL
48+
"06 " + // Protocol
49+
"09 af " + // Checksum
50+
"7f 00 00 01 " + // NWSrc
51+
"08 08 08 08 " // NWDst
52+
b = strings.Replace(b, " ", "", -1)
53+
byte, _ := hex.DecodeString(b)
54+
55+
ip := New()
56+
ip.UnmarshalBinary(byte)
57+
58+
src := net.ParseIP("127.0.0.1").To4()
59+
dst := net.ParseIP("8.8.8.8").To4()
60+
61+
if int(ip.Len()) != len(byte) {
62+
t.Errorf("Got length of %d, expected %d.", ip.Len(), len(byte))
63+
} else if ip.Version != 5 {
64+
t.Errorf("Got type %d, expected %d.", ip.Version, 5)
65+
} else if ip.Length != 20 {
66+
t.Errorf("Got length %d, expected %d.", ip.Length, 20)
67+
} else if ip.TTL != 1 {
68+
t.Errorf("Got ttl %d, expected %d.", ip.TTL, 1)
69+
} else if ip.Protocol != Type_TCP {
70+
t.Errorf("Got protocol %d, expected %d.", ip.Protocol, Type_TCP)
71+
} else if bytes.Compare(ip.NWSrc, src) != 0 {
72+
t.Errorf("Got nw-src %d, expected %d.", ip.NWSrc, src)
73+
} else if bytes.Compare(ip.NWDst, dst) != 0 {
74+
t.Errorf("Got nw-dst %d, expected %d.", ip.NWDst, dst)
75+
}
76+
}

protocol/util/buffer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func NewBuffer(buf []byte) *Buffer {
1313
}
1414

1515
func (b *Buffer) Len() uint16 {
16-
return uint16(b.Len())
16+
return uint16(b.Buffer.Len())
1717
}
1818

1919
func (b *Buffer) MarshalBinary() (data []byte, err error) {

0 commit comments

Comments
 (0)