Skip to content
Snippets Groups Projects
nlri.go 1.64 KiB
Newer Older
Oliver Herms's avatar
Oliver Herms committed
package packet

import (
	"bytes"
	"fmt"
	"math"
	"net"
Oliver Herms's avatar
Oliver Herms committed

	"github.com/taktv6/tflow2/convert"
Oliver Herms's avatar
Oliver Herms committed
)

func decodeNLRIs(buf *bytes.Buffer, length uint16) (*NLRI, error) {
	var ret *NLRI
	var eol *NLRI
	var nlri *NLRI
	var err error
	var consumed uint8
	p := uint16(0)

	for p < length {
		nlri, consumed, err = decodeNLRI(buf)
		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
}

func decodeNLRI(buf *bytes.Buffer) (*NLRI, uint8, error) {
	var addr [4]byte
	nlri := &NLRI{}

	err := decode(buf, []interface{}{&nlri.Pfxlen})
	if err != nil {
		return nil, 0, err
	}

	toCopy := uint8(math.Ceil(float64(nlri.Pfxlen) / float64(OctetLen)))
	for i := uint8(0); i < net.IPv4len%OctetLen; i++ {
		if i < toCopy {
			err := decode(buf, []interface{}{&addr[i]})
			if err != nil {
				return nil, 0, err
			}
		} else {
			addr[i] = 0
		}
	}
Oliver Herms's avatar
Oliver Herms committed
	nlri.IP = fourBytesToUint32(addr)
Oliver Herms's avatar
Oliver Herms committed
	return nlri, toCopy + 1, nil
}

func (n *NLRI) serialize(buf *bytes.Buffer) uint8 {
Oliver Herms's avatar
Oliver Herms committed
	a := convert.Uint32Byte(n.IP)
Oliver Herms's avatar
Oliver Herms committed

	addr := [4]byte{a[0], a[1], a[2], a[3]}
	nBytes := bytesInAddr(n.Pfxlen)

	buf.WriteByte(n.Pfxlen)
	buf.Write(addr[:nBytes])

	return nBytes + 1
}

Oliver Herms's avatar
Oliver Herms committed
func (n *NLRIAddPath) serialize(buf *bytes.Buffer) uint8 {
	a := convert.Uint32Byte(n.IP)

	addr := [4]byte{a[0], a[1], a[2], a[3]}
	nBytes := bytesInAddr(n.Pfxlen)

	buf.Write(convert.Uint32Byte(n.PathIdentifier))
	buf.WriteByte(n.Pfxlen)
	buf.Write(addr[:nBytes])

	return nBytes + 1
}

func bytesInAddr(pfxlen uint8) uint8 {
	return uint8(math.Ceil(float64(pfxlen) / 8))
}