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 (
SAFILen = 1
CommunityLen = 4
LargeCommunityLen = 12
IPv4Len = 4
IPv6Len = 16
OpenMsg = 1
UpdateMsg = 2
......
......@@ -17,7 +17,7 @@ type MultiProtocolReachNLRI struct {
Prefixes []bnet.Prefix
}
func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint8 {
func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint16 {
nextHop := n.NextHop.Bytes()
tempBuf := bytes.NewBuffer(nil)
......@@ -32,7 +32,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint8 {
buf.Write(tempBuf.Bytes())
return uint8(tempBuf.Len())
return uint16(tempBuf.Len())
}
func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error) {
......
......@@ -15,7 +15,7 @@ type MultiProtocolUnreachNLRI struct {
Prefixes []bnet.Prefix
}
func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint8 {
func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint16 {
tempBuf := bytes.NewBuffer(nil)
tempBuf.Write(convert.Uint16Byte(n.AFI))
tempBuf.WriteByte(n.SAFI)
......@@ -25,7 +25,7 @@ func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint8 {
buf.Write(tempBuf.Bytes())
return uint8(tempBuf.Len())
return uint16(tempBuf.Len())
}
func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, error) {
......
......@@ -3,6 +3,7 @@ package packet
import (
"bytes"
"fmt"
"math"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/types"
......@@ -434,6 +435,10 @@ func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint16
pathAttrLen = uint16(pa.serializeCommunities(buf))
case LargeCommunitiesAttr:
pathAttrLen = uint16(pa.serializeLargeCommunities(buf))
case MultiProtocolReachNLRICode:
pathAttrLen = pa.serializeMultiProtocolReachNLRI(buf)
case MultiProtocolUnreachNLRICode:
pathAttrLen = pa.serializeMultiProtocolUnreachNLRI(buf)
default:
pathAttrLen = pa.serializeUnknownAttribute(buf)
}
......@@ -621,6 +626,62 @@ func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint16 {
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 {
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) {
u.toSendMu.Lock()
overhead := u.updateOverhead()
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)
if err != nil {
log.Errorf("Unable to get path attributes: %v", err)
......@@ -96,10 +99,11 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
prefixes := make([]bnet.Prefix, 0, 1)
for _, pfx := range pathNLRIs.pfxs {
budget -= int(packet.BytesInAddr(pfx.Pfxlen())) + 1
if budget < 0 {
updatesPrefixes = append(updatesPrefixes, prefixes)
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)
......@@ -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) {
var nlri *packet.NLRI
var err error
for _, prefixes := range updatePrefixes {
update := u.updateMessageForPrefixes(prefixes, pathAttrs, pathID)
for _, updatePrefix := range updatePrefixes {
update := &packet.BGPUpdate{
PathAttributes: pathAttrs,
err = serializeAndSendUpdate(u.fsm.con, update, u.fsm.options)
if err != nil {
log.Errorf("Failed to serialize and send: %v", err)
}
}
}
for _, pfx := range updatePrefix {
nlri = &packet.NLRI{
PathIdentifier: pathID,
IP: pfx.Addr().ToUint32(),
Pfxlen: pfx.Pfxlen(),
Next: update.NLRI,
}
update.NLRI = nlri
func (u *UpdateSender) updateMessageForPrefixes(pfxs []bnet.Prefix, pa *packet.PathAttribute, pathID uint32) *packet.BGPUpdate {
if u.fsm.options.SupportsMultiProtocol {
return u.bgpUpdateMultiProtocol(pfxs, pa, pathID)
}
return u.bgpUpdate(pfxs, pa, pathID)
}
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)
if err != nil {
log.Errorf("Failed to serialize and send: %v", err)
return update
}
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
......
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