diff --git a/protocols/bgp/packet/decode_options.go b/protocols/bgp/packet/decode_options.go index 9cea580caaccdd2c2176bae4ab5081f281a6f729..fc50c946ed8027f74e6b0ada18eb54387eccd33e 100644 --- a/protocols/bgp/packet/decode_options.go +++ b/protocols/bgp/packet/decode_options.go @@ -1,5 +1,7 @@ package packet +// DecodeOptions represents options for the BGP message decoder type DecodeOptions struct { + AddPath bool Use32BitASN bool } diff --git a/protocols/bgp/packet/decoder.go b/protocols/bgp/packet/decoder.go index a6f226e49150210b4e3b781a30c571d18b191048..736137582bf1d73f5b474297cdaaf3c6cd8ba167 100644 --- a/protocols/bgp/packet/decoder.go +++ b/protocols/bgp/packet/decoder.go @@ -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 } diff --git a/protocols/bgp/packet/mp_reach_nlri.go b/protocols/bgp/packet/mp_reach_nlri.go index 513bf5d40265adcca1e00e4186752139eddcd126..b714dc19b03333930e6b9b60d53093e15f957314 100644 --- a/protocols/bgp/packet/mp_reach_nlri.go +++ b/protocols/bgp/packet/mp_reach_nlri.go @@ -28,11 +28,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions tempBuf.WriteByte(0) // RESERVED for cur := n.NLRI; cur != nil; cur = cur.Next { - if opt.UseAddPath { - n.NLRI.serializeAddPath(tempBuf) - } else { - n.NLRI.serialize(tempBuf) - } + cur.serialize(tempBuf, opt.UseAddPath) } buf.Write(tempBuf.Bytes()) @@ -40,7 +36,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 +76,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 } diff --git a/protocols/bgp/packet/mp_unreach_nlri.go b/protocols/bgp/packet/mp_unreach_nlri.go index f6c365bb220fb4d76165bcbb8fc207a9b77ae3de..ed2c863d1af21b201695dc11b9eebef08c91ed9f 100644 --- a/protocols/bgp/packet/mp_unreach_nlri.go +++ b/protocols/bgp/packet/mp_unreach_nlri.go @@ -4,28 +4,24 @@ import ( "bytes" "fmt" - bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/util/decode" "github.com/taktv6/tflow2/convert" ) // MultiProtocolUnreachNLRI represents network layer withdraw information for one prefix of an IP address family (rfc4760) type MultiProtocolUnreachNLRI struct { - AFI uint16 - SAFI uint8 - Prefixes []bnet.Prefix - PathID uint32 + AFI uint16 + SAFI uint8 + NLRI *NLRI } func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions) uint16 { tempBuf := bytes.NewBuffer(nil) tempBuf.Write(convert.Uint16Byte(n.AFI)) tempBuf.WriteByte(n.SAFI) - for _, pfx := range n.Prefixes { - if opt.UseAddPath { - tempBuf.Write(convert.Uint32Byte(n.PathID)) - } - tempBuf.Write(serializePrefix(pfx)) + + for cur := n.NLRI; cur != nil; cur = cur.Next { + cur.serialize(tempBuf, opt.UseAddPath) } buf.Write(tempBuf.Bytes()) @@ -33,7 +29,7 @@ func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptio return uint16(tempBuf.Len()) } -func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, error) { +func deserializeMultiProtocolUnreachNLRI(b []byte, addPath bool) (MultiProtocolUnreachNLRI, error) { n := MultiProtocolUnreachNLRI{} prefixesLength := len(b) - 3 // 3 <- AFI + SAFI @@ -41,42 +37,27 @@ func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, er return n, fmt.Errorf("Invalid length of MP_UNREACH_NLRI: expected more than 3 bytes but got %d", len(b)) } - prefixes := make([]byte, prefixesLength) + nlris := make([]byte, prefixesLength) fields := []interface{}{ &n.AFI, &n.SAFI, - &prefixes, + &nlris, } err := decode.Decode(bytes.NewBuffer(b), fields) if err != nil { return MultiProtocolUnreachNLRI{}, err } - if len(prefixes) == 0 { + if len(nlris) == 0 { return n, nil } - idx := uint16(0) - for idx < uint16(len(prefixes)) { - pfxLen := prefixes[idx] - numBytes := uint16(BytesInAddr(pfxLen)) - idx++ - - r := uint16(len(prefixes)) - idx - if r < numBytes { - return MultiProtocolUnreachNLRI{}, fmt.Errorf("expected %d bytes for NLRI, only %d remaining", numBytes, r) - } - - start := idx - end := idx + numBytes - pfx, err := deserializePrefix(prefixes[start:end], pfxLen, n.AFI) - if err != nil { - return MultiProtocolUnreachNLRI{}, err - } - n.Prefixes = append(n.Prefixes, pfx) - - idx = idx + numBytes + buf := bytes.NewBuffer(nlris) + nlri, err := decodeNLRIs(buf, uint16(buf.Len()), n.AFI, addPath) + if err != nil { + return MultiProtocolUnreachNLRI{}, err } + n.NLRI = nlri return n, nil } diff --git a/protocols/bgp/packet/mp_unreach_nlri_test.go b/protocols/bgp/packet/mp_unreach_nlri_test.go index 467b19e030dd208f5e1103d81465107f531591ec..a550f3b3a02f5314c5430e000263a061af680385 100644 --- a/protocols/bgp/packet/mp_unreach_nlri_test.go +++ b/protocols/bgp/packet/mp_unreach_nlri_test.go @@ -20,8 +20,8 @@ func TestSerializeMultiProtocolUnreachNLRI(t *testing.T) { nlri: MultiProtocolUnreachNLRI{ AFI: IPv6AFI, SAFI: UnicastSAFI, - Prefixes: []bnet.Prefix{ - bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44), + NLRI: &NLRI{ + Prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44), }, }, expected: []byte{ @@ -35,10 +35,10 @@ func TestSerializeMultiProtocolUnreachNLRI(t *testing.T) { nlri: MultiProtocolUnreachNLRI{ AFI: IPv6AFI, SAFI: UnicastSAFI, - Prefixes: []bnet.Prefix{ - bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44), + NLRI: &NLRI{ + PathIdentifier: 100, + Prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44), }, - PathID: 100, }, expected: []byte{ 0x00, 0x02, // AFI diff --git a/protocols/bgp/packet/nlri.go b/protocols/bgp/packet/nlri.go index 9406c776d2dcadd66f96a4bd71220a6466d2ce31..1f4f7f6e4293771349b60d1e581e697f5fa085d4 100644 --- a/protocols/bgp/packet/nlri.go +++ b/protocols/bgp/packet/nlri.go @@ -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 @@ -71,20 +89,22 @@ func decodeNLRI(buf *bytes.Buffer, afi uint16) (*NLRI, uint8, error) { return nlri, consumed, nil } -func (n *NLRI) serialize(buf *bytes.Buffer) uint8 { - buf.WriteByte(n.Prefix.Pfxlen()) - b := n.Prefix.Addr().Bytes() +func (n *NLRI) serialize(buf *bytes.Buffer, addPath bool) uint8 { + numBytes := uint8(0) - nBytes := BytesInAddr(n.Prefix.Pfxlen()) - buf.Write(b[:nBytes]) + if addPath { + buf.Write(convert.Uint32Byte(n.PathIdentifier)) + numBytes += 4 + } - return nBytes + 1 -} + buf.WriteByte(n.Prefix.Pfxlen()) + numBytes++ -func (n *NLRI) serializeAddPath(buf *bytes.Buffer) uint8 { - buf.Write(convert.Uint32Byte(n.PathIdentifier)) + pfxNumBytes := BytesInAddr(n.Prefix.Pfxlen()) + buf.Write(n.Prefix.Addr().Bytes()[:pfxNumBytes]) + numBytes += pfxNumBytes - return uint8(n.serialize(buf) + 4) + return numBytes } // BytesInAddr gets the amount of bytes needed to encode an NLRI of prefix length pfxlen diff --git a/protocols/bgp/packet/nlri_test.go b/protocols/bgp/packet/nlri_test.go index bd4f6653c5e18b905abdb67b0d4ac176b6677a16..1efb81eaf44e758685923c2e553d3890a92c5592 100644 --- a/protocols/bgp/packet/nlri_test.go +++ b/protocols/bgp/packet/nlri_test.go @@ -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) @@ -169,6 +220,7 @@ func TestNLRISerialize(t *testing.T) { tests := []struct { name string nlri *NLRI + addPath bool expected []byte }{ { @@ -192,51 +244,38 @@ func TestNLRISerialize(t *testing.T) { }, expected: []byte{17, 100, 200, 128}, }, - } - - for _, test := range tests { - buf := bytes.NewBuffer(nil) - test.nlri.serialize(buf) - res := buf.Bytes() - assert.Equal(t, test.expected, res) - } -} - -func TestNLRIAddPathSerialize(t *testing.T) { - tests := []struct { - name string - nlri *NLRI - expected []byte - }{ { - name: "Test #1", + name: "with add-path #1", nlri: &NLRI{ PathIdentifier: 100, Prefix: bnet.NewPfx(bnet.IPv4FromOctets(1, 2, 3, 0), 25), }, + addPath: true, expected: []byte{0, 0, 0, 100, 25, 1, 2, 3, 0}, }, { - name: "Test #2", + name: "with add-path #2", nlri: &NLRI{ PathIdentifier: 100, Prefix: bnet.NewPfx(bnet.IPv4FromOctets(1, 2, 3, 0), 24), }, + addPath: true, expected: []byte{0, 0, 0, 100, 24, 1, 2, 3}, }, { - name: "Test #3", + name: "with add-path #3", nlri: &NLRI{ PathIdentifier: 100, Prefix: bnet.NewPfx(bnet.IPv4FromOctets(100, 200, 128, 0), 17), }, + addPath: true, expected: []byte{0, 0, 0, 100, 17, 100, 200, 128}, }, } for _, test := range tests { buf := bytes.NewBuffer(nil) - test.nlri.serializeAddPath(buf) + test.nlri.serialize(buf, test.addPath) res := buf.Bytes() assert.Equal(t, test.expected, res) } diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go index ae81d961753c15059925ef26711c5cc99234ff23..a09a3e2c81a5e130c4f59fe769f6ed4432db87f1 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -110,11 +110,11 @@ 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: - if err := pa.decodeMultiProtocolUnreachNLRI(buf); err != nil { + if err := pa.decodeMultiProtocolUnreachNLRI(buf, opt.AddPath); err != nil { return nil, consumed, fmt.Errorf("Failed to multi protocol unreachable NLRI: %v", err) } case AS4AggregatorAttr: @@ -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) } @@ -153,7 +153,7 @@ func (pa *PathAttribute) decodeMultiProtocolReachNLRI(buf *bytes.Buffer) error { return nil } -func (pa *PathAttribute) decodeMultiProtocolUnreachNLRI(buf *bytes.Buffer) error { +func (pa *PathAttribute) decodeMultiProtocolUnreachNLRI(buf *bytes.Buffer, addPath bool) error { b := make([]byte, pa.Length) n, err := buf.Read(b) if err != nil { @@ -163,7 +163,7 @@ func (pa *PathAttribute) decodeMultiProtocolUnreachNLRI(buf *bytes.Buffer) error return fmt.Errorf("Unable to read %d bytes from buffer, only got %d bytes", pa.Length, n) } - nlri, err := deserializeMultiProtocolUnreachNLRI(b) + nlri, err := deserializeMultiProtocolUnreachNLRI(b, addPath) if err != nil { return fmt.Errorf("Unable to decode MP_UNREACH_NLRI: %v", err) } diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go index 2ddc92834c5592ab5ac30d5274712a389f543be4..07fff30276f065d4f132b84a84f72f1c8593b43f 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -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 { @@ -1036,8 +1037,8 @@ func TestDecodeMultiProtocolUnreachNLRI(t *testing.T) { Value: MultiProtocolUnreachNLRI{ AFI: IPv6AFI, SAFI: UnicastSAFI, - Prefixes: []bnet.Prefix{ - bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44), + NLRI: &NLRI{ + Prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44), }, }, }, @@ -1072,7 +1073,7 @@ func TestDecodeMultiProtocolUnreachNLRI(t *testing.T) { pa := &PathAttribute{ Length: l, } - err := pa.decodeMultiProtocolUnreachNLRI(bytes.NewBuffer(test.input)) + err := pa.decodeMultiProtocolUnreachNLRI(bytes.NewBuffer(test.input), false) if test.wantFail { if err != nil { diff --git a/protocols/bgp/packet/update.go b/protocols/bgp/packet/update.go index 167439ab06b77d669c5de258a252b5c2105794a6..8d142fdfc08a43480ed7a3789678f99da4a14f4d 100644 --- a/protocols/bgp/packet/update.go +++ b/protocols/bgp/packet/update.go @@ -18,18 +18,11 @@ type BGPUpdate struct { // SerializeUpdate serializes an BGPUpdate to wire format func (b *BGPUpdate) SerializeUpdate(opt *EncodeOptions) ([]byte, error) { budget := MaxLen - MinLen - nlriLen := 0 buf := bytes.NewBuffer(nil) withdrawBuf := bytes.NewBuffer(nil) for withdraw := b.WithdrawnRoutes; withdraw != nil; withdraw = withdraw.Next { - if opt.UseAddPath { - nlriLen = int(withdraw.serializeAddPath(withdrawBuf)) - } else { - nlriLen = int(withdraw.serialize(withdrawBuf)) - } - - budget -= nlriLen + budget -= int(withdraw.serialize(withdrawBuf, opt.UseAddPath)) if budget < 0 { return nil, fmt.Errorf("update too long") } @@ -46,13 +39,7 @@ func (b *BGPUpdate) SerializeUpdate(opt *EncodeOptions) ([]byte, error) { nlriBuf := bytes.NewBuffer(nil) for nlri := b.NLRI; nlri != nil; nlri = nlri.Next { - if opt.UseAddPath { - nlriLen = int(nlri.serializeAddPath(nlriBuf)) - } else { - nlriLen = int(nlri.serialize(nlriBuf)) - } - - budget -= nlriLen + budget -= int(nlri.serialize(nlriBuf, opt.UseAddPath)) if budget < 0 { return nil, fmt.Errorf("update too long") } @@ -92,8 +79,7 @@ func (b *BGPUpdate) SerializeUpdateAddPath(opt *EncodeOptions) ([]byte, error) { withdrawBuf := bytes.NewBuffer(nil) for withdraw := b.WithdrawnRoutes; withdraw != nil; withdraw = withdraw.Next { - nlriLen := int(withdraw.serialize(withdrawBuf)) - budget -= nlriLen + budget -= int(withdraw.serialize(withdrawBuf, opt.UseAddPath)) if budget < 0 { return nil, fmt.Errorf("update too long") } @@ -110,8 +96,7 @@ func (b *BGPUpdate) SerializeUpdateAddPath(opt *EncodeOptions) ([]byte, error) { nlriBuf := bytes.NewBuffer(nil) for nlri := b.NLRI; nlri != nil; nlri = nlri.Next { - nlriLen := int(nlri.serialize(nlriBuf)) - budget -= nlriLen + budget -= int(nlri.serialize(nlriBuf, opt.UseAddPath)) if budget < 0 { return nil, fmt.Errorf("update too long") } diff --git a/protocols/bgp/server/fsm_address_family.go b/protocols/bgp/server/fsm_address_family.go index 04aa26ab9ed70662bd854cbbbea6a3425d9929d7..772a2dbf436cf1256ce965f16f0cb7ac5a2e1647 100644 --- a/protocols/bgp/server/fsm_address_family.go +++ b/protocols/bgp/server/fsm_address_family.go @@ -161,8 +161,8 @@ func (f *fsmAddressFamily) multiProtocolWithdraw(path *route.Path, nlri packet.M return } - for _, pfx := range nlri.Prefixes { - f.adjRIBIn.RemovePath(pfx, path) + for cur := nlri.NLRI; cur != nil; cur = cur.Next { + f.adjRIBIn.RemovePath(cur.Prefix, path) } } diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go index 87e999caca45a87a124ee1f2269db7169d0eae80..17b021a55504af3e6cba17285da7a33ba9d0a360 100644 --- a/protocols/bgp/server/update_sender.go +++ b/protocols/bgp/server/update_sender.go @@ -311,10 +311,12 @@ func (u *UpdateSender) withdrawPrefixMultiProtocol(out io.Writer, pfx bnet.Prefi PathAttributes: &packet.PathAttribute{ TypeCode: packet.MultiProtocolUnreachNLRICode, Value: packet.MultiProtocolUnreachNLRI{ - AFI: u.addressFamily.afi, - SAFI: u.addressFamily.safi, - Prefixes: []bnet.Prefix{pfx}, - PathID: pathID, + AFI: u.addressFamily.afi, + SAFI: u.addressFamily.safi, + NLRI: &packet.NLRI{ + PathIdentifier: pathID, + Prefix: pfx, + }, }, }, }