Skip to content
Snippets Groups Projects
Unverified Commit 381feef7 authored by Daniel Czerwonk's avatar Daniel Czerwonk Committed by GitHub
Browse files

Merge pull request #124 from bio-routing/feature/addpathrx

Implement add path RX on packet level
parents 6a9f2671 e18e9db5
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