Skip to content
Snippets Groups Projects
Commit de6edf54 authored by Daniel Czerwonk's avatar Daniel Czerwonk
Browse files

added add-path for ipv6

parent 86f17a1f
No related branches found
No related tags found
No related merge requests found
......@@ -7,6 +7,7 @@ import (
"github.com/taktv6/tflow2/convert"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/types"
)
// MultiProtocolReachNLRI represents network layer reachability information for one prefix of an IP address family (rfc4760)
......@@ -15,9 +16,10 @@ type MultiProtocolReachNLRI struct {
SAFI uint8
NextHop bnet.IP
Prefixes []bnet.Prefix
PathID uint32
}
func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint16 {
func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *types.Options) uint16 {
nextHop := n.NextHop.Bytes()
tempBuf := bytes.NewBuffer(nil)
......@@ -27,6 +29,9 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint16 {
tempBuf.Write(nextHop)
tempBuf.WriteByte(0) // RESERVED
for _, pfx := range n.Prefixes {
if opt.AddPathRX {
tempBuf.Write(convert.Uint32Byte(n.PathID))
}
tempBuf.Write(serializePrefix(pfx))
}
......
......@@ -5,6 +5,7 @@ import (
"testing"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/types"
"github.com/stretchr/testify/assert"
)
......@@ -13,6 +14,7 @@ func TestSerializeMultiProtocolReachNLRI(t *testing.T) {
name string
nlri MultiProtocolReachNLRI
expected []byte
addPath bool
}{
{
name: "Simple IPv6 prefix",
......@@ -32,12 +34,35 @@ func TestSerializeMultiProtocolReachNLRI(t *testing.T) {
0x30, 0x26, 0x00, 0x00, 0x06, 0xff, 0x05, // Prefix
},
},
{
name: "IPv6 prefix with ADD-PATH",
nlri: MultiProtocolReachNLRI{
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),
},
PathID: 100,
},
expected: []byte{
0x00, 0x02, // AFI
0x01, // SAFI
0x10, 0x20, 0x01, 0x06, 0x78, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // NextHop
0x00, // RESERVED
0x00, 0x00, 0x00, 100, // PathID
0x30, 0x26, 0x00, 0x00, 0x06, 0xff, 0x05, // Prefix
},
addPath: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
buf := &bytes.Buffer{}
test.nlri.serialize(buf)
test.nlri.serialize(buf, &types.Options{
AddPathRX: test.addPath,
})
assert.Equal(t, test.expected, buf.Bytes())
})
}
......
......@@ -5,6 +5,7 @@ import (
"fmt"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/types"
"github.com/taktv6/tflow2/convert"
)
......@@ -13,13 +14,17 @@ type MultiProtocolUnreachNLRI struct {
AFI uint16
SAFI uint8
Prefixes []bnet.Prefix
PathID uint32
}
func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint16 {
func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer, opt *types.Options) uint16 {
tempBuf := bytes.NewBuffer(nil)
tempBuf.Write(convert.Uint16Byte(n.AFI))
tempBuf.WriteByte(n.SAFI)
for _, pfx := range n.Prefixes {
if opt.AddPathRX {
tempBuf.Write(convert.Uint32Byte(n.PathID))
}
tempBuf.Write(serializePrefix(pfx))
}
......
......@@ -5,6 +5,7 @@ import (
"testing"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/types"
"github.com/stretchr/testify/assert"
)
......@@ -13,6 +14,7 @@ func TestSerializeMultiProtocolUnreachNLRI(t *testing.T) {
name string
nlri MultiProtocolUnreachNLRI
expected []byte
addPath bool
}{
{
name: "Simple IPv6 prefix",
......@@ -29,12 +31,32 @@ func TestSerializeMultiProtocolUnreachNLRI(t *testing.T) {
0x2c, 0x26, 0x20, 0x01, 0x10, 0x90, 0x00, // Prefix
},
},
{
name: "IPv6 prefix with ADD-PATH",
nlri: MultiProtocolUnreachNLRI{
AFI: IPv6AFI,
SAFI: UnicastSAFI,
Prefixes: []bnet.Prefix{
bnet.NewPfx(bnet.IPv6FromBlocks(0x2620, 0x110, 0x9000, 0, 0, 0, 0, 0), 44),
},
PathID: 100,
},
expected: []byte{
0x00, 0x02, // AFI
0x01, // SAFI
0x00, 0x00, 0x00, 100, // PathID
0x2c, 0x26, 0x20, 0x01, 0x10, 0x90, 0x00, // Prefix
},
addPath: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
buf := &bytes.Buffer{}
test.nlri.serialize(buf)
test.nlri.serialize(buf, &types.Options{
AddPathRX: test.addPath,
})
assert.Equal(t, test.expected, buf.Bytes())
})
}
......
......@@ -468,9 +468,9 @@ func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint16
case LargeCommunitiesAttr:
pathAttrLen = uint16(pa.serializeLargeCommunities(buf))
case MultiProtocolReachNLRICode:
pathAttrLen = pa.serializeMultiProtocolReachNLRI(buf)
pathAttrLen = pa.serializeMultiProtocolReachNLRI(buf, opt)
case MultiProtocolUnreachNLRICode:
pathAttrLen = pa.serializeMultiProtocolUnreachNLRI(buf)
pathAttrLen = pa.serializeMultiProtocolUnreachNLRI(buf, opt)
case OriginatorIDAttr:
pathAttrLen = uint16(pa.serializeOriginatorID(buf))
case ClusterListAttr:
......@@ -695,22 +695,22 @@ func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint16 {
return uint16(len(b) + 2)
}
func (pa *PathAttribute) serializeMultiProtocolReachNLRI(buf *bytes.Buffer) uint16 {
func (pa *PathAttribute) serializeMultiProtocolReachNLRI(buf *bytes.Buffer, opt *types.Options) uint16 {
v := pa.Value.(MultiProtocolReachNLRI)
pa.Optional = true
tempBuf := bytes.NewBuffer(nil)
v.serialize(tempBuf)
v.serialize(tempBuf, opt)
return pa.serializeGeneric(tempBuf.Bytes(), buf)
}
func (pa *PathAttribute) serializeMultiProtocolUnreachNLRI(buf *bytes.Buffer) uint16 {
func (pa *PathAttribute) serializeMultiProtocolUnreachNLRI(buf *bytes.Buffer, opt *types.Options) uint16 {
v := pa.Value.(MultiProtocolUnreachNLRI)
pa.Optional = true
tempBuf := bytes.NewBuffer(nil)
v.serialize(tempBuf)
v.serialize(tempBuf, opt)
return pa.serializeGeneric(tempBuf.Bytes(), buf)
}
......
......@@ -179,10 +179,7 @@ func (s *openSentState) processMultiProtocolCapability(cap packet.MultiProtocolC
}
func (s *openSentState) processAddPathCapability(addPathCap packet.AddPathCapability) {
if addPathCap.AFI != 1 {
return
}
if addPathCap.SAFI != 1 {
if addPathCap.SAFI != packet.UnicastSAFI {
return
}
......
......@@ -136,10 +136,7 @@ func newPeer(c config.Peer, rib *locRIB.LocRIB, server *bgpServer) (*peer, error
caps := make(packet.Capabilities, 0)
addPathEnabled, addPathCap := handleAddPathCapability(c)
if addPathEnabled {
caps = append(caps, addPathCap)
}
caps = append(caps, addPathCapabilities(c)...)
caps = append(caps, asn4Capability(c))
......@@ -174,7 +171,9 @@ func multiProtocolCapability(afi uint16) packet.Capability {
}
}
func handleAddPathCapability(c config.Peer) (bool, packet.Capability) {
func addPathCapabilities(c config.Peer) []packet.Capability {
caps := make([]packet.Capability, 0)
addPath := uint8(0)
if c.AddPathRecv {
addPath += packet.AddPathReceive
......@@ -184,17 +183,30 @@ func handleAddPathCapability(c config.Peer) (bool, packet.Capability) {
}
if addPath == 0 {
return false, packet.Capability{}
return caps
}
return true, packet.Capability{
caps = append(caps, packet.Capability{
Code: packet.AddPathCapabilityCode,
Value: packet.AddPathCapability{
AFI: packet.IPv4AFI,
SAFI: packet.UnicastSAFI,
SendReceive: addPath,
},
})
if c.IPv6 {
caps = append(caps, packet.Capability{
Code: packet.AddPathCapabilityCode,
Value: packet.AddPathCapability{
AFI: packet.IPv6AFI,
SAFI: packet.UnicastSAFI,
SendReceive: addPath,
},
})
}
return caps
}
func filterOrDefault(f *filter.Filter) *filter.Filter {
......
......@@ -102,6 +102,10 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
for _, pfx := range pathNLRIs.pfxs {
budget -= int(packet.BytesInAddr(pfx.Pfxlen())) + 1
if u.fsm.options.AddPathRX {
budget -= 4
}
if budget < 0 {
updatesPrefixes = append(updatesPrefixes, prefixes)
prefixes = make([]bnet.Prefix, 0, 1)
......@@ -183,6 +187,7 @@ func (u *UpdateSender) bgpUpdateMultiProtocol(pfxs []bnet.Prefix, pa *packet.Pat
SAFI: packet.UnicastSAFI,
NextHop: nextHop,
Prefixes: pfxs,
PathID: pathID,
},
}
attrs.Next = pa
......@@ -224,7 +229,7 @@ func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool {
func (u *UpdateSender) withdrawPrefix(pfx bnet.Prefix, p *route.Path) error {
if u.fsm.options.SupportsMultiProtocol {
return withDrawPrefixesMultiProtocol(u.fsm.con, u.fsm.options, pfx)
return withDrawPrefixesMultiProtocol(u.fsm.con, u.fsm.options, pfx, p)
}
return withDrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p)
......
......@@ -59,7 +59,12 @@ func withDrawPrefixesAddPath(out io.Writer, opt *types.Options, pfx net.Prefix,
return serializeAndSendUpdate(out, update, opt)
}
func withDrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Prefix) error {
func withDrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Prefix, p *route.Path) error {
pathID := uint32(0)
if p.BGPPath != nil {
pathID = p.BGPPath.PathIdentifier
}
update := &packet.BGPUpdate{
PathAttributes: &packet.PathAttribute{
TypeCode: packet.MultiProtocolUnreachNLRICode,
......@@ -67,8 +72,10 @@ func withDrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Pr
AFI: packet.IPv6AFI,
SAFI: packet.UnicastSAFI,
Prefixes: []net.Prefix{pfx},
PathID: pathID,
},
},
}
return serializeAndSendUpdate(out, update, opt)
}
......@@ -91,7 +91,7 @@ func TestWithDrawPrefixesMultiProtocol(t *testing.T) {
opt := &types.Options{
AddPathRX: false,
}
err := withDrawPrefixesMultiProtocol(buf, opt, test.Prefix)
err := withDrawPrefixesMultiProtocol(buf, opt, test.Prefix, &route.Path{})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment