Skip to content
Snippets Groups Projects
nlri.go 1.78 KiB
Newer Older
  • Learn to ignore specific revisions
  • Oliver Herms's avatar
    Oliver Herms committed
    package packet
    
    import (
    	"bytes"
    	"fmt"
    	"math"
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    
    	bnet "github.com/bio-routing/bio-rd/net"
    
    Oliver Herms's avatar
    Oliver Herms committed
    	"github.com/taktv6/tflow2/convert"
    
    Oliver Herms's avatar
    Oliver Herms committed
    )
    
    
    type NLRI struct {
    	PathIdentifier uint32
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	Prefix         bnet.Prefix
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16) (*NLRI, error) {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	var ret *NLRI
    	var eol *NLRI
    	var nlri *NLRI
    	var err error
    	var consumed uint8
    	p := uint16(0)
    
    	for p < length {
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    		nlri, consumed, err = decodeNLRI(buf, afi)
    
    Oliver Herms's avatar
    Oliver Herms committed
    		if err != nil {
    			return nil, fmt.Errorf("Unable to decode NLRI: %v", err)
    		}
    		p += uint16(consumed)
    
    		if ret == nil {
    			ret = nlri
    			eol = nlri
    			continue
    		}
    
    		eol.Next = nlri
    		eol = nlri
    	}
    
    	return ret, nil
    }
    
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    func decodeNLRI(buf *bytes.Buffer, afi uint16) (*NLRI, uint8, error) {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	nlri := &NLRI{}
    
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	consumed := uint8(0)
    	pfxLen, err := buf.ReadByte()
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if err != nil {
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    		return nil, consumed, err
    
    Oliver Herms's avatar
    Oliver Herms committed
    	}
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	consumed++
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	numBytes := uint8(BytesInAddr(pfxLen))
    	bytes := make([]byte, numBytes)
    
    	r, err := buf.Read(bytes)
    	consumed += uint8(r)
    	if r < int(numBytes) {
    		return nil, consumed, fmt.Errorf("expected %d bytes for NLRI, only %d remaining", numBytes, r)
    
    Oliver Herms's avatar
    Oliver Herms committed
    	}
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    
    	pfx, err := deserializePrefix(bytes, pfxLen, afi)
    
    	if err != nil {
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    		return nil, consumed, err
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	nlri.Prefix = pfx
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	return nlri, consumed, nil
    
    Oliver Herms's avatar
    Oliver Herms committed
    }
    
    
    func (n *NLRI) serialize(buf *bytes.Buffer) uint8 {
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	buf.WriteByte(n.Prefix.Pfxlen())
    	b := n.Prefix.Addr().Bytes()
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	nBytes := BytesInAddr(n.Prefix.Pfxlen())
    
    	buf.Write(b[:nBytes])
    
    func (n *NLRI) serializeAddPath(buf *bytes.Buffer) uint8 {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	buf.Write(convert.Uint32Byte(n.PathIdentifier))
    
    
    	return uint8(n.serialize(buf) + 4)
    
    // BytesInAddr gets the amount of bytes needed to encode an NLRI of prefix length pfxlen
    func BytesInAddr(pfxlen uint8) uint8 {
    
    	return uint8(math.Ceil(float64(pfxlen) / 8))
    }