forked from TrueCloudLab/restic
78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package icmp
|
||
|
|
||
|
import "encoding/binary"
|
||
|
|
||
|
// A MPLSLabel represents a MPLS label stack entry.
|
||
|
type MPLSLabel struct {
|
||
|
Label int // label value
|
||
|
TC int // traffic class; formerly experimental use
|
||
|
S bool // bottom of stack
|
||
|
TTL int // time to live
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
classMPLSLabelStack = 1
|
||
|
typeIncomingMPLSLabelStack = 1
|
||
|
)
|
||
|
|
||
|
// A MPLSLabelStack represents a MPLS label stack.
|
||
|
type MPLSLabelStack struct {
|
||
|
Class int // extension object class number
|
||
|
Type int // extension object sub-type
|
||
|
Labels []MPLSLabel
|
||
|
}
|
||
|
|
||
|
// Len implements the Len method of Extension interface.
|
||
|
func (ls *MPLSLabelStack) Len(proto int) int {
|
||
|
return 4 + (4 * len(ls.Labels))
|
||
|
}
|
||
|
|
||
|
// Marshal implements the Marshal method of Extension interface.
|
||
|
func (ls *MPLSLabelStack) Marshal(proto int) ([]byte, error) {
|
||
|
b := make([]byte, ls.Len(proto))
|
||
|
if err := ls.marshal(proto, b); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return b, nil
|
||
|
}
|
||
|
|
||
|
func (ls *MPLSLabelStack) marshal(proto int, b []byte) error {
|
||
|
l := ls.Len(proto)
|
||
|
binary.BigEndian.PutUint16(b[:2], uint16(l))
|
||
|
b[2], b[3] = classMPLSLabelStack, typeIncomingMPLSLabelStack
|
||
|
off := 4
|
||
|
for _, ll := range ls.Labels {
|
||
|
b[off], b[off+1], b[off+2] = byte(ll.Label>>12), byte(ll.Label>>4&0xff), byte(ll.Label<<4&0xf0)
|
||
|
b[off+2] |= byte(ll.TC << 1 & 0x0e)
|
||
|
if ll.S {
|
||
|
b[off+2] |= 0x1
|
||
|
}
|
||
|
b[off+3] = byte(ll.TTL)
|
||
|
off += 4
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func parseMPLSLabelStack(b []byte) (Extension, error) {
|
||
|
ls := &MPLSLabelStack{
|
||
|
Class: int(b[2]),
|
||
|
Type: int(b[3]),
|
||
|
}
|
||
|
for b = b[4:]; len(b) >= 4; b = b[4:] {
|
||
|
ll := MPLSLabel{
|
||
|
Label: int(b[0])<<12 | int(b[1])<<4 | int(b[2])>>4,
|
||
|
TC: int(b[2]&0x0e) >> 1,
|
||
|
TTL: int(b[3]),
|
||
|
}
|
||
|
if b[2]&0x1 != 0 {
|
||
|
ll.S = true
|
||
|
}
|
||
|
ls.Labels = append(ls.Labels, ll)
|
||
|
}
|
||
|
return ls, nil
|
||
|
}
|