...

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

Documentation: github.com/mdlayher/ethernet

     1  package ethernet
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  	"io"
     7  )
     8  
     9  const (
    10  	// VLANNone is a special VLAN ID which indicates that no VLAN is being
    11  	// used in a Frame.  In this case, the VLAN's other fields may be used
    12  	// to indicate a Frame's priority.
    13  	VLANNone = 0x000
    14  
    15  	// VLANMax is a reserved VLAN ID which may indicate a wildcard in some
    16  	// management systems, but may not be configured or transmitted in a
    17  	// VLAN tag.
    18  	VLANMax = 0xfff
    19  )
    20  
    21  // ErrInvalidVLAN is returned when a VLAN tag is invalid due to one of the
    22  // following reasons:
    23  //   - Priority of greater than 7 is detected
    24  //   - ID of greater than 4094 (0xffe) is detected
    25  //   - A customer VLAN does not follow a service VLAN (when using Q-in-Q)
    26  var ErrInvalidVLAN = errors.New("invalid VLAN")
    27  
    28  // Priority is an IEEE P802.1p priority level.  Priority can be any value from
    29  // 0 to 7.
    30  //
    31  // It is important to note that priority 1 (PriorityBackground) actually has
    32  // a lower priority than 0 (PriorityBestEffort).  All other Priority constants
    33  // indicate higher priority as the integer values increase.
    34  type Priority uint8
    35  
    36  // IEEE P802.1p recommended priority levels.  Note that PriorityBackground has
    37  // a lower priority than PriorityBestEffort.
    38  const (
    39  	PriorityBackground           Priority = 1
    40  	PriorityBestEffort           Priority = 0
    41  	PriorityExcellentEffort      Priority = 2
    42  	PriorityCriticalApplications Priority = 3
    43  	PriorityVideo                Priority = 4
    44  	PriorityVoice                Priority = 5
    45  	PriorityInternetworkControl  Priority = 6
    46  	PriorityNetworkControl       Priority = 7
    47  )
    48  
    49  // A VLAN is an IEEE 802.1Q Virtual LAN (VLAN) tag.  A VLAN contains
    50  // information regarding traffic priority and a VLAN identifier for
    51  // a given Frame.
    52  type VLAN struct {
    53  	// Priority specifies a IEEE P802.1p priority level.  Priority can be any
    54  	// value from 0 to 7.
    55  	Priority Priority
    56  
    57  	// DropEligible indicates if a Frame is eligible to be dropped in the
    58  	// presence of network congestion.
    59  	DropEligible bool
    60  
    61  	// ID specifies the VLAN ID for a Frame.  ID can be any value from 0 to
    62  	// 4094 (0x000 to 0xffe), allowing up to 4094 VLANs.
    63  	//
    64  	// If ID is 0 (0x000, VLANNone), no VLAN is specified, and the other fields
    65  	// simply indicate a Frame's priority.
    66  	ID uint16
    67  }
    68  
    69  // MarshalBinary allocates a byte slice and marshals a VLAN into binary form.
    70  func (v *VLAN) MarshalBinary() ([]byte, error) {
    71  	b := make([]byte, 2)
    72  	_, err := v.read(b)
    73  	return b, err
    74  }
    75  
    76  // read reads data from a VLAN into b.  read is used to marshal a VLAN into
    77  // binary form, but does not allocate on its own.
    78  func (v *VLAN) read(b []byte) (int, error) {
    79  	// Check for VLAN priority in valid range
    80  	if v.Priority > PriorityNetworkControl {
    81  		return 0, ErrInvalidVLAN
    82  	}
    83  
    84  	// Check for VLAN ID in valid range
    85  	if v.ID >= VLANMax {
    86  		return 0, ErrInvalidVLAN
    87  	}
    88  
    89  	// 3 bits: priority
    90  	ub := uint16(v.Priority) << 13
    91  
    92  	// 1 bit: drop eligible
    93  	var drop uint16
    94  	if v.DropEligible {
    95  		drop = 1
    96  	}
    97  	ub |= drop << 12
    98  
    99  	// 12 bits: VLAN ID
   100  	ub |= v.ID
   101  
   102  	binary.BigEndian.PutUint16(b, ub)
   103  	return 2, nil
   104  }
   105  
   106  // UnmarshalBinary unmarshals a byte slice into a VLAN.
   107  func (v *VLAN) UnmarshalBinary(b []byte) error {
   108  	// VLAN tag is always 2 bytes
   109  	if len(b) != 2 {
   110  		return io.ErrUnexpectedEOF
   111  	}
   112  
   113  	//  3 bits: priority
   114  	//  1 bit : drop eligible
   115  	// 12 bits: VLAN ID
   116  	ub := binary.BigEndian.Uint16(b[0:2])
   117  	v.Priority = Priority(uint8(ub >> 13))
   118  	v.DropEligible = ub&0x1000 != 0
   119  	v.ID = ub & 0x0fff
   120  
   121  	// Check for VLAN ID in valid range
   122  	if v.ID >= VLANMax {
   123  		return ErrInvalidVLAN
   124  	}
   125  
   126  	return nil
   127  }
   128  

View as plain text