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

export ipv6 routes

parent 0995e3d7
No related branches found
No related tags found
No related merge requests found
...@@ -16,6 +16,8 @@ const ( ...@@ -16,6 +16,8 @@ const (
SAFILen = 1 SAFILen = 1
CommunityLen = 4 CommunityLen = 4
LargeCommunityLen = 12 LargeCommunityLen = 12
IPv4Len = 4
IPv6Len = 16
OpenMsg = 1 OpenMsg = 1
UpdateMsg = 2 UpdateMsg = 2
......
...@@ -17,7 +17,7 @@ type MultiProtocolReachNLRI struct { ...@@ -17,7 +17,7 @@ type MultiProtocolReachNLRI struct {
Prefixes []bnet.Prefix Prefixes []bnet.Prefix
} }
func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint8 { func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint16 {
nextHop := n.NextHop.Bytes() nextHop := n.NextHop.Bytes()
tempBuf := bytes.NewBuffer(nil) tempBuf := bytes.NewBuffer(nil)
...@@ -32,7 +32,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint8 { ...@@ -32,7 +32,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint8 {
buf.Write(tempBuf.Bytes()) buf.Write(tempBuf.Bytes())
return uint8(tempBuf.Len()) return uint16(tempBuf.Len())
} }
func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error) { func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error) {
......
...@@ -15,7 +15,7 @@ type MultiProtocolUnreachNLRI struct { ...@@ -15,7 +15,7 @@ type MultiProtocolUnreachNLRI struct {
Prefixes []bnet.Prefix Prefixes []bnet.Prefix
} }
func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint8 { func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint16 {
tempBuf := bytes.NewBuffer(nil) tempBuf := bytes.NewBuffer(nil)
tempBuf.Write(convert.Uint16Byte(n.AFI)) tempBuf.Write(convert.Uint16Byte(n.AFI))
tempBuf.WriteByte(n.SAFI) tempBuf.WriteByte(n.SAFI)
...@@ -25,7 +25,7 @@ func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint8 { ...@@ -25,7 +25,7 @@ func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint8 {
buf.Write(tempBuf.Bytes()) buf.Write(tempBuf.Bytes())
return uint8(tempBuf.Len()) return uint16(tempBuf.Len())
} }
func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, error) { func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, error) {
......
...@@ -3,6 +3,7 @@ package packet ...@@ -3,6 +3,7 @@ package packet
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"math"
bnet "github.com/bio-routing/bio-rd/net" bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/bio-routing/bio-rd/protocols/bgp/types"
...@@ -434,6 +435,10 @@ func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint16 ...@@ -434,6 +435,10 @@ func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint16
pathAttrLen = uint16(pa.serializeCommunities(buf)) pathAttrLen = uint16(pa.serializeCommunities(buf))
case LargeCommunitiesAttr: case LargeCommunitiesAttr:
pathAttrLen = uint16(pa.serializeLargeCommunities(buf)) pathAttrLen = uint16(pa.serializeLargeCommunities(buf))
case MultiProtocolReachNLRICode:
pathAttrLen = pa.serializeMultiProtocolReachNLRI(buf)
case MultiProtocolUnreachNLRICode:
pathAttrLen = pa.serializeMultiProtocolUnreachNLRI(buf)
default: default:
pathAttrLen = pa.serializeUnknownAttribute(buf) pathAttrLen = pa.serializeUnknownAttribute(buf)
} }
...@@ -621,6 +626,62 @@ func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint16 { ...@@ -621,6 +626,62 @@ func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint16 {
return uint16(len(b) + 2) return uint16(len(b) + 2)
} }
func (pa *PathAttribute) serializeMultiProtocolReachNLRI(buf *bytes.Buffer) uint16 {
v := pa.Value.(MultiProtocolReachNLRI)
pa.Optional = true
tempBuf := bytes.NewBuffer(nil)
v.serialize(tempBuf)
return pa.serializeGeneric(tempBuf.Bytes(), buf)
}
func (pa *PathAttribute) serializeMultiProtocolUnreachNLRI(buf *bytes.Buffer) uint16 {
v := pa.Value.(MultiProtocolUnreachNLRI)
pa.Optional = true
tempBuf := bytes.NewBuffer(nil)
v.serialize(tempBuf)
return pa.serializeGeneric(tempBuf.Bytes(), buf)
}
func (pa *PathAttribute) serializeGeneric(b []byte, buf *bytes.Buffer) uint16 {
attrFlags := uint8(0)
if pa.Optional {
attrFlags = setOptional(attrFlags)
}
if pa.Transitive {
attrFlags = setTransitive(attrFlags)
}
if len(b) > math.MaxUint8 {
pa.ExtendedLength = true
}
if pa.ExtendedLength {
attrFlags = setExtendedLength(attrFlags)
}
if pa.Transitive {
attrFlags = setTransitive(attrFlags)
}
buf.WriteByte(attrFlags)
buf.WriteByte(pa.TypeCode)
if pa.ExtendedLength {
l := len(b)
buf.WriteByte(uint8(l >> 8))
buf.WriteByte(uint8(l & 0x0000FFFF))
} else {
buf.WriteByte(uint8(len(b)))
}
buf.Write(b)
return uint16(len(b) + 2)
}
func fourBytesToUint32(address [4]byte) uint32 { func fourBytesToUint32(address [4]byte) uint32 {
return uint32(address[0])<<24 + uint32(address[1])<<16 + uint32(address[2])<<8 + uint32(address[3]) return uint32(address[0])<<24 + uint32(address[1])<<16 + uint32(address[2])<<8 + uint32(address[3])
} }
......
...@@ -84,8 +84,11 @@ func (u *UpdateSender) sender(aggrTime time.Duration) { ...@@ -84,8 +84,11 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
u.toSendMu.Lock() u.toSendMu.Lock()
overhead := u.updateOverhead()
for key, pathNLRIs := range u.toSend { for key, pathNLRIs := range u.toSend {
budget = packet.MaxLen - packet.HeaderLen - packet.MinUpdateLen - int(pathNLRIs.path.BGPPath.Length()) budget = packet.MaxLen - packet.HeaderLen - packet.MinUpdateLen - int(pathNLRIs.path.BGPPath.Length()) - overhead
pathAttrs, err = packet.PathAttributes(pathNLRIs.path, u.iBGP) pathAttrs, err = packet.PathAttributes(pathNLRIs.path, u.iBGP)
if err != nil { if err != nil {
log.Errorf("Unable to get path attributes: %v", err) log.Errorf("Unable to get path attributes: %v", err)
...@@ -96,10 +99,11 @@ func (u *UpdateSender) sender(aggrTime time.Duration) { ...@@ -96,10 +99,11 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
prefixes := make([]bnet.Prefix, 0, 1) prefixes := make([]bnet.Prefix, 0, 1)
for _, pfx := range pathNLRIs.pfxs { for _, pfx := range pathNLRIs.pfxs {
budget -= int(packet.BytesInAddr(pfx.Pfxlen())) + 1 budget -= int(packet.BytesInAddr(pfx.Pfxlen())) + 1
if budget < 0 { if budget < 0 {
updatesPrefixes = append(updatesPrefixes, prefixes) updatesPrefixes = append(updatesPrefixes, prefixes)
prefixes = make([]bnet.Prefix, 0, 1) prefixes = make([]bnet.Prefix, 0, 1)
budget = packet.MaxLen - int(pathNLRIs.path.BGPPath.Length()) budget = packet.MaxLen - int(pathNLRIs.path.BGPPath.Length()) - overhead
} }
prefixes = append(prefixes, pfx) prefixes = append(prefixes, pfx)
...@@ -118,30 +122,97 @@ func (u *UpdateSender) sender(aggrTime time.Duration) { ...@@ -118,30 +122,97 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
} }
} }
func (u *UpdateSender) updateOverhead() int {
// TODO: for multi RIB support we need the AFI/SAFI combination to determine overhead. For now: MultiProtocol = IPv6
if u.fsm.options.SupportsMultiProtocol {
// since we are replacing the next hop attribute IPv4Len has to be subtracted, we also add another byte for extended length
return packet.AFILen + packet.SAFILen + 1 + packet.IPv6Len - packet.IPv4Len + 1
}
return 0
}
func (u *UpdateSender) sendUpdates(pathAttrs *packet.PathAttribute, updatePrefixes [][]bnet.Prefix, pathID uint32) { func (u *UpdateSender) sendUpdates(pathAttrs *packet.PathAttribute, updatePrefixes [][]bnet.Prefix, pathID uint32) {
var nlri *packet.NLRI
var err error var err error
for _, prefixes := range updatePrefixes {
update := u.updateMessageForPrefixes(prefixes, pathAttrs, pathID)
for _, updatePrefix := range updatePrefixes { err = serializeAndSendUpdate(u.fsm.con, update, u.fsm.options)
update := &packet.BGPUpdate{ if err != nil {
PathAttributes: pathAttrs, log.Errorf("Failed to serialize and send: %v", err)
} }
}
}
for _, pfx := range updatePrefix { func (u *UpdateSender) updateMessageForPrefixes(pfxs []bnet.Prefix, pa *packet.PathAttribute, pathID uint32) *packet.BGPUpdate {
nlri = &packet.NLRI{ if u.fsm.options.SupportsMultiProtocol {
PathIdentifier: pathID, return u.bgpUpdateMultiProtocol(pfxs, pa, pathID)
IP: pfx.Addr().ToUint32(), }
Pfxlen: pfx.Pfxlen(),
Next: update.NLRI, return u.bgpUpdate(pfxs, pa, pathID)
} }
update.NLRI = nlri
func (u *UpdateSender) bgpUpdate(pfxs []bnet.Prefix, pa *packet.PathAttribute, pathID uint32) *packet.BGPUpdate {
update := &packet.BGPUpdate{
PathAttributes: pa,
}
var nlri *packet.NLRI
for _, pfx := range pfxs {
nlri = &packet.NLRI{
PathIdentifier: pathID,
IP: pfx.Addr().ToUint32(),
Pfxlen: pfx.Pfxlen(),
Next: update.NLRI,
} }
update.NLRI = nlri
}
err = serializeAndSendUpdate(u.fsm.con, update, u.fsm.options) return update
if err != nil { }
log.Errorf("Failed to serialize and send: %v", err)
func (u *UpdateSender) bgpUpdateMultiProtocol(pfxs []bnet.Prefix, pa *packet.PathAttribute, pathID uint32) *packet.BGPUpdate {
pa, nextHop := u.copyAttributesWithoutNextHop(pa)
attrs := &packet.PathAttribute{
TypeCode: packet.MultiProtocolReachNLRICode,
Value: packet.MultiProtocolReachNLRI{
AFI: packet.IPv6AFI,
SAFI: packet.UnicastSAFI,
NextHop: nextHop,
Prefixes: pfxs,
},
}
attrs.Next = pa
return &packet.BGPUpdate{
PathAttributes: attrs,
}
}
func (u *UpdateSender) copyAttributesWithoutNextHop(pa *packet.PathAttribute) (attrs *packet.PathAttribute, nextHop bnet.IP) {
attrs = pa.Copy()
curCopy := attrs
cur := pa
if cur.TypeCode == packet.NextHopAttr {
nextHop = cur.Value.(bnet.IP)
cur = cur.Next
}
for cur != nil {
if cur.TypeCode == packet.NextHopAttr {
nextHop = cur.Value.(bnet.IP)
} else {
curCopy.Next = cur.Copy()
curCopy = curCopy.Next
} }
cur = cur.Next
} }
return attrs, nextHop
} }
// RemovePath withdraws prefix `pfx` from a peer // RemovePath withdraws prefix `pfx` from a peer
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment