diff --git a/.gitignore b/.gitignore index bb99a56915e4f0f56746244dbb3affd0ee20712a..c97ea2a6069695630909b3884565f91629e3965e 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,8 @@ # 'go build' binary bio-rd +examples/bgp +examples/bmp # bazel directories /bazel-* diff --git a/protocols/bgp/packet/decoder.go b/protocols/bgp/packet/decoder.go index 2abfeec67a6761723119a4b8d6e2719f99649239..de86c370a6c428d06e656e5c54872f5e1e33c752 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)) + msg.WithdrawnRoutes, err = decodeNLRIs(buf, uint16(msg.WithdrawnRoutesLen), IPv4AFI) 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) + msg.NLRI, err = decodeNLRIs(buf, nlriLen, IPv4AFI) if err != nil { return msg, err } diff --git a/protocols/bgp/packet/decoder_test.go b/protocols/bgp/packet/decoder_test.go index 3db3b4888742093b9d29e971e7a44e1fb2fca0c5..dfa7ce6469299ed0df2127505162045b5d79cf39 100644 --- a/protocols/bgp/packet/decoder_test.go +++ b/protocols/bgp/packet/decoder_test.go @@ -209,11 +209,9 @@ func TestDecode(t *testing.T) { Body: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, }, @@ -429,11 +427,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, }, @@ -455,11 +451,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, TotalPathAttrLen: 5, @@ -497,11 +491,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, TotalPathAttrLen: 14, @@ -600,11 +592,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, TotalPathAttrLen: 20, @@ -675,11 +665,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, TotalPathAttrLen: 27, @@ -766,11 +754,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, TotalPathAttrLen: 34, @@ -870,11 +856,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, TotalPathAttrLen: 41, @@ -986,11 +970,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, TotalPathAttrLen: 44, @@ -1118,11 +1100,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, TotalPathAttrLen: 53, @@ -1207,8 +1187,7 @@ func TestDecodeUpdateMsg(t *testing.T) { }, }, NLRI: &NLRI{ - Pfxlen: 8, - IP: bnet.IPv4FromOctets(11, 0, 0, 0), + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(11, 0, 0, 0), 8), }, }, }, @@ -1290,11 +1269,9 @@ func TestDecodeUpdateMsg(t *testing.T) { expected: &BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, TotalPathAttrLen: 16, diff --git a/protocols/bgp/packet/mp_reach_nlri.go b/protocols/bgp/packet/mp_reach_nlri.go index b08edca7a83d3d794b6411df58b8f8f85866a3f5..513bf5d40265adcca1e00e4186752139eddcd126 100644 --- a/protocols/bgp/packet/mp_reach_nlri.go +++ b/protocols/bgp/packet/mp_reach_nlri.go @@ -4,19 +4,17 @@ import ( "bytes" "fmt" - "github.com/taktv6/tflow2/convert" - bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/util/decode" + "github.com/taktv6/tflow2/convert" ) -// MultiProtocolReachNLRI represents network layer reachability information for one prefix of an IP address family (rfc4760) +// MultiProtocolReachNLRI represents network layer reachability information for an IP address family (rfc4760) type MultiProtocolReachNLRI struct { - AFI uint16 - SAFI uint8 - NextHop bnet.IP - Prefixes []bnet.Prefix - PathID uint32 + AFI uint16 + SAFI uint8 + NextHop bnet.IP + NLRI *NLRI } func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions) uint16 { @@ -28,11 +26,13 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions tempBuf.WriteByte(uint8(len(nextHop))) tempBuf.Write(nextHop) tempBuf.WriteByte(0) // RESERVED - for _, pfx := range n.Prefixes { + + for cur := n.NLRI; cur != nil; cur = cur.Next { if opt.UseAddPath { - tempBuf.Write(convert.Uint32Byte(n.PathID)) + n.NLRI.serializeAddPath(tempBuf) + } else { + n.NLRI.serialize(tempBuf) } - tempBuf.Write(serializePrefix(pfx)) } buf.Write(tempBuf.Bytes()) @@ -73,34 +73,18 @@ func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error) } budget -= int(nextHopLength) - n.Prefixes = make([]bnet.Prefix, 0) if budget == 0 { return n, nil } variable = variable[1+nextHopLength:] // 1 <- RESERVED field - idx := uint16(0) - for idx < uint16(len(variable)) { - pfxLen := variable[idx] - numBytes := uint16(BytesInAddr(pfxLen)) - idx++ - - r := uint16(len(variable)) - idx - if r < numBytes { - return MultiProtocolReachNLRI{}, fmt.Errorf("expected %d bytes for NLRI, only %d remaining", numBytes, r) - } - - start := idx - end := idx + numBytes - pfx, err := deserializePrefix(variable[start:end], pfxLen, n.AFI) - if err != nil { - return MultiProtocolReachNLRI{}, err - } - n.Prefixes = append(n.Prefixes, pfx) - - idx = idx + numBytes + buf := bytes.NewBuffer(variable) + nlri, err := decodeNLRIs(buf, uint16(buf.Len()), n.AFI) + if err != nil { + return MultiProtocolReachNLRI{}, err } + n.NLRI = nlri return n, nil } diff --git a/protocols/bgp/packet/mp_reach_nlri_test.go b/protocols/bgp/packet/mp_reach_nlri_test.go index cb6e5b544333d76f3244c8ef6895acb40783f149..a4878cf7d161c03fa0947d238f2203707e6c369d 100644 --- a/protocols/bgp/packet/mp_reach_nlri_test.go +++ b/protocols/bgp/packet/mp_reach_nlri_test.go @@ -21,8 +21,8 @@ func TestSerializeMultiProtocolReachNLRI(t *testing.T) { AFI: IPv6AFI, SAFI: UnicastSAFI, NextHop: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0x2), - Prefixes: []bnet.Prefix{ - bnet.NewPfx(bnet.IPv6FromBlocks(0x2600, 0x6, 0xff05, 0, 0, 0, 0, 0), 48), + NLRI: &NLRI{ + Prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2600, 0x6, 0xff05, 0, 0, 0, 0, 0), 48), }, }, expected: []byte{ @@ -39,10 +39,10 @@ func TestSerializeMultiProtocolReachNLRI(t *testing.T) { AFI: IPv6AFI, SAFI: UnicastSAFI, NextHop: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0x2), - Prefixes: []bnet.Prefix{ - bnet.NewPfx(bnet.IPv6FromBlocks(0x2600, 0x6, 0xff05, 0, 0, 0, 0, 0), 48), + NLRI: &NLRI{ + Prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2600, 0x6, 0xff05, 0, 0, 0, 0, 0), 48), + PathIdentifier: 100, }, - PathID: 100, }, expected: []byte{ 0x00, 0x02, // AFI diff --git a/protocols/bgp/packet/nlri.go b/protocols/bgp/packet/nlri.go index bc404cc347b2672c2da711d5dfae2d0174f6dc98..9406c776d2dcadd66f96a4bd71220a6466d2ce31 100644 --- a/protocols/bgp/packet/nlri.go +++ b/protocols/bgp/packet/nlri.go @@ -4,21 +4,18 @@ import ( "bytes" "fmt" "math" - "net" bnet "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/util/decode" "github.com/taktv6/tflow2/convert" ) type NLRI struct { PathIdentifier uint32 - IP bnet.IP - Pfxlen uint8 + Prefix bnet.Prefix Next *NLRI } -func decodeNLRIs(buf *bytes.Buffer, length uint16) (*NLRI, error) { +func decodeNLRIs(buf *bytes.Buffer, length uint16, afi uint16) (*NLRI, error) { var ret *NLRI var eol *NLRI var nlri *NLRI @@ -27,7 +24,7 @@ func decodeNLRIs(buf *bytes.Buffer, length uint16) (*NLRI, error) { p := uint16(0) for p < length { - nlri, consumed, err = decodeNLRI(buf) + nlri, consumed, err = decodeNLRI(buf, afi) if err != nil { return nil, fmt.Errorf("Unable to decode NLRI: %v", err) } @@ -46,39 +43,39 @@ func decodeNLRIs(buf *bytes.Buffer, length uint16) (*NLRI, error) { return ret, nil } -func decodeNLRI(buf *bytes.Buffer) (*NLRI, uint8, error) { - addr := make([]byte, 4) +func decodeNLRI(buf *bytes.Buffer, afi uint16) (*NLRI, uint8, error) { nlri := &NLRI{} - err := decode.Decode(buf, []interface{}{&nlri.Pfxlen}) + consumed := uint8(0) + pfxLen, err := buf.ReadByte() if err != nil { - return nil, 0, err + return nil, consumed, err } + consumed++ - toCopy := uint8(math.Ceil(float64(nlri.Pfxlen) / float64(OctetLen))) - for i := uint8(0); i < net.IPv4len%OctetLen; i++ { - if i < toCopy { - err := decode.Decode(buf, []interface{}{&addr[i]}) - if err != nil { - return nil, 0, err - } - } else { - addr[i] = 0 - } + 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) } - nlri.IP, err = bnet.IPFromBytes(addr) + + pfx, err := deserializePrefix(bytes, pfxLen, afi) if err != nil { - return nil, 0, err + return nil, consumed, err } + nlri.Prefix = pfx - return nlri, toCopy + 1, nil + return nlri, consumed, nil } func (n *NLRI) serialize(buf *bytes.Buffer) uint8 { - buf.WriteByte(n.Pfxlen) - b := n.IP.Bytes() + buf.WriteByte(n.Prefix.Pfxlen()) + b := n.Prefix.Addr().Bytes() - nBytes := BytesInAddr(n.Pfxlen) + nBytes := BytesInAddr(n.Prefix.Pfxlen()) buf.Write(b[:nBytes]) return nBytes + 1 diff --git a/protocols/bgp/packet/nlri_test.go b/protocols/bgp/packet/nlri_test.go index b109fe052de7526307b499422b8abd7a6378dcb0..bd4f6653c5e18b905abdb67b0d4ac176b6677a16 100644 --- a/protocols/bgp/packet/nlri_test.go +++ b/protocols/bgp/packet/nlri_test.go @@ -24,14 +24,11 @@ func TestDecodeNLRIs(t *testing.T) { }, wantFail: false, expected: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 24, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 24), Next: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(172, 16, 0, 0), - Pfxlen: 17, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(172, 16, 0, 0), 17), }, }, }, @@ -49,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))) + res, err := decodeNLRIs(buf, uint16(len(test.input)), IPv4AFI) if test.wantFail && err == nil { t.Errorf("Expected error did not happen for test %q", test.name) @@ -77,8 +74,7 @@ func TestDecodeNLRI(t *testing.T) { }, wantFail: false, expected: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 24, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 24), }, }, { @@ -88,8 +84,7 @@ func TestDecodeNLRI(t *testing.T) { }, wantFail: false, expected: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 128), - Pfxlen: 25, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 128), 25), }, }, { @@ -115,7 +110,7 @@ func TestDecodeNLRI(t *testing.T) { for _, test := range tests { buf := bytes.NewBuffer(test.input) - res, _, err := decodeNLRI(buf) + res, _, err := decodeNLRI(buf, IPv4AFI) if test.wantFail && err == nil { t.Errorf("Expected error did not happen for test %q", test.name) @@ -179,24 +174,21 @@ func TestNLRISerialize(t *testing.T) { { name: "Test #1", nlri: &NLRI{ - IP: bnet.IPv4FromOctets(1, 2, 3, 0), - Pfxlen: 25, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(1, 2, 3, 0), 25), }, expected: []byte{25, 1, 2, 3, 0}, }, { name: "Test #2", nlri: &NLRI{ - IP: bnet.IPv4FromOctets(1, 2, 3, 0), - Pfxlen: 24, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(1, 2, 3, 0), 24), }, expected: []byte{24, 1, 2, 3}, }, { name: "Test #3", nlri: &NLRI{ - IP: bnet.IPv4FromOctets(100, 200, 128, 0), - Pfxlen: 17, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(100, 200, 128, 0), 17), }, expected: []byte{17, 100, 200, 128}, }, @@ -220,8 +212,7 @@ func TestNLRIAddPathSerialize(t *testing.T) { name: "Test #1", nlri: &NLRI{ PathIdentifier: 100, - IP: bnet.IPv4FromOctets(1, 2, 3, 0), - Pfxlen: 25, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(1, 2, 3, 0), 25), }, expected: []byte{0, 0, 0, 100, 25, 1, 2, 3, 0}, }, @@ -229,8 +220,7 @@ func TestNLRIAddPathSerialize(t *testing.T) { name: "Test #2", nlri: &NLRI{ PathIdentifier: 100, - IP: bnet.IPv4FromOctets(1, 2, 3, 0), - Pfxlen: 24, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(1, 2, 3, 0), 24), }, expected: []byte{0, 0, 0, 100, 24, 1, 2, 3}, }, @@ -238,8 +228,7 @@ func TestNLRIAddPathSerialize(t *testing.T) { name: "Test #3", nlri: &NLRI{ PathIdentifier: 100, - IP: bnet.IPv4FromOctets(100, 200, 128, 0), - Pfxlen: 17, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(100, 200, 128, 0), 17), }, expected: []byte{0, 0, 0, 100, 17, 100, 200, 128}, }, diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go index 1b7cce5be4170738d58ef90574b3ed7d573f4b43..2ddc92834c5592ab5ac30d5274712a389f543be4 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -928,8 +928,8 @@ func TestDecodeMultiProtocolReachNLRI(t *testing.T) { AFI: IPv6AFI, SAFI: UnicastSAFI, NextHop: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0x2), - Prefixes: []bnet.Prefix{ - bnet.NewPfx(bnet.IPv6FromBlocks(0x2600, 0x6, 0xff05, 0, 0, 0, 0, 0), 48), + NLRI: &NLRI{ + Prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2600, 0x6, 0xff05, 0, 0, 0, 0, 0), 48), }, }, }, @@ -961,10 +961,9 @@ func TestDecodeMultiProtocolReachNLRI(t *testing.T) { expected: &PathAttribute{ Length: 21, Value: MultiProtocolReachNLRI{ - AFI: IPv6AFI, - SAFI: UnicastSAFI, - NextHop: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0x2), - Prefixes: []bnet.Prefix{}, + AFI: IPv6AFI, + SAFI: UnicastSAFI, + NextHop: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0x2), }, }, }, @@ -1869,8 +1868,7 @@ func TestSerialize(t *testing.T) { name: "Withdraw only", msg: &BGPUpdate{ WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(100, 110, 120, 0), - Pfxlen: 24, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(100, 110, 120, 0), 24), }, }, expected: []byte{ @@ -1886,8 +1884,7 @@ func TestSerialize(t *testing.T) { name: "NLRI only", msg: &BGPUpdate{ NLRI: &NLRI{ - IP: bnet.IPv4FromOctets(100, 110, 128, 0), - Pfxlen: 17, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(100, 110, 128, 0), 17), }, }, expected: []byte{ @@ -1925,11 +1922,9 @@ func TestSerialize(t *testing.T) { name: "Full test", msg: &BGPUpdate{ WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, PathAttributes: &PathAttribute{ @@ -1972,11 +1967,9 @@ func TestSerialize(t *testing.T) { }, }, NLRI: &NLRI{ - IP: bnet.IPv4FromOctets(8, 8, 8, 0), - Pfxlen: 24, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(8, 8, 8, 0), 24), Next: &NLRI{ - IP: bnet.IPv4FromOctets(185, 65, 240, 0), - Pfxlen: 22, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(185, 65, 240, 0), 22), }, }, }, @@ -2042,8 +2035,7 @@ func TestSerialize(t *testing.T) { name: "Reflected NLRI", msg: &BGPUpdate{ NLRI: &NLRI{ - IP: bnet.IPv4FromOctets(100, 110, 128, 0), - Pfxlen: 17, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(100, 110, 128, 0), 17), }, PathAttributes: &PathAttribute{ TypeCode: OriginatorIDAttr, @@ -2112,8 +2104,7 @@ func TestSerializeAddPath(t *testing.T) { msg: &BGPUpdate{ WithdrawnRoutes: &NLRI{ PathIdentifier: 257, - IP: bnet.IPv4FromOctets(100, 110, 120, 0), - Pfxlen: 24, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(100, 110, 120, 0), 24), }, }, expected: []byte{ @@ -2131,8 +2122,7 @@ func TestSerializeAddPath(t *testing.T) { msg: &BGPUpdate{ NLRI: &NLRI{ PathIdentifier: 257, - IP: bnet.IPv4FromOctets(100, 110, 128, 0), - Pfxlen: 17, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(100, 110, 128, 0), 17), }, }, expected: []byte{ @@ -2171,11 +2161,9 @@ func TestSerializeAddPath(t *testing.T) { name: "Full test", msg: &BGPUpdate{ WithdrawnRoutes: &NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, PathAttributes: &PathAttribute{ @@ -2218,11 +2206,9 @@ func TestSerializeAddPath(t *testing.T) { }, }, NLRI: &NLRI{ - IP: bnet.IPv4FromOctets(8, 8, 8, 0), - Pfxlen: 24, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(8, 8, 8, 0), 24), Next: &NLRI{ - IP: bnet.IPv4FromOctets(185, 65, 240, 0), - Pfxlen: 22, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(185, 65, 240, 0), 22), }, }, }, diff --git a/protocols/bgp/server/fsm_address_family.go b/protocols/bgp/server/fsm_address_family.go index 8eac38966eab6533ed42a3a44207c1cfcbdb0f42..8d3e042ed5b600d0a4a77932a4be2141ea41b242 100644 --- a/protocols/bgp/server/fsm_address_family.go +++ b/protocols/bgp/server/fsm_address_family.go @@ -107,19 +107,16 @@ func (f *fsmAddressFamily) processUpdate(u *packet.BGPUpdate) { func (f *fsmAddressFamily) withdraws(u *packet.BGPUpdate) { for r := u.WithdrawnRoutes; r != nil; r = r.Next { - pfx := bnet.NewPfx(r.IP, r.Pfxlen) - f.adjRIBIn.RemovePath(pfx, nil) + f.adjRIBIn.RemovePath(r.Prefix, nil) } } func (f *fsmAddressFamily) updates(u *packet.BGPUpdate) { for r := u.NLRI; r != nil; r = r.Next { - pfx := bnet.NewPfx(r.IP, r.Pfxlen) - path := f.newRoutePath() f.processAttributes(u.PathAttributes, path) - f.adjRIBIn.AddPath(pfx, path) + f.adjRIBIn.AddPath(r.Prefix, path) } } @@ -154,8 +151,12 @@ func (f *fsmAddressFamily) multiProtocolUpdate(path *route.Path, nlri packet.Mul path.BGPPath.NextHop = nlri.NextHop - for _, pfx := range nlri.Prefixes { - f.adjRIBIn.AddPath(pfx, path) + if nlri.NLRI == nil { + return + } + + for n := nlri.NLRI; n != nil; n = n.Next { + f.adjRIBIn.AddPath(n.Prefix, path) } } diff --git a/protocols/bgp/server/update_helper_test.go b/protocols/bgp/server/update_helper_test.go index a7f45b5b39ee7279c44168395303ac6480cceff0..fee9d895b8d491599eeaf5f4e9ba560eee5dc848 100644 --- a/protocols/bgp/server/update_helper_test.go +++ b/protocols/bgp/server/update_helper_test.go @@ -6,9 +6,8 @@ import ( "io" "testing" - "github.com/bio-routing/bio-rd/protocols/bgp/packet" - bnet "github.com/bio-routing/bio-rd/net" + "github.com/bio-routing/bio-rd/protocols/bgp/packet" "github.com/stretchr/testify/assert" ) @@ -49,11 +48,9 @@ func TestSerializeAndSendUpdate(t *testing.T) { testUpdate: &packet.BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &packet.NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &packet.NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, }, @@ -79,11 +76,9 @@ func TestSerializeAndSendUpdate(t *testing.T) { testUpdate: &packet.BGPUpdate{ WithdrawnRoutesLen: 5, WithdrawnRoutes: &packet.NLRI{ - IP: bnet.IPv4FromOctets(10, 0, 0, 0), - Pfxlen: 8, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8), Next: &packet.NLRI{ - IP: bnet.IPv4FromOctets(192, 168, 0, 0), - Pfxlen: 16, + Prefix: bnet.NewPfx(bnet.IPv4FromOctets(192, 168, 0, 0), 16), }, }, }, diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go index ca7a11d5f9738d07c82c55591830652ab4ec6b11..87e999caca45a87a124ee1f2269db7169d0eae80 100644 --- a/protocols/bgp/server/update_sender.go +++ b/protocols/bgp/server/update_sender.go @@ -7,11 +7,10 @@ import ( "sync" "time" + bnet "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/protocols/bgp/packet" "github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/routingtable" - - bnet "github.com/bio-routing/bio-rd/net" log "github.com/sirupsen/logrus" ) @@ -191,8 +190,7 @@ func (u *UpdateSender) bgpUpdate(pfxs []bnet.Prefix, pa *packet.PathAttribute, p for _, pfx := range pfxs { nlri = &packet.NLRI{ PathIdentifier: pathID, - IP: pfx.Addr(), - Pfxlen: pfx.Pfxlen(), + Prefix: pfx, Next: update.NLRI, } update.NLRI = nlri @@ -207,11 +205,10 @@ func (u *UpdateSender) bgpUpdateMultiProtocol(pfxs []bnet.Prefix, pa *packet.Pat attrs := &packet.PathAttribute{ TypeCode: packet.MultiProtocolReachNLRICode, Value: packet.MultiProtocolReachNLRI{ - AFI: u.addressFamily.afi, - SAFI: u.addressFamily.safi, - NextHop: nextHop, - Prefixes: pfxs, - PathID: pathID, + AFI: u.addressFamily.afi, + SAFI: u.addressFamily.safi, + NextHop: nextHop, + NLRI: u.nlriForPrefixes(pfxs, pathID), }, } attrs.Next = pa @@ -221,6 +218,27 @@ func (u *UpdateSender) bgpUpdateMultiProtocol(pfxs []bnet.Prefix, pa *packet.Pat } } +func (u *UpdateSender) nlriForPrefixes(pfxs []bnet.Prefix, pathID uint32) *packet.NLRI { + var prev, res *packet.NLRI + for _, pfx := range pfxs { + cur := &packet.NLRI{ + Prefix: pfx, + PathIdentifier: pathID, + } + + if res == nil { + res = cur + prev = cur + continue + } + + prev.Next = cur + prev = cur + } + + return res +} + func (u *UpdateSender) copyAttributesWithoutNextHop(pa *packet.PathAttribute) (attrs *packet.PathAttribute, nextHop bnet.IP) { var curCopy, lastCopy *packet.PathAttribute for cur := pa; cur != nil; cur = cur.Next { @@ -276,8 +294,7 @@ func (u *UpdateSender) withdrawPrefixIPv4(out io.Writer, pfx bnet.Prefix, p *rou update := &packet.BGPUpdate{ WithdrawnRoutes: &packet.NLRI{ PathIdentifier: p.BGPPath.PathIdentifier, - IP: pfx.Addr(), - Pfxlen: pfx.Pfxlen(), + Prefix: pfx, }, }