...

Source file src/github.com/mdlayher/ethernet/ethernet_test.go

Documentation: github.com/mdlayher/ethernet

     1  package ethernet
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"net"
     7  	"reflect"
     8  	"testing"
     9  )
    10  
    11  func TestFrameMarshalBinary(t *testing.T) {
    12  	tests := []struct {
    13  		desc string
    14  		f    *Frame
    15  		b    []byte
    16  		err  error
    17  	}{
    18  		{
    19  			desc: "S-VLAN, no C-VLAN",
    20  			f: &Frame{
    21  				// Contents don't matter.
    22  				ServiceVLAN: &VLAN{},
    23  			},
    24  			err: ErrInvalidVLAN,
    25  		},
    26  		{
    27  			desc: "IPv4, no VLANs",
    28  			f: &Frame{
    29  				Destination: net.HardwareAddr{0, 1, 0, 1, 0, 1},
    30  				Source:      net.HardwareAddr{1, 0, 1, 0, 1, 0},
    31  				EtherType:   EtherTypeIPv4,
    32  				Payload:     bytes.Repeat([]byte{0}, 50),
    33  			},
    34  			b: append([]byte{
    35  				0, 1, 0, 1, 0, 1,
    36  				1, 0, 1, 0, 1, 0,
    37  				0x08, 0x00,
    38  			}, bytes.Repeat([]byte{0}, 50)...),
    39  		},
    40  		{
    41  			desc: "IPv6, C-VLAN: (PRI 1, ID 101)",
    42  			f: &Frame{
    43  				Destination: net.HardwareAddr{1, 0, 1, 0, 1, 0},
    44  				Source:      net.HardwareAddr{0, 1, 0, 1, 0, 1},
    45  				VLAN: &VLAN{
    46  					Priority: 1,
    47  					ID:       101,
    48  				},
    49  				EtherType: EtherTypeIPv6,
    50  				Payload:   bytes.Repeat([]byte{0}, 50),
    51  			},
    52  			b: append([]byte{
    53  				1, 0, 1, 0, 1, 0,
    54  				0, 1, 0, 1, 0, 1,
    55  				0x81, 0x00,
    56  				0x20, 0x65,
    57  				0x86, 0xDD,
    58  			}, bytes.Repeat([]byte{0}, 50)...),
    59  		},
    60  		{
    61  			desc: "ARP, S-VLAN: (PRI 0, DROP, ID 100), C-VLAN: (PRI 1, ID 101)",
    62  			f: &Frame{
    63  				Destination: Broadcast,
    64  				Source:      net.HardwareAddr{0, 1, 0, 1, 0, 1},
    65  				ServiceVLAN: &VLAN{
    66  					DropEligible: true,
    67  					ID:           100,
    68  				},
    69  				VLAN: &VLAN{
    70  					Priority: 1,
    71  					ID:       101,
    72  				},
    73  				EtherType: EtherTypeARP,
    74  				Payload:   bytes.Repeat([]byte{0}, 50),
    75  			},
    76  			b: append([]byte{
    77  				0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    78  				0, 1, 0, 1, 0, 1,
    79  				0x88, 0xa8,
    80  				0x10, 0x64,
    81  				0x81, 0x00,
    82  				0x20, 0x65,
    83  				0x08, 0x06,
    84  			}, bytes.Repeat([]byte{0}, 50)...),
    85  		},
    86  	}
    87  
    88  	for _, tt := range tests {
    89  		t.Run(tt.desc, func(t *testing.T) {
    90  			b, err := tt.f.MarshalBinary()
    91  			if err != nil {
    92  				if want, got := tt.err, err; want != got {
    93  					t.Fatalf("unexpected error: %v != %v", want, got)
    94  				}
    95  
    96  				return
    97  			}
    98  
    99  			if want, got := tt.b, b; !bytes.Equal(want, got) {
   100  				t.Fatalf("unexpected Frame bytes:\n- want: %v\n-  got: %v", want, got)
   101  			}
   102  		})
   103  	}
   104  }
   105  
   106  func TestFrameMarshalFCS(t *testing.T) {
   107  	tests := []struct {
   108  		desc string
   109  		f    *Frame
   110  		b    []byte
   111  		err  error
   112  	}{
   113  		{
   114  			desc: "IPv4, no VLANs",
   115  			f: &Frame{
   116  				Destination: net.HardwareAddr{0, 1, 0, 1, 0, 1},
   117  				Source:      net.HardwareAddr{1, 0, 1, 0, 1, 0},
   118  				EtherType:   EtherTypeIPv4,
   119  				Payload:     bytes.Repeat([]byte{0}, 50),
   120  			},
   121  			b: append(
   122  				append(
   123  					[]byte{
   124  						0, 1, 0, 1, 0, 1,
   125  						1, 0, 1, 0, 1, 0,
   126  						0x08, 0x00,
   127  					},
   128  					bytes.Repeat([]byte{0}, 50)...,
   129  				),
   130  				[]byte{159, 205, 24, 60}...,
   131  			),
   132  		},
   133  	}
   134  
   135  	for _, tt := range tests {
   136  		t.Run(tt.desc, func(t *testing.T) {
   137  			b, err := tt.f.MarshalFCS()
   138  			if err != nil {
   139  				if want, got := tt.err, err; want != got {
   140  					t.Fatalf("unexpected error: %v != %v", want, got)
   141  				}
   142  
   143  				return
   144  			}
   145  
   146  			if want, got := tt.b, b; !bytes.Equal(want, got) {
   147  				t.Fatalf("unexpected Frame bytes:\n- want: %v\n-  got: %v", want, got)
   148  			}
   149  		})
   150  	}
   151  }
   152  
   153  func TestFrameUnmarshalBinary(t *testing.T) {
   154  	tests := []struct {
   155  		desc string
   156  		b    []byte
   157  		f    *Frame
   158  		err  error
   159  	}{
   160  		{
   161  			desc: "nil buffer",
   162  			err:  io.ErrUnexpectedEOF,
   163  		},
   164  		{
   165  			desc: "short buffer",
   166  			b:    bytes.Repeat([]byte{0}, 13),
   167  			err:  io.ErrUnexpectedEOF,
   168  		},
   169  		{
   170  			desc: "1 short S-VLAN",
   171  			b: []byte{
   172  				0, 0, 0, 0, 0, 0,
   173  				0, 0, 0, 0, 0, 0,
   174  				0x88, 0xa8,
   175  				0x00,
   176  			},
   177  			err: io.ErrUnexpectedEOF,
   178  		},
   179  		{
   180  			desc: "1 short C-VLAN",
   181  			b: []byte{
   182  				0, 0, 0, 0, 0, 0,
   183  				0, 0, 0, 0, 0, 0,
   184  				0x81, 0x00,
   185  				0x00,
   186  			},
   187  			err: io.ErrUnexpectedEOF,
   188  		},
   189  		{
   190  			desc: "VLAN ID too large",
   191  			b: []byte{
   192  				0, 0, 0, 0, 0, 0,
   193  				0, 0, 0, 0, 0, 0,
   194  				0x81, 0x00,
   195  				0xff, 0xff,
   196  				0x00, 0x00,
   197  			},
   198  			err: ErrInvalidVLAN,
   199  		},
   200  		{
   201  			desc: "no C-VLAN after S-VLAN",
   202  			b: []byte{
   203  				0, 0, 0, 0, 0, 0,
   204  				0, 0, 0, 0, 0, 0,
   205  				0x88, 0xa8,
   206  				0x20, 0x65,
   207  				0x08, 0x06,
   208  				0x00, 0x00, 0x00, 0x00,
   209  			},
   210  			err: ErrInvalidVLAN,
   211  		},
   212  		{
   213  			desc: "short C-VLAN after S-VLAN",
   214  			b: []byte{
   215  				0, 0, 0, 0, 0, 0,
   216  				0, 0, 0, 0, 0, 0,
   217  				0x88, 0xa8,
   218  				0x20, 0x65,
   219  				0x81, 0x00,
   220  				0x00, 0x00,
   221  			},
   222  			err: io.ErrUnexpectedEOF,
   223  		},
   224  		{
   225  			desc: "go-fuzz crasher: VLAN tag without enough bytes for trailing EtherType",
   226  			b:    []byte("190734863281\x81\x0032"),
   227  			err:  io.ErrUnexpectedEOF,
   228  		},
   229  		{
   230  			desc: "0 VLANs detected, but 1 may have been present",
   231  			b:    bytes.Repeat([]byte{0}, 56),
   232  			f: &Frame{
   233  				Destination: net.HardwareAddr{0, 0, 0, 0, 0, 0},
   234  				Source:      net.HardwareAddr{0, 0, 0, 0, 0, 0},
   235  				Payload:     bytes.Repeat([]byte{0}, 42),
   236  			},
   237  		},
   238  		{
   239  			desc: "IPv4, no VLANs",
   240  			b: append([]byte{
   241  				0, 1, 0, 1, 0, 1,
   242  				1, 0, 1, 0, 1, 0,
   243  				0x08, 0x00,
   244  			}, bytes.Repeat([]byte{0}, 50)...),
   245  			f: &Frame{
   246  				Destination: net.HardwareAddr{0, 1, 0, 1, 0, 1},
   247  				Source:      net.HardwareAddr{1, 0, 1, 0, 1, 0},
   248  				EtherType:   EtherTypeIPv4,
   249  				Payload:     bytes.Repeat([]byte{0}, 50),
   250  			},
   251  		},
   252  		{
   253  			desc: "IPv6, C-VLAN: (PRI 1, ID 101)",
   254  			b: append([]byte{
   255  				1, 0, 1, 0, 1, 0,
   256  				0, 1, 0, 1, 0, 1,
   257  				0x81, 0x00,
   258  				0x20, 0x65,
   259  				0x86, 0xDD,
   260  			}, bytes.Repeat([]byte{0}, 50)...),
   261  			f: &Frame{
   262  				Destination: net.HardwareAddr{1, 0, 1, 0, 1, 0},
   263  				Source:      net.HardwareAddr{0, 1, 0, 1, 0, 1},
   264  				VLAN: &VLAN{
   265  					Priority: 1,
   266  					ID:       101,
   267  				},
   268  				EtherType: EtherTypeIPv6,
   269  				Payload:   bytes.Repeat([]byte{0}, 50),
   270  			},
   271  		},
   272  		{
   273  			desc: "ARP, S-VLAN: (PRI 0, DROP, ID 100), C-VLAN: (PRI 1, ID 101)",
   274  			b: append([]byte{
   275  				0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   276  				0, 1, 0, 1, 0, 1,
   277  				0x88, 0xa8,
   278  				0x10, 0x64,
   279  				0x81, 0x00,
   280  				0x20, 0x65,
   281  				0x08, 0x06,
   282  			}, bytes.Repeat([]byte{0}, 50)...),
   283  			f: &Frame{
   284  				Destination: Broadcast,
   285  				Source:      net.HardwareAddr{0, 1, 0, 1, 0, 1},
   286  				ServiceVLAN: &VLAN{
   287  					DropEligible: true,
   288  					ID:           100,
   289  				},
   290  				VLAN: &VLAN{
   291  					Priority: 1,
   292  					ID:       101,
   293  				},
   294  				EtherType: EtherTypeARP,
   295  				Payload:   bytes.Repeat([]byte{0}, 50),
   296  			},
   297  		},
   298  	}
   299  
   300  	for _, tt := range tests {
   301  		t.Run(tt.desc, func(t *testing.T) {
   302  			f := new(Frame)
   303  			if err := f.UnmarshalBinary(tt.b); err != nil {
   304  				if want, got := tt.err, err; want != got {
   305  					t.Fatalf("unexpected error: %v != %v", want, got)
   306  				}
   307  
   308  				return
   309  			}
   310  
   311  			if want, got := tt.f, f; !reflect.DeepEqual(want, got) {
   312  				t.Fatalf("unexpected Frame:\n- want: %v\n-  got: %v", want, got)
   313  			}
   314  		})
   315  	}
   316  }
   317  
   318  func TestFrameUnmarshalFCS(t *testing.T) {
   319  	tests := []struct {
   320  		desc string
   321  		b    []byte
   322  		f    *Frame
   323  		err  error
   324  	}{
   325  		{
   326  			desc: "too short for FCS",
   327  			b:    []byte{1, 2, 3},
   328  			err:  io.ErrUnexpectedEOF,
   329  		},
   330  		{
   331  			desc: "invalid FCS",
   332  			b:    []byte{1, 2, 3, 4},
   333  			err:  ErrInvalidFCS,
   334  		},
   335  		{
   336  			desc: "IPv4, no VLANs",
   337  			b: append(
   338  				append(
   339  					[]byte{
   340  						0, 1, 0, 1, 0, 1,
   341  						1, 0, 1, 0, 1, 0,
   342  						0x08, 0x00,
   343  					},
   344  					bytes.Repeat([]byte{0}, 50)...,
   345  				),
   346  				[]byte{159, 205, 24, 60}...,
   347  			),
   348  			f: &Frame{
   349  				Destination: net.HardwareAddr{0, 1, 0, 1, 0, 1},
   350  				Source:      net.HardwareAddr{1, 0, 1, 0, 1, 0},
   351  				EtherType:   EtherTypeIPv4,
   352  				Payload:     bytes.Repeat([]byte{0}, 50),
   353  			},
   354  		},
   355  	}
   356  
   357  	for _, tt := range tests {
   358  		t.Run(tt.desc, func(t *testing.T) {
   359  			f := new(Frame)
   360  			if err := f.UnmarshalFCS(tt.b); err != nil {
   361  				if want, got := tt.err, err; want != got {
   362  					t.Fatalf("unexpected error: %v != %v", want, got)
   363  				}
   364  
   365  				return
   366  			}
   367  
   368  			if want, got := tt.f, f; !reflect.DeepEqual(want, got) {
   369  				t.Fatalf("unexpected Frame:\n- want: %v\n-  got: %v", want, got)
   370  			}
   371  		})
   372  	}
   373  }
   374  
   375  // Benchmarks for Frame.MarshalBinary with varying VLAN tags and payloads
   376  
   377  func BenchmarkFrameMarshalBinary(b *testing.B) {
   378  	f := &Frame{
   379  		Payload: []byte{0, 1, 2, 3, 4},
   380  	}
   381  
   382  	benchmarkFrameMarshalBinary(b, f)
   383  }
   384  
   385  func BenchmarkFrameMarshalBinaryCVLAN(b *testing.B) {
   386  	f := &Frame{
   387  		VLAN: &VLAN{
   388  			Priority: PriorityBackground,
   389  			ID:       10,
   390  		},
   391  		Payload: []byte{0, 1, 2, 3, 4},
   392  	}
   393  
   394  	benchmarkFrameMarshalBinary(b, f)
   395  }
   396  
   397  func BenchmarkFrameMarshalBinarySVLANCVLAN(b *testing.B) {
   398  	f := &Frame{
   399  		ServiceVLAN: &VLAN{
   400  			Priority: PriorityBackground,
   401  			ID:       10,
   402  		},
   403  		VLAN: &VLAN{
   404  			Priority: PriorityBestEffort,
   405  			ID:       20,
   406  		},
   407  		Payload: []byte{0, 1, 2, 3, 4},
   408  	}
   409  
   410  	benchmarkFrameMarshalBinary(b, f)
   411  }
   412  
   413  func BenchmarkFrameMarshalBinaryJumboPayload(b *testing.B) {
   414  	f := &Frame{
   415  		Payload: make([]byte, 8192),
   416  	}
   417  
   418  	benchmarkFrameMarshalBinary(b, f)
   419  }
   420  
   421  func benchmarkFrameMarshalBinary(b *testing.B, f *Frame) {
   422  	f.Destination = net.HardwareAddr{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad}
   423  	f.Source = net.HardwareAddr{0xad, 0xbe, 0xef, 0xde, 0xad, 0xde}
   424  
   425  	b.ResetTimer()
   426  	b.ReportAllocs()
   427  	for i := 0; i < b.N; i++ {
   428  		if _, err := f.MarshalBinary(); err != nil {
   429  			b.Fatal(err)
   430  		}
   431  	}
   432  }
   433  
   434  // Benchmarks for Frame.MarshalFCS
   435  
   436  func BenchmarkFrameMarshalFCS(b *testing.B) {
   437  	f := &Frame{
   438  		Payload: []byte{0, 1, 2, 3, 4},
   439  	}
   440  
   441  	benchmarkFrameMarshalFCS(b, f)
   442  }
   443  
   444  func benchmarkFrameMarshalFCS(b *testing.B, f *Frame) {
   445  	f.Destination = net.HardwareAddr{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad}
   446  	f.Source = net.HardwareAddr{0xad, 0xbe, 0xef, 0xde, 0xad, 0xde}
   447  
   448  	b.ResetTimer()
   449  	b.ReportAllocs()
   450  	for i := 0; i < b.N; i++ {
   451  		if _, err := f.MarshalFCS(); err != nil {
   452  			b.Fatal(err)
   453  		}
   454  	}
   455  }
   456  
   457  // Benchmarks for Frame.UnmarshalBinary with varying VLAN tags and payloads
   458  
   459  func BenchmarkFrameUnmarshalBinary(b *testing.B) {
   460  	f := &Frame{
   461  		Payload: []byte{0, 1, 2, 3, 4},
   462  	}
   463  
   464  	benchmarkFrameUnmarshalBinary(b, f)
   465  }
   466  
   467  func BenchmarkFrameUnmarshalBinaryCVLAN(b *testing.B) {
   468  	f := &Frame{
   469  		VLAN: &VLAN{
   470  			Priority: PriorityBackground,
   471  			ID:       10,
   472  		},
   473  
   474  		Payload: []byte{0, 1, 2, 3, 4},
   475  	}
   476  
   477  	benchmarkFrameUnmarshalBinary(b, f)
   478  }
   479  
   480  func BenchmarkFrameUnmarshalBinarySVLANCVLAN(b *testing.B) {
   481  	f := &Frame{
   482  		ServiceVLAN: &VLAN{
   483  			Priority: PriorityBackground,
   484  			ID:       10,
   485  		},
   486  		VLAN: &VLAN{
   487  			Priority: PriorityBestEffort,
   488  			ID:       20,
   489  		},
   490  		Payload: []byte{0, 1, 2, 3, 4},
   491  	}
   492  
   493  	benchmarkFrameUnmarshalBinary(b, f)
   494  }
   495  
   496  func BenchmarkFrameUnmarshalBinaryJumboPayload(b *testing.B) {
   497  	f := &Frame{
   498  		Payload: make([]byte, 8192),
   499  	}
   500  
   501  	benchmarkFrameUnmarshalBinary(b, f)
   502  }
   503  
   504  func benchmarkFrameUnmarshalBinary(b *testing.B, f *Frame) {
   505  	f.Destination = net.HardwareAddr{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad}
   506  	f.Source = net.HardwareAddr{0xad, 0xbe, 0xef, 0xde, 0xad, 0xde}
   507  
   508  	fb, err := f.MarshalBinary()
   509  	if err != nil {
   510  		b.Fatal(err)
   511  	}
   512  
   513  	b.ResetTimer()
   514  	b.ReportAllocs()
   515  	for i := 0; i < b.N; i++ {
   516  		if err := f.UnmarshalBinary(fb); err != nil {
   517  			b.Fatal(err)
   518  		}
   519  	}
   520  }
   521  
   522  // Benchmarks for Frame.UnmarshalFCS
   523  
   524  func BenchmarkFrameUnmarshalFCS(b *testing.B) {
   525  	f := &Frame{
   526  		Payload: []byte{0, 1, 2, 3, 4},
   527  	}
   528  
   529  	benchmarkFrameUnmarshalFCS(b, f)
   530  }
   531  
   532  func benchmarkFrameUnmarshalFCS(b *testing.B, f *Frame) {
   533  	f.Destination = net.HardwareAddr{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad}
   534  	f.Source = net.HardwareAddr{0xad, 0xbe, 0xef, 0xde, 0xad, 0xde}
   535  
   536  	fb, err := f.MarshalFCS()
   537  	if err != nil {
   538  		b.Fatal(err)
   539  	}
   540  
   541  	b.ResetTimer()
   542  	b.ReportAllocs()
   543  	for i := 0; i < b.N; i++ {
   544  		if err := f.UnmarshalFCS(fb); err != nil {
   545  			b.Fatal(err)
   546  		}
   547  	}
   548  }
   549  

View as plain text