From 9520337496ed0b9784361d4119aef81647c78ef2 Mon Sep 17 00:00:00 2001 From: Oliver Herms <oliver.herms@exaring.de> Date: Wed, 16 May 2018 14:10:34 +0200 Subject: [PATCH] Added addpath support --- config/peer.go | 2 +- main.go | 7 +- protocols/bgp/packet/bgp.go | 16 ++++ protocols/bgp/packet/decoder.go | 39 ++++++-- protocols/bgp/packet/encoder.go | 68 +++++++++++++- protocols/bgp/packet/encoder_test.go | 36 +++---- protocols/bgp/packet/nlri.go | 13 +++ protocols/bgp/packet/nlri_test.go | 43 +++++++++ protocols/bgp/packet/parameters.go | 9 ++ protocols/bgp/server/fsm.go | 94 ++++++++++++++++--- protocols/bgp/server/peer.go | 4 +- protocols/bgp/server/update_sender.go | 1 + .../bgp/server/update_sender_add_path.go | 73 ++++++++++++++ routingtable/adjRIBOut/adj_rib_out.go | 5 +- .../adjRIBOutAddPath/adj_rib_out_add_path.go | 9 +- routingtable/client_interface.go | 2 + routingtable/locRIB/loc_rib.go | 6 +- 17 files changed, 374 insertions(+), 53 deletions(-) create mode 100644 protocols/bgp/server/update_sender_add_path.go diff --git a/config/peer.go b/config/peer.go index 355e0583..9e057b9d 100644 --- a/config/peer.go +++ b/config/peer.go @@ -17,5 +17,5 @@ type Peer struct { Passive bool RouterID uint32 AddPathSend routingtable.ClientOptions - AddPathRecv uint + AddPathRecv bool } diff --git a/main.go b/main.go index ac5805fc..7e19a5aa 100644 --- a/main.go +++ b/main.go @@ -37,9 +37,12 @@ func main() { KeepAlive: 30, Passive: true, RouterID: b.RouterID(), + AddPathSend: routingtable.ClientOptions{ + MaxPaths: 10, + }, }, rib) - time.Sleep(time.Second * 30) + time.Sleep(time.Second * 15) b.AddPeer(config.Peer{ AdminEnabled: true, @@ -54,7 +57,7 @@ func main() { AddPathSend: routingtable.ClientOptions{ MaxPaths: 10, }, - AddPathRecv: 1, + AddPathRecv: true, }, rib) go func() { diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go index e6ac0e6b..41a2113f 100644 --- a/protocols/bgp/packet/bgp.go +++ b/protocols/bgp/packet/bgp.go @@ -4,6 +4,7 @@ const ( OctetLen = 8 MaxASNsSegment = 255 BGP4Version = 4 + MinOpenLen = 29 MarkerLen = 16 HeaderLen = 19 @@ -128,6 +129,14 @@ type BGPUpdate struct { NLRI *NLRI } +type BGPUpdateAddPath struct { + WithdrawnRoutesLen uint16 + WithdrawnRoutes *NLRIAddPath + TotalPathAttrLen uint16 + PathAttributes *PathAttribute + NLRI *NLRIAddPath +} + type PathAttribute struct { Length uint16 Optional bool @@ -145,6 +154,13 @@ type NLRI struct { Next *NLRI } +type NLRIAddPath struct { + PathIdentifier uint32 + IP uint32 + Pfxlen uint8 + Next *NLRIAddPath +} + type ASPath []ASPathSegment type ASPathSegment struct { Type uint8 diff --git a/protocols/bgp/packet/decoder.go b/protocols/bgp/packet/decoder.go index c5274122..a0179812 100644 --- a/protocols/bgp/packet/decoder.go +++ b/protocols/bgp/packet/decoder.go @@ -130,6 +130,9 @@ func invalidErrCode(n *BGPNotification) (*BGPNotification, error) { func decodeOpenMsg(buf *bytes.Buffer) (*BGPOpen, error) { msg, err := _decodeOpenMsg(buf) + if err != nil { + return nil, fmt.Errorf("Unable to decode OPEN message: %v", err) + } return msg.(*BGPOpen), err } @@ -182,15 +185,18 @@ func decodeOptParams(buf *bytes.Buffer, optParmLen uint8) ([]OptParam, error) { fmt.Printf("Type: %d\n", o.Type) switch o.Type { case CapabilitiesParamType: - cap, err := decodeCapability(buf) + caps, err := decodeCapabilities(buf, o.Length) if err != nil { - return nil, fmt.Errorf("Unable to decode capability: %v", err) + return nil, fmt.Errorf("Unable to decode capabilites: %v", err) } - o.Value = cap + + o.Value = caps optParams = append(optParams, o) - read += cap.Length + 2 + for _, cap := range caps { + read += cap.Length + 2 + } default: - return nil, fmt.Errorf("Unrecognized option") + return nil, fmt.Errorf("Unrecognized option: %d", o.Type) } } @@ -198,6 +204,22 @@ func decodeOptParams(buf *bytes.Buffer, optParmLen uint8) ([]OptParam, error) { return optParams, nil } +func decodeCapabilities(buf *bytes.Buffer, length uint8) (Capabilities, error) { + ret := make(Capabilities, 0) + read := uint8(0) + for read < length { + cap, err := decodeCapability(buf) + if err != nil { + return nil, fmt.Errorf("Unable to decode capability: %v", err) + } + + ret = append(ret, cap) + read += cap.Length + 2 + } + + return ret, nil +} + func decodeCapability(buf *bytes.Buffer) (Capability, error) { cap := Capability{} fields := []interface{}{ @@ -218,7 +240,12 @@ func decodeCapability(buf *bytes.Buffer) (Capability, error) { } cap.Value = addPathCap default: - return cap, fmt.Errorf("Unknown capability: %d", cap.Code) + for i := uint8(0); i < cap.Length; i++ { + _, err := buf.ReadByte() + if err != nil { + return cap, fmt.Errorf("Read failed: %v", err) + } + } } return cap, nil diff --git a/protocols/bgp/packet/encoder.go b/protocols/bgp/packet/encoder.go index 3f44047a..ea87d1ff 100644 --- a/protocols/bgp/packet/encoder.go +++ b/protocols/bgp/packet/encoder.go @@ -26,7 +26,11 @@ func SerializeNotificationMsg(msg *BGPNotification) []byte { } func SerializeOpenMsg(msg *BGPOpen) []byte { - openLen := uint16(29) + optParmsBuf := bytes.NewBuffer(make([]byte, 0)) + serializeOptParams(optParmsBuf, msg.OptParams) + optParms := optParmsBuf.Bytes() + openLen := uint16(len(optParms) + MinOpenLen) + buf := bytes.NewBuffer(make([]byte, 0, openLen)) serializeHeader(buf, openLen, OpenMsg) @@ -35,9 +39,6 @@ func SerializeOpenMsg(msg *BGPOpen) []byte { buf.Write(convert.Uint16Byte(msg.HoldTime)) buf.Write(convert.Uint32Byte(msg.BGPIdentifier)) - optParmsBuf := bytes.NewBuffer(make([]byte, 0)) - serializeOptParams(optParmsBuf, msg.OptParams) - optParms := optParmsBuf.Bytes() buf.WriteByte(uint8(len(optParms))) buf.Write(optParms) @@ -62,6 +63,65 @@ func serializeHeader(buf *bytes.Buffer, length uint16, typ uint8) { buf.WriteByte(typ) } +func (b *BGPUpdateAddPath) SerializeUpdate() ([]byte, error) { + budget := MaxLen - MinLen + buf := bytes.NewBuffer(nil) + + withdrawBuf := bytes.NewBuffer(nil) + for withdraw := b.WithdrawnRoutes; withdraw != nil; withdraw = withdraw.Next { + nlriLen := int(withdraw.serialize(withdrawBuf)) + budget -= nlriLen + if budget < 0 { + return nil, fmt.Errorf("update too long") + } + } + + pathAttributesBuf := bytes.NewBuffer(nil) + for pa := b.PathAttributes; pa != nil; pa = pa.Next { + paLen := int(pa.serialize(pathAttributesBuf)) + budget -= paLen + if budget < 0 { + return nil, fmt.Errorf("update too long") + } + } + + nlriBuf := bytes.NewBuffer(nil) + for nlri := b.NLRI; nlri != nil; nlri = nlri.Next { + nlriLen := int(nlri.serialize(nlriBuf)) + budget -= nlriLen + if budget < 0 { + return nil, fmt.Errorf("update too long") + } + } + + withdrawnRoutesLen := withdrawBuf.Len() + if withdrawnRoutesLen > 65535 { + return nil, fmt.Errorf("Invalid Withdrawn Routes Length: %d", withdrawnRoutesLen) + } + + totalPathAttributesLen := pathAttributesBuf.Len() + if totalPathAttributesLen > 65535 { + return nil, fmt.Errorf("Invalid Total Path Attribute Length: %d", totalPathAttributesLen) + } + + totalLength := 2 + withdrawnRoutesLen + totalPathAttributesLen + 2 + nlriBuf.Len() + 19 + if totalLength > 4096 { + return nil, fmt.Errorf("Update too long: %d bytes", totalLength) + } + + serializeHeader(buf, uint16(totalLength), UpdateMsg) + + buf.Write(convert.Uint16Byte(uint16(withdrawnRoutesLen))) + buf.Write(withdrawBuf.Bytes()) + + buf.Write(convert.Uint16Byte(uint16(totalPathAttributesLen))) + buf.Write(pathAttributesBuf.Bytes()) + + buf.Write(nlriBuf.Bytes()) + + return buf.Bytes(), nil +} + func (b *BGPUpdate) SerializeUpdate() ([]byte, error) { budget := MaxLen - MinLen buf := bytes.NewBuffer(nil) diff --git a/protocols/bgp/packet/encoder_test.go b/protocols/bgp/packet/encoder_test.go index cc6968d9..0d4f70a3 100644 --- a/protocols/bgp/packet/encoder_test.go +++ b/protocols/bgp/packet/encoder_test.go @@ -94,7 +94,7 @@ func TestSerializeOpenMsg(t *testing.T) { } } -/*func TestSerializeOptParams(t *testing.T) { +func TestSerializeOptParams(t *testing.T) { tests := []struct { name string optParams []OptParam @@ -109,28 +109,20 @@ func TestSerializeOpenMsg(t *testing.T) { name: "1 Option", optParams: []OptParam{ { - Type: 100, - Length: 2, - Value: []byte{1, 2}, + Type: 2, + Length: 6, + Value: Capability{ + Code: 69, + Length: 4, + Value: AddPathCapability{ + AFI: 1, + SAFI: 1, + SendReceive: 3, + }, + }, }, }, - expected: []byte{100, 2, 1, 2}, - }, - { - name: "2 Options", - optParams: []OptParam{ - { - Type: 100, - Length: 2, - Value: []byte{1, 2}, - }, - { - Type: 200, - Length: 2, - Value: []byte{3, 4}, - }, - }, - expected: []byte{100, 2, 1, 2, 200, 2, 3, 4}, + expected: []byte{2, 6, 69, 4, 0, 1, 1, 3}, }, } @@ -139,7 +131,7 @@ func TestSerializeOpenMsg(t *testing.T) { serializeOptParams(buf, test.optParams) assert.Equal(t, test.expected, buf.Bytes()) } -}*/ +} func TestSerializeHeader(t *testing.T) { tests := []struct { diff --git a/protocols/bgp/packet/nlri.go b/protocols/bgp/packet/nlri.go index 05fecbff..6de92a6c 100644 --- a/protocols/bgp/packet/nlri.go +++ b/protocols/bgp/packet/nlri.go @@ -73,6 +73,19 @@ func (n *NLRI) serialize(buf *bytes.Buffer) uint8 { return nBytes + 1 } +func (n *NLRIAddPath) serialize(buf *bytes.Buffer) uint8 { + a := convert.Uint32Byte(n.IP) + + addr := [4]byte{a[0], a[1], a[2], a[3]} + nBytes := bytesInAddr(n.Pfxlen) + + buf.Write(convert.Uint32Byte(n.PathIdentifier)) + buf.WriteByte(n.Pfxlen) + buf.Write(addr[:nBytes]) + + return nBytes + 1 +} + func bytesInAddr(pfxlen uint8) uint8 { return uint8(math.Ceil(float64(pfxlen) / 8)) } diff --git a/protocols/bgp/packet/nlri_test.go b/protocols/bgp/packet/nlri_test.go index b97509b8..17a17dd3 100644 --- a/protocols/bgp/packet/nlri_test.go +++ b/protocols/bgp/packet/nlri_test.go @@ -208,3 +208,46 @@ func TestNLRISerialize(t *testing.T) { assert.Equal(t, test.expected, res) } } + +func TestNLRIAddPathSerialize(t *testing.T) { + tests := []struct { + name string + nlri *NLRIAddPath + expected []byte + }{ + { + name: "Test #1", + nlri: &NLRIAddPath{ + PathIdentifier: 100, + IP: strAddr("1.2.3.0"), + Pfxlen: 25, + }, + expected: []byte{0, 0, 0, 100, 25, 1, 2, 3, 0}, + }, + { + name: "Test #2", + nlri: &NLRIAddPath{ + PathIdentifier: 100, + IP: strAddr("1.2.3.0"), + Pfxlen: 24, + }, + expected: []byte{0, 0, 0, 100, 24, 1, 2, 3}, + }, + { + name: "Test #3", + nlri: &NLRIAddPath{ + PathIdentifier: 100, + IP: strAddr("100.200.128.0"), + Pfxlen: 17, + }, + expected: []byte{0, 0, 0, 100, 17, 100, 200, 128}, + }, + } + + for _, test := range tests { + buf := bytes.NewBuffer(nil) + test.nlri.serialize(buf) + res := buf.Bytes() + assert.Equal(t, test.expected, res) + } +} diff --git a/protocols/bgp/packet/parameters.go b/protocols/bgp/packet/parameters.go index 543bc447..8edf42fc 100644 --- a/protocols/bgp/packet/parameters.go +++ b/protocols/bgp/packet/parameters.go @@ -16,12 +16,21 @@ type OptParam struct { Value Serializable } +type Capabilities []Capability + type Capability struct { Code uint8 Length uint8 Value Serializable } +func (c Capabilities) serialize(buf *bytes.Buffer) { + tmpBuf := bytes.NewBuffer(make([]byte, 0)) + for _, cap := range c { + cap.serialize(tmpBuf) + } +} + func (c Capability) serialize(buf *bytes.Buffer) { tmpBuf := bytes.NewBuffer(make([]byte, 0)) c.Value.serialize(tmpBuf) diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go index c41e03b1..c53696fb 100644 --- a/protocols/bgp/server/fsm.go +++ b/protocols/bgp/server/fsm.go @@ -15,6 +15,7 @@ import ( "github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/routingtable/adjRIBIn" "github.com/bio-routing/bio-rd/routingtable/adjRIBOut" + "github.com/bio-routing/bio-rd/routingtable/adjRIBOutAddPath" "github.com/bio-routing/bio-rd/routingtable/locRIB" log "github.com/sirupsen/logrus" tomb "gopkg.in/tomb.v2" @@ -90,9 +91,12 @@ type FSM struct { stopMsgRecvCh chan struct{} adjRIBIn *adjRIBIn.AdjRIBIn - adjRIBOut *adjRIBOut.AdjRIBOut + adjRIBOut routingtable.RouteTableClient rib *locRIB.LocRIB - updateSender *UpdateSender + updateSender routingtable.RouteTableClient + + capAddPathSend bool + capAddPathRecv bool } type msgRecvMsg struct { @@ -134,7 +138,6 @@ func NewFSM(peer *Peer, c config.Peer, rib *locRIB.LocRIB) *FSM { rib: rib, } - fsm.updateSender = newUpdateSender(fsm) return fsm } @@ -303,8 +306,6 @@ func (fsm *FSM) connect() int { } func (fsm *FSM) connectSendOpen() int { - optOpenParams := make([]packet.OptParam, 0) - err := fsm.sendOpen(fsm.con) if err != nil { stopTimer(fsm.connectRetryTimer) @@ -459,6 +460,9 @@ func (fsm *FSM) openSent() int { fsm.keepaliveTime = fsm.holdTime / 3 fsm.keepaliveTimer.Reset(time.Second * fsm.keepaliveTime) } + + fsm.processOpenOptions(openMsg.OptParams) + return fsm.changeState(OpenConfirm, "Received OPEN message") default: sendNotification(fsm.con, packet.FiniteStateMachineError, 0) @@ -485,6 +489,56 @@ func (fsm *FSM) openSent() int { } } +func (fsm *FSM) processOpenOptions(optParams []packet.OptParam) { + for _, optParam := range optParams { + if optParam.Type != packet.CapabilitiesParamType { + continue + } + + fsm.processCapabilities(optParam.Value.(packet.Capabilities)) + } +} + +func (fsm *FSM) processCapabilities(caps packet.Capabilities) { + for _, cap := range caps { + fsm.processCapability(cap) + } +} + +func (fsm *FSM) processCapability(cap packet.Capability) { + switch cap.Code { + case packet.AddPathCapabilityCode: + fsm.processAddPathCapability(cap.Value.(packet.AddPathCapability)) + + } +} + +func (fsm *FSM) processAddPathCapability(addPathCap packet.AddPathCapability) { + if addPathCap.AFI != 1 { + return + } + if addPathCap.SAFI != 1 { + return + } + switch addPathCap.SendReceive { + case packet.AddPathReceive: + if !fsm.peer.addPathSend.BestOnly { + fsm.capAddPathSend = true + } + case packet.AddPathSend: + if fsm.peer.addPathRecv { + fsm.capAddPathRecv = true + } + case packet.AddPathSendReceive: + if !fsm.peer.addPathSend.BestOnly { + fsm.capAddPathSend = true + } + if fsm.peer.addPathRecv { + fsm.capAddPathRecv = true + } + } +} + func (fsm *FSM) openSentTCPFail(err error) int { fsm.con.Close() fsm.resetConnectRetryTimer() @@ -607,7 +661,7 @@ func (fsm *FSM) openConfirm() int { switch msg.Header.Type { case packet.NotificationMsg: - nMsg := msg.Body.(packet.BGPNotification) + nMsg := msg.Body.(*packet.BGPNotification) if nMsg.ErrorCode == packet.UnsupportedVersionNumber { stopTimer(fsm.connectRetryTimer) fsm.con.Close() @@ -669,18 +723,30 @@ func (fsm *FSM) established() int { Type: route.BGPPathType, Address: tnet.IPv4ToUint32(fsm.remote), } - fsm.adjRIBOut = adjRIBOut.New(n) - fsm.adjRIBOut.Register(fsm.updateSender) - fsm.rib.RegisterWithOptions(fsm.adjRIBOut, routingtable.ClientOptions{BestOnly: true}) + clientOptions := routingtable.ClientOptions{} + if fsm.capAddPathSend { + fsm.updateSender = newUpdateSenderAddPath(fsm) + fsm.adjRIBOut = adjRIBOutAddPath.New(n) + clientOptions = fsm.peer.addPathSend + } else { + fsm.updateSender = newUpdateSender(fsm) + fsm.adjRIBOut = adjRIBOut.New(n) + } + + fsm.adjRIBOut.Register(fsm.updateSender) + fsm.rib.RegisterWithOptions(fsm.adjRIBOut, clientOptions) - go func() { + /*go func() { for { + if fsm.adjRIBOut == nil { + return + } fmt.Printf("ADJ-RIB-OUT: %s\n", fsm.remote.String()) fmt.Print(fsm.adjRIBOut.Print()) time.Sleep(time.Second * 11) } - }() + }()*/ for { select { @@ -756,8 +822,10 @@ func (fsm *FSM) established() int { fmt.Printf("LPM: Adding prefix %s\n", pfx.String()) path := &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + Source: tnet.IPv4ToUint32(fsm.remote), + }, } for pa := u.PathAttributes; pa != nil; pa = pa.Next { diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go index e3091290..7bfcbc56 100644 --- a/protocols/bgp/server/peer.go +++ b/protocols/bgp/server/peer.go @@ -17,7 +17,7 @@ type Peer struct { rib *locRIB.LocRIB routerID uint32 addPathSend routingtable.ClientOptions - addPathRecv uint + addPathRecv bool optOpenParams []packet.OptParam } @@ -35,7 +35,7 @@ func NewPeer(c config.Peer, rib *locRIB.LocRIB) (*Peer, error) { caps := make([]packet.Capability, 0) addPath := uint8(0) - if c.AddPathRecv > 1 { + if c.AddPathRecv { addPath += packet.AddPathReceive } if !c.AddPathSend.BestOnly { diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go index 329e9713..07af48dd 100644 --- a/protocols/bgp/server/update_sender.go +++ b/protocols/bgp/server/update_sender.go @@ -12,6 +12,7 @@ import ( ) type UpdateSender struct { + routingtable.ClientManager fsm *FSM } diff --git a/protocols/bgp/server/update_sender_add_path.go b/protocols/bgp/server/update_sender_add_path.go new file mode 100644 index 00000000..fc7fd0a7 --- /dev/null +++ b/protocols/bgp/server/update_sender_add_path.go @@ -0,0 +1,73 @@ +package server + +import ( + "fmt" + + log "github.com/sirupsen/logrus" + + "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" +) + +type UpdateSenderAddPath struct { + routingtable.ClientManager + fsm *FSM +} + +func newUpdateSenderAddPath(fsm *FSM) *UpdateSenderAddPath { + return &UpdateSenderAddPath{ + fsm: fsm, + } +} + +func (u *UpdateSenderAddPath) AddPath(pfx net.Prefix, p *route.Path) error { + fmt.Printf("SENDING AN BGP UPDATE WITH ADD PATH TO %s\n", u.fsm.remote.String()) + asPathPA, err := packet.ParseASPathStr(fmt.Sprintf("%d %s", u.fsm.localASN, p.BGPPath.ASPath)) + if err != nil { + return fmt.Errorf("Unable to parse AS path: %v", err) + } + + update := &packet.BGPUpdateAddPath{ + PathAttributes: &packet.PathAttribute{ + TypeCode: packet.OriginAttr, + Value: p.BGPPath.Origin, + Next: &packet.PathAttribute{ + TypeCode: packet.ASPathAttr, + Value: asPathPA.Value, + Next: &packet.PathAttribute{ + TypeCode: packet.NextHopAttr, + Value: p.BGPPath.NextHop, + }, + }, + }, + NLRI: &packet.NLRIAddPath{ + PathIdentifier: p.BGPPath.PathIdentifier, + IP: pfx.Addr(), + Pfxlen: pfx.Pfxlen(), + }, + } + + updateBytes, err := update.SerializeUpdate() + if err != nil { + log.Errorf("Unable to serialize BGP Update: %v", err) + return nil + } + fmt.Printf("Sending Update: %v\n", updateBytes) + _, err = u.fsm.con.Write(updateBytes) + if err != nil { + return fmt.Errorf("Failed sending Update: %v", err) + } + return nil +} + +func (u *UpdateSenderAddPath) RemovePath(pfx net.Prefix, p *route.Path) bool { + log.Warningf("BGP Update Sender: RemovePath not implemented") + return false +} + +func (u *UpdateSenderAddPath) UpdateNewClient(client routingtable.RouteTableClient) error { + log.Warningf("BGP Update Sender: RemovePath not implemented") + return nil +} diff --git a/routingtable/adjRIBOut/adj_rib_out.go b/routingtable/adjRIBOut/adj_rib_out.go index 8691c5ac..086d8654 100644 --- a/routingtable/adjRIBOut/adj_rib_out.go +++ b/routingtable/adjRIBOut/adj_rib_out.go @@ -7,6 +7,7 @@ import ( "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/routingtable" + "github.com/taktv6/tflow2/convert" ) // AdjRIBOut represents an Adjacency RIB In as described in RFC4271 @@ -29,11 +30,13 @@ func New(neighbor *routingtable.Neighbor) *AdjRIBOut { // UpdateNewClient sends current state to a new client func (a *AdjRIBOut) UpdateNewClient(client routingtable.RouteTableClient) error { - return fmt.Errorf("Not supported") + return nil } // AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added. func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error { + fmt.Printf("THIS IS ADJ RIB OUT NON ADD PATH FOR %v\n", convert.Uint32Byte(a.neighbor.Address)) + if a.isOwnPath(p) { return nil } diff --git a/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go b/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go index b3e440a8..5c661734 100644 --- a/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go +++ b/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go @@ -7,6 +7,7 @@ import ( "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/routingtable" + "github.com/taktv6/tflow2/convert" ) // AdjRIBOutAddPath represents an Adjacency RIB Out with BGP add path @@ -29,11 +30,13 @@ func New(neighbor *routingtable.Neighbor) *AdjRIBOutAddPath { // UpdateNewClient sends current state to a new client func (a *AdjRIBOutAddPath) UpdateNewClient(client routingtable.RouteTableClient) error { - return fmt.Errorf("Not supported") + return nil } // AddPath adds path p to prefix `pfx` func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error { + fmt.Printf("THIS IS ADD PATH ON ADJ RIB OUT FOR %v", convert.Uint32Byte(a.neighbor.Address)) + if a.isOwnPath(p) { return nil } @@ -41,6 +44,10 @@ func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error { a.mu.Lock() defer a.mu.Unlock() + p.BGPPath.PathIdentifier = 7 + + a.rt.AddPath(pfx, p) + for _, client := range a.ClientManager.Clients() { client.AddPath(pfx, p) } diff --git a/routingtable/client_interface.go b/routingtable/client_interface.go index 63ba81e8..0800ceec 100644 --- a/routingtable/client_interface.go +++ b/routingtable/client_interface.go @@ -10,4 +10,6 @@ type RouteTableClient interface { AddPath(net.Prefix, *route.Path) error RemovePath(net.Prefix, *route.Path) bool UpdateNewClient(RouteTableClient) error + Register(RouteTableClient) + Unregister(RouteTableClient) } diff --git a/routingtable/locRIB/loc_rib.go b/routingtable/locRIB/loc_rib.go index 6e030de3..8d8632c0 100644 --- a/routingtable/locRIB/loc_rib.go +++ b/routingtable/locRIB/loc_rib.go @@ -51,7 +51,7 @@ func (a *LocRIB) AddPath(pfx net.Prefix, p *route.Path) error { oldRoute = r.Copy() routeExisted = true } - + // FIXME: in AddPath() we assume that the same reference of route (r) is modified (not responsibility of locRIB). If this implementation changes in the future this code will break. a.rt.AddPath(pfx, p) if !routeExisted { @@ -99,6 +99,7 @@ func (a *LocRIB) propagateChanges(oldRoute *route.Route, newRoute *route.Route) } func (a *LocRIB) addPathsToClients(oldRoute *route.Route, newRoute *route.Route) { + fmt.Printf("LocRIB: Updating %d clients\n", len(a.ClientManager.Clients())) for _, client := range a.ClientManager.Clients() { opts := a.ClientManager.GetOptions(client) oldMaxPaths := opts.GetMaxPaths(oldRoute.ECMPPathCount()) @@ -107,6 +108,9 @@ func (a *LocRIB) addPathsToClients(oldRoute *route.Route, newRoute *route.Route) oldPathsLimit := int(math.Min(float64(oldMaxPaths), float64(len(oldRoute.Paths())))) newPathsLimit := int(math.Min(float64(newMaxPaths), float64(len(newRoute.Paths())))) + fmt.Printf("oldPathsLimit: %v\n", oldPathsLimit) + fmt.Printf("newPathsLimit: %v\n", newPathsLimit) + advertise := route.PathsDiff(newRoute.Paths()[0:newPathsLimit], oldRoute.Paths()[0:oldPathsLimit]) fmt.Printf("ADVERTISING PATHS %v TO CLIENTS\n", advertise) -- GitLab