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

export ipv6 routes

parent 0995e3d7
Branches
Tags
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