Skip to content

Commit efe7f7b

Browse files
committed
- add some methods for VLAN
- fix VLAN.UnmarshalBinary and VLANs.UnmarshalBinary on handing empty slice
1 parent 28cb5f1 commit efe7f7b

File tree

2 files changed

+93
-3
lines changed

2 files changed

+93
-3
lines changed

etherconn.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,23 @@ const (
147147
NOVLANTAG = 0xffff
148148
)
149149

150-
// VLAN reprents a VLAN tag
150+
// VLAN reprents a VLAN tag.
151+
// Note: VLAN shouldn't be used directly, use VLANs instead even if there is only one tag
151152
type VLAN struct {
152153
ID uint16
153154
EtherType uint16
154155
}
155156

157+
// Equal return true if both v's ID and EtherType equals to vlan
158+
func (vlan VLAN) Equal(v VLAN) bool {
159+
return v.ID == vlan.ID && v.EtherType == vlan.EtherType
160+
}
161+
162+
// IsUnspecified return true if both vlan's ID and EtherType is zero
163+
func (vlan VLAN) IsUnspecified() bool {
164+
return vlan.ID == 0 && vlan.EtherType == 0
165+
}
166+
156167
// MarshalBinary implements encoding.BinaryMarshaler interface
157168
func (vlan VLAN) MarshalBinary() (data []byte, err error) {
158169
data = make([]byte, 4)
@@ -163,8 +174,13 @@ func (vlan VLAN) MarshalBinary() (data []byte, err error) {
163174

164175
// UnmarshalBinary implements encoding.BinaryUnmarshaler interface
165176
func (vlan *VLAN) UnmarshalBinary(data []byte) error {
177+
if len(data) == 0 {
178+
vlan.ID = 0
179+
vlan.EtherType = 0
180+
return nil
181+
}
166182
if len(data) < 4 {
167-
return fmt.Errorf("can't unmarshal VLAN from a byte slice less than 4 bytes")
183+
return fmt.Errorf("can't unmarshal VLAN from a byte slice less than 4 bytes, got %d bytes", len(data))
168184
}
169185
vlan.ID = binary.BigEndian.Uint16(data[:2])
170186
vlan.EtherType = binary.BigEndian.Uint16(data[2:4])
@@ -194,8 +210,13 @@ func (vlans VLANs) MarshalBinary() (data []byte, err error) {
194210

195211
// UnmarshalBinary implements encoding.BinaryUnmarshaler interface
196212
func (vlans *VLANs) UnmarshalBinary(data []byte) error {
213+
if len(data) == 0 {
214+
*vlans = []*VLAN{}
215+
return nil
216+
}
217+
197218
if len(data) < 4 {
198-
return fmt.Errorf("can't unmarshal VLANs from a byte slice less than 4 bytes")
219+
return fmt.Errorf("can't unmarshal VLANs from a byte slice less than 4 bytes, got %d bytes", len(data))
199220
}
200221
*vlans = []*VLAN{}
201222
for start := 0; start+4 <= len(data); start += 4 {

etherconn_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,13 @@ func TestVLANs(t *testing.T) {
950950
},
951951
shouldFail: true,
952952
},
953+
{
954+
v: etherconn.VLANs{},
955+
vs: "",
956+
newIDs: []uint16{},
957+
newv: etherconn.VLANs{},
958+
shouldFail: false,
959+
},
953960
}
954961
testFunc := func(c testVLANsCase) error {
955962
if len(c.vbs) != 0 {
@@ -1030,6 +1037,68 @@ func (tvlanc *testVLANsMarshalCase) dotest() error {
10301037
return nil
10311038
}
10321039

1040+
func TestVLANMarshalBinary(t *testing.T) {
1041+
type tcase struct {
1042+
vlan etherconn.VLAN
1043+
expectedMarshal []byte
1044+
unmarshalBytes []byte
1045+
shouldFail bool
1046+
}
1047+
testcaseList := []tcase{
1048+
{
1049+
vlan: etherconn.VLAN{
1050+
ID: 33,
1051+
EtherType: etherconn.DefaultVLANEtype,
1052+
},
1053+
expectedMarshal: []byte{0, 33, 0x81, 0},
1054+
},
1055+
{
1056+
vlan: etherconn.VLAN{},
1057+
expectedMarshal: []byte{0, 0, 0, 0},
1058+
},
1059+
{
1060+
vlan: etherconn.VLAN{},
1061+
expectedMarshal: []byte{0, 0, 0, 0},
1062+
unmarshalBytes: []byte{},
1063+
},
1064+
}
1065+
testFunc := func(c tcase) error {
1066+
buf, err := c.vlan.MarshalBinary()
1067+
if err != nil {
1068+
return err
1069+
}
1070+
if !bytes.Equal(buf, c.expectedMarshal) {
1071+
return fmt.Errorf("marshal result %v is different from expected %v", buf, c.expectedMarshal)
1072+
}
1073+
if c.unmarshalBytes != nil {
1074+
newv := new(etherconn.VLAN)
1075+
err = newv.UnmarshalBinary(c.unmarshalBytes)
1076+
if err != nil {
1077+
return err
1078+
}
1079+
if newv == nil {
1080+
t.Log("newv is nil")
1081+
}
1082+
if !newv.Equal(c.vlan) {
1083+
return fmt.Errorf("unmarshaled result %v is different from original one %v", newv, c.vlan)
1084+
}
1085+
1086+
}
1087+
return nil
1088+
}
1089+
for i, c := range testcaseList {
1090+
t.Logf("test case %d", i)
1091+
err := testFunc(c)
1092+
if err != nil {
1093+
if !c.shouldFail {
1094+
t.Fatalf("test case %d fails, %v", i, err)
1095+
} else {
1096+
t.Logf("case %d fails as expected, %v", i, err)
1097+
}
1098+
}
1099+
}
1100+
}
1101+
10331102
func TestVLANsUnMarhal(t *testing.T) {
10341103
testCaseList := []testVLANsMarshalCase{
10351104
//case 0,qinq with .

0 commit comments

Comments
 (0)