Skip to content
Snippets Groups Projects
Commit e18e9db5 authored by Oliver Herms's avatar Oliver Herms
Browse files

Implement add path RX on packet level

parent 6a9f2671
No related branches found
No related tags found
No related merge requests found
package packet
// DecodeOptions represents options for the BGP message decoder
type DecodeOptions struct {
AddPath bool
Use32BitASN bool
}
......@@ -49,7 +49,7 @@ func decodeUpdateMsg(buf *bytes.Buffer, l uint16, opt *DecodeOptions) (*BGPUpdat
return msg, err
}
msg.WithdrawnRoutes, err = decodeNLRIs(buf, uint16(msg.WithdrawnRoutesLen), IPv4AFI)
msg.WithdrawnRoutes, err = decodeNLRIs(buf, uint16(msg.WithdrawnRoutesLen), IPv4AFI, opt.AddPath)
if err != nil {
return msg, err
}
......@@ -66,7 +66,7 @@ func decodeUpdateMsg(buf *bytes.Buffer, l uint16, opt *DecodeOptions) (*BGPUpdat
nlriLen := uint16(l) - 4 - uint16(msg.TotalPathAttrLen) - uint16(msg.WithdrawnRoutesLen)
if nlriLen > 0 {
msg.NLRI, err = decodeNLRIs(buf, nlriLen, IPv4AFI)
msg.NLRI, err = decodeNLRIs(buf, nlriLen, IPv4AFI, opt.AddPath)
if err != nil {
return msg, err
}
......
......@@ -40,7 +40,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions
return uint16(tempBuf.Len())
}
func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error) {
func deserializeMultiProtocolReachNLRI(b []byte, addPath bool) (MultiProtocolReachNLRI, error) {
n := MultiProtocolReachNLRI{}
nextHopLength := uint8(0)
......@@ -80,7 +80,7 @@ func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error)
variable = variable[1+nextHopLength:] // 1 <- RESERVED field
buf := bytes.NewBuffer(variable)
nlri, err := decodeNLRIs(buf, uint16(buf.Len()), n.AFI)
nlri, err := decodeNLRIs(buf, uint16(buf.Len()), n.AFI, addPath)
if err != nil {
return MultiProtocolReachNLRI{}, err
}
......
......@@ -6,16 +6,22 @@ import (
"math"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/util/decode"
"github.com/taktv6/tflow2/convert"
)
const (
pathIdentifierLen = 4
)
// NLRI represents a Network Layer Reachability Information
type NLRI struct {
PathIdentifier uint32
Prefix bnet.Prefix
Next *NLRI
}
func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16) (*NLRI, error) {
func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16, addPath bool) (*NLRI, error) {
var ret *NLRI
var eol *NLRI
var nlri *NLRI
......@@ -24,7 +30,7 @@ func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16) (*NLRI, error) {
p := uint16(0)
for p < length {
nlri, consumed, err = decodeNLRI(buf, afi)
nlri, consumed, err = decodeNLRI(buf, afi, addPath)
if err != nil {
return nil, fmt.Errorf("Unable to decode NLRI: %v", err)
}
......@@ -43,10 +49,22 @@ func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16) (*NLRI, error) {
return ret, nil
}
func decodeNLRI(buf *bytes.Buffer, afi uint16) (*NLRI, uint8, error) {
func decodeNLRI(buf *bytes.Buffer, afi uint16, addPath bool) (*NLRI, uint8, error) {
nlri := &NLRI{}
consumed := uint8(0)
if addPath {
err := decode.Decode(buf, []interface{}{
&nlri.PathIdentifier,
})
if err != nil {
return nil, consumed, fmt.Errorf("Unable to decode path identifier: %v", err)
}
consumed += pathIdentifierLen
}
pfxLen, err := buf.ReadByte()
if err != nil {
return nil, consumed, err
......
......@@ -46,7 +46,7 @@ func TestDecodeNLRIs(t *testing.T) {
for _, test := range tests {
buf := bytes.NewBuffer(test.input)
res, err := decodeNLRIs(buf, uint16(len(test.input)), IPv4AFI)
res, err := decodeNLRIs(buf, uint16(len(test.input)), IPv4AFI, false)
if test.wantFail && err == nil {
t.Errorf("Expected error did not happen for test %q", test.name)
......@@ -64,6 +64,7 @@ func TestDecodeNLRI(t *testing.T) {
tests := []struct {
name string
input []byte
addPath bool
wantFail bool
expected *NLRI
}{
......@@ -101,6 +102,56 @@ func TestDecodeNLRI(t *testing.T) {
},
wantFail: true,
},
{
name: "Valid NRLI #1 add path",
input: []byte{
0, 0, 0, 10, 24, 192, 168, 0,
},
addPath: true,
wantFail: false,
expected: &NLRI{
PathIdentifier: 10,
Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 24),
},
},
{
name: "Valid NRLI #2 add path",
input: []byte{
0, 0, 1, 0, 25, 192, 168, 0, 128,
},
addPath: true,
wantFail: false,
expected: &NLRI{
PathIdentifier: 256,
Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 128), 25),
},
},
{
name: "Incomplete path Identifier",
input: []byte{
0, 0, 0,
},
addPath: true,
wantFail: true,
},
{
name: "Incomplete NLRI #1 add path",
input: []byte{
0, 0, 1, 0, 25, 192, 168, 0,
},
addPath: true,
wantFail: true,
},
{
name: "Incomplete NLRI #2 add path",
input: []byte{
0, 0, 1, 0, 25,
},
addPath: true,
wantFail: true,
},
{
name: "Empty input",
input: []byte{},
......@@ -110,7 +161,7 @@ func TestDecodeNLRI(t *testing.T) {
for _, test := range tests {
buf := bytes.NewBuffer(test.input)
res, _, err := decodeNLRI(buf, IPv4AFI)
res, _, err := decodeNLRI(buf, IPv4AFI, test.addPath)
if test.wantFail && err == nil {
t.Errorf("Expected error did not happen for test %q", test.name)
......
......@@ -110,7 +110,7 @@ func decodePathAttr(buf *bytes.Buffer, opt *DecodeOptions) (pa *PathAttribute, c
return nil, consumed, fmt.Errorf("Failed to decode OriginatorID: %v", err)
}
case MultiProtocolReachNLRICode:
if err := pa.decodeMultiProtocolReachNLRI(buf); err != nil {
if err := pa.decodeMultiProtocolReachNLRI(buf, opt.AddPath); err != nil {
return nil, consumed, fmt.Errorf("Failed to multi protocol reachable NLRI: %v", err)
}
case MultiProtocolUnreachNLRICode:
......@@ -134,7 +134,7 @@ func decodePathAttr(buf *bytes.Buffer, opt *DecodeOptions) (pa *PathAttribute, c
return pa, consumed + pa.Length, nil
}
func (pa *PathAttribute) decodeMultiProtocolReachNLRI(buf *bytes.Buffer) error {
func (pa *PathAttribute) decodeMultiProtocolReachNLRI(buf *bytes.Buffer, addPath bool) error {
b := make([]byte, pa.Length)
n, err := buf.Read(b)
if err != nil {
......@@ -144,7 +144,7 @@ func (pa *PathAttribute) decodeMultiProtocolReachNLRI(buf *bytes.Buffer) error {
return fmt.Errorf("Unable to read %d bytes from buffer, only got %d bytes", pa.Length, n)
}
nlri, err := deserializeMultiProtocolReachNLRI(b)
nlri, err := deserializeMultiProtocolReachNLRI(b, addPath)
if err != nil {
return fmt.Errorf("Unable to decode MP_REACH_NLRI: %v", err)
}
......
......@@ -903,6 +903,7 @@ func TestDecodeMultiProtocolReachNLRI(t *testing.T) {
tests := []struct {
name string
input []byte
addPath bool
wantFail bool
explicitLength uint16
expected *PathAttribute
......@@ -992,7 +993,7 @@ func TestDecodeMultiProtocolReachNLRI(t *testing.T) {
pa := &PathAttribute{
Length: l,
}
err := pa.decodeMultiProtocolReachNLRI(bytes.NewBuffer(test.input))
err := pa.decodeMultiProtocolReachNLRI(bytes.NewBuffer(test.input), test.addPath)
if test.wantFail {
if err != nil {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment