diff --git a/protocols/bgp/packet/BUILD.bazel b/protocols/bgp/packet/BUILD.bazel index f9886e41d0eea9ee21bac03dc902ad7f4218b131..9ea14d6607ee4dfe18b135e29c8de7c9d3a4b8a3 100644 --- a/protocols/bgp/packet/BUILD.bazel +++ b/protocols/bgp/packet/BUILD.bazel @@ -4,7 +4,9 @@ go_library( name = "go_default_library", srcs = [ "bgp.go", + "decode_options.go", "decoder.go", + "encode_options.go", "encoder.go", "helper.go", "mp_reach_nlri.go", diff --git a/protocols/bgp/packet/decoder.go b/protocols/bgp/packet/decoder.go index cd951463a15215bd6aaa43e8799e59c95cee549b..0d719fc04c20779ae818e21e756ba925c4bb4e5e 100644 --- a/protocols/bgp/packet/decoder.go +++ b/protocols/bgp/packet/decoder.go @@ -6,12 +6,11 @@ import ( "fmt" "net" - "github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/taktv6/tflow2/convert" ) // Decode decodes a BGP message -func Decode(buf *bytes.Buffer, opt *types.Options) (*BGPMessage, error) { +func Decode(buf *bytes.Buffer, opt *DecodeOptions) (*BGPMessage, error) { hdr, err := decodeHeader(buf) if err != nil { return nil, fmt.Errorf("Failed to decode header: %v", err) @@ -28,7 +27,7 @@ func Decode(buf *bytes.Buffer, opt *types.Options) (*BGPMessage, error) { }, nil } -func decodeMsgBody(buf *bytes.Buffer, msgType uint8, l uint16, opt *types.Options) (interface{}, error) { +func decodeMsgBody(buf *bytes.Buffer, msgType uint8, l uint16, opt *DecodeOptions) (interface{}, error) { switch msgType { case OpenMsg: return decodeOpenMsg(buf) @@ -42,7 +41,7 @@ func decodeMsgBody(buf *bytes.Buffer, msgType uint8, l uint16, opt *types.Option return nil, fmt.Errorf("Unknown message type: %d", msgType) } -func decodeUpdateMsg(buf *bytes.Buffer, l uint16, opt *types.Options) (*BGPUpdate, error) { +func decodeUpdateMsg(buf *bytes.Buffer, l uint16, opt *DecodeOptions) (*BGPUpdate, error) { msg := &BGPUpdate{} err := decode(buf, []interface{}{&msg.WithdrawnRoutesLen}) diff --git a/protocols/bgp/packet/decoder_test.go b/protocols/bgp/packet/decoder_test.go index ac611ceff133e4375e70995a2b564900671ed8aa..74e5b84f978f084c38360b85b72030fe79fe945e 100644 --- a/protocols/bgp/packet/decoder_test.go +++ b/protocols/bgp/packet/decoder_test.go @@ -74,7 +74,7 @@ func BenchmarkDecodeUpdateMsg(b *testing.B) { for i := 0; i < b.N; i++ { buf := bytes.NewBuffer(input) - _, err := decodeUpdateMsg(buf, uint16(len(input)), &types.Options{}) + _, err := decodeUpdateMsg(buf, uint16(len(input)), &DecodeOptions{}) if err != nil { fmt.Printf("decodeUpdateMsg failed: %v\n", err) } @@ -255,7 +255,7 @@ func TestDecode(t *testing.T) { for _, test := range tests { buf := bytes.NewBuffer(test.input) - msg, err := Decode(buf, &types.Options{}) + msg, err := Decode(buf, &DecodeOptions{}) if err != nil && !test.wantFail { t.Errorf("Unexpected error in test %d: %v", test.testNum, err) @@ -1369,7 +1369,7 @@ func TestDecodeUpdateMsg(t *testing.T) { if l == 0 { l = uint16(len(test.input)) } - msg, err := decodeUpdateMsg(buf, l, &types.Options{}) + msg, err := decodeUpdateMsg(buf, l, &DecodeOptions{}) if err != nil && !test.wantFail { t.Fatalf("Unexpected error in test %d: %v", test.testNum, err) @@ -1405,7 +1405,7 @@ func TestDecodeMsgBody(t *testing.T) { } for _, test := range tests { - res, err := decodeMsgBody(test.buffer, test.msgType, test.length, &types.Options{}) + res, err := decodeMsgBody(test.buffer, test.msgType, test.length, &DecodeOptions{}) if test.wantFail && err == nil { t.Errorf("Expected error dit not happen in test %q", test.name) } diff --git a/protocols/bgp/packet/mp_reach_nlri.go b/protocols/bgp/packet/mp_reach_nlri.go index 305ae994d1cdb383ac13a4c1455510d3cce0509d..55a709f53e96d50afae44d5894427f08c1ef7bf6 100644 --- a/protocols/bgp/packet/mp_reach_nlri.go +++ b/protocols/bgp/packet/mp_reach_nlri.go @@ -7,7 +7,6 @@ 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) @@ -19,7 +18,7 @@ type MultiProtocolReachNLRI struct { PathID uint32 } -func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *types.Options) uint16 { +func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions) uint16 { nextHop := n.NextHop.Bytes() tempBuf := bytes.NewBuffer(nil) @@ -29,7 +28,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer, opt *types.Options tempBuf.Write(nextHop) tempBuf.WriteByte(0) // RESERVED for _, pfx := range n.Prefixes { - if opt.AddPathRX { + if opt.UseAddPath { tempBuf.Write(convert.Uint32Byte(n.PathID)) } tempBuf.Write(serializePrefix(pfx)) diff --git a/protocols/bgp/packet/mp_reach_nlri_test.go b/protocols/bgp/packet/mp_reach_nlri_test.go index 73a52bba8c517f8924e65181cafcf376be3dddb0..cb6e5b544333d76f3244c8ef6895acb40783f149 100644 --- a/protocols/bgp/packet/mp_reach_nlri_test.go +++ b/protocols/bgp/packet/mp_reach_nlri_test.go @@ -5,7 +5,6 @@ import ( "testing" bnet "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/stretchr/testify/assert" ) @@ -60,8 +59,8 @@ func TestSerializeMultiProtocolReachNLRI(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { buf := &bytes.Buffer{} - test.nlri.serialize(buf, &types.Options{ - AddPathRX: test.addPath, + test.nlri.serialize(buf, &EncodeOptions{ + UseAddPath: test.addPath, }) assert.Equal(t, test.expected, buf.Bytes()) }) diff --git a/protocols/bgp/packet/mp_unreach_nlri.go b/protocols/bgp/packet/mp_unreach_nlri.go index 2e3475425ddb19292a6c4d5f355c8456aeac7b03..6431577ce4188837811f26bb8d819f4015c2d2a3 100644 --- a/protocols/bgp/packet/mp_unreach_nlri.go +++ b/protocols/bgp/packet/mp_unreach_nlri.go @@ -5,7 +5,6 @@ import ( "fmt" bnet "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/taktv6/tflow2/convert" ) @@ -17,12 +16,12 @@ type MultiProtocolUnreachNLRI struct { PathID uint32 } -func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer, opt *types.Options) uint16 { +func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer, opt *EncodeOptions) uint16 { tempBuf := bytes.NewBuffer(nil) tempBuf.Write(convert.Uint16Byte(n.AFI)) tempBuf.WriteByte(n.SAFI) for _, pfx := range n.Prefixes { - if opt.AddPathRX { + if opt.UseAddPath { tempBuf.Write(convert.Uint32Byte(n.PathID)) } tempBuf.Write(serializePrefix(pfx)) diff --git a/protocols/bgp/packet/mp_unreach_nlri_test.go b/protocols/bgp/packet/mp_unreach_nlri_test.go index c4484f97f71d182a8886854063368b9127154a8f..467b19e030dd208f5e1103d81465107f531591ec 100644 --- a/protocols/bgp/packet/mp_unreach_nlri_test.go +++ b/protocols/bgp/packet/mp_unreach_nlri_test.go @@ -5,7 +5,6 @@ import ( "testing" bnet "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/stretchr/testify/assert" ) @@ -54,8 +53,8 @@ func TestSerializeMultiProtocolUnreachNLRI(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { buf := &bytes.Buffer{} - test.nlri.serialize(buf, &types.Options{ - AddPathRX: test.addPath, + test.nlri.serialize(buf, &EncodeOptions{ + UseAddPath: test.addPath, }) assert.Equal(t, test.expected, buf.Bytes()) }) diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go index 5b5af4ecd816650ed5575dd16ede7f529fc349aa..819fc7b945d858fa30c4a34119c1c98a914dadab 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -11,7 +11,7 @@ import ( "github.com/taktv6/tflow2/convert" ) -func decodePathAttrs(buf *bytes.Buffer, tpal uint16, opt *types.Options) (*PathAttribute, error) { +func decodePathAttrs(buf *bytes.Buffer, tpal uint16, opt *DecodeOptions) (*PathAttribute, error) { var ret *PathAttribute var eol *PathAttribute var pa *PathAttribute @@ -38,7 +38,7 @@ func decodePathAttrs(buf *bytes.Buffer, tpal uint16, opt *types.Options) (*PathA return ret, nil } -func decodePathAttr(buf *bytes.Buffer, opt *types.Options) (pa *PathAttribute, consumed uint16, err error) { +func decodePathAttr(buf *bytes.Buffer, opt *DecodeOptions) (pa *PathAttribute, consumed uint16, err error) { pa = &PathAttribute{} err = decodePathAttrFlags(buf, pa) @@ -66,7 +66,7 @@ func decodePathAttr(buf *bytes.Buffer, opt *types.Options) (pa *PathAttribute, c } case ASPathAttr: asnLength := uint8(2) - if opt.Supports4OctetASN { + if opt.Use32BitASN { asnLength = 4 } @@ -445,7 +445,7 @@ func dumpNBytes(buf *bytes.Buffer, n uint16) error { } // Serialize serializes a path attribute -func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint16 { +func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *EncodeOptions) uint16 { pathAttrLen := uint16(0) switch pa.TypeCode { @@ -493,28 +493,28 @@ func (pa *PathAttribute) serializeOrigin(buf *bytes.Buffer) uint8 { return 4 } -func (pa *PathAttribute) serializeASPath(buf *bytes.Buffer, opt *types.Options) uint8 { +func (pa *PathAttribute) serializeASPath(buf *bytes.Buffer, opt *EncodeOptions) uint8 { attrFlags := uint8(0) attrFlags = setTransitive(attrFlags) buf.WriteByte(attrFlags) buf.WriteByte(ASPathAttr) - asnLength := uint8(2) - if opt.Supports4OctetASN { - asnLength = 4 - } - length := uint8(0) segmentsBuf := bytes.NewBuffer(nil) for _, segment := range pa.Value.(types.ASPath) { segmentsBuf.WriteByte(segment.Type) segmentsBuf.WriteByte(uint8(len(segment.ASNs))) + asnLength := uint8(2) + if opt.Use32BitASN { + asnLength = 4 + } + for _, asn := range segment.ASNs { - if asnLength == 2 { - segmentsBuf.Write(convert.Uint16Byte(uint16(asn))) - } else { + if opt.Use32BitASN { segmentsBuf.Write(convert.Uint32Byte(asn)) + } else { + segmentsBuf.Write(convert.Uint16Byte(uint16(asn))) } } length += 2 + uint8(len(segment.ASNs))*asnLength @@ -695,7 +695,7 @@ func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint16 { return uint16(len(b) + 2) } -func (pa *PathAttribute) serializeMultiProtocolReachNLRI(buf *bytes.Buffer, opt *types.Options) uint16 { +func (pa *PathAttribute) serializeMultiProtocolReachNLRI(buf *bytes.Buffer, opt *EncodeOptions) uint16 { v := pa.Value.(MultiProtocolReachNLRI) pa.Optional = true @@ -705,7 +705,7 @@ func (pa *PathAttribute) serializeMultiProtocolReachNLRI(buf *bytes.Buffer, opt return pa.serializeGeneric(tempBuf.Bytes(), buf) } -func (pa *PathAttribute) serializeMultiProtocolUnreachNLRI(buf *bytes.Buffer, opt *types.Options) uint16 { +func (pa *PathAttribute) serializeMultiProtocolUnreachNLRI(buf *bytes.Buffer, opt *EncodeOptions) uint16 { v := pa.Value.(MultiProtocolUnreachNLRI) pa.Optional = true diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go index dd4b31e8005812f7a8f90c36b139d8ac244e320e..e92efb76ab7194d8f4087b7cfd90cadd1be9aa4a 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -52,7 +52,7 @@ func TestDecodePathAttrs(t *testing.T) { } for _, test := range tests { - res, err := decodePathAttrs(bytes.NewBuffer(test.input), uint16(len(test.input)), &types.Options{}) + res, err := decodePathAttrs(bytes.NewBuffer(test.input), uint16(len(test.input)), &DecodeOptions{}) if test.wantFail && err == nil { t.Errorf("Expected error did not happen for test %q", test.name) @@ -249,7 +249,7 @@ func TestDecodePathAttr(t *testing.T) { } for _, test := range tests { - res, _, err := decodePathAttr(bytes.NewBuffer(test.input), &types.Options{}) + res, _, err := decodePathAttr(bytes.NewBuffer(test.input), &DecodeOptions{}) if test.wantFail && err == nil { t.Errorf("Expected error did not happen for test %q", test.name) @@ -1516,8 +1516,8 @@ func TestSerializeASPath(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { buf := bytes.NewBuffer(nil) - opt := &types.Options{ - Supports4OctetASN: test.use32BitASN, + opt := &EncodeOptions{ + Use32BitASN: test.use32BitASN, } n := test.input.serializeASPath(buf, opt) if n != test.expectedLen { @@ -2020,10 +2020,7 @@ func TestSerialize(t *testing.T) { } for _, test := range tests { - opt := &types.Options{ - AddPathRX: false, - } - res, err := test.msg.SerializeUpdate(opt) + res, err := test.msg.SerializeUpdate(&EncodeOptions{}) if err != nil { if test.wantFail { continue @@ -2233,8 +2230,8 @@ func TestSerializeAddPath(t *testing.T) { } for _, test := range tests { - opt := &types.Options{ - AddPathRX: true, + opt := &EncodeOptions{ + UseAddPath: true, } res, err := test.msg.SerializeUpdate(opt) if err != nil { diff --git a/protocols/bgp/packet/update.go b/protocols/bgp/packet/update.go index 55b0cc0b9099076edbaef35fcfab1cfc83443330..167439ab06b77d669c5de258a252b5c2105794a6 100644 --- a/protocols/bgp/packet/update.go +++ b/protocols/bgp/packet/update.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" - "github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/taktv6/tflow2/convert" ) @@ -17,14 +16,14 @@ type BGPUpdate struct { } // SerializeUpdate serializes an BGPUpdate to wire format -func (b *BGPUpdate) SerializeUpdate(opt *types.Options) ([]byte, error) { +func (b *BGPUpdate) SerializeUpdate(opt *EncodeOptions) ([]byte, error) { budget := MaxLen - MinLen nlriLen := 0 buf := bytes.NewBuffer(nil) withdrawBuf := bytes.NewBuffer(nil) for withdraw := b.WithdrawnRoutes; withdraw != nil; withdraw = withdraw.Next { - if opt.AddPathRX { + if opt.UseAddPath { nlriLen = int(withdraw.serializeAddPath(withdrawBuf)) } else { nlriLen = int(withdraw.serialize(withdrawBuf)) @@ -47,7 +46,7 @@ func (b *BGPUpdate) SerializeUpdate(opt *types.Options) ([]byte, error) { nlriBuf := bytes.NewBuffer(nil) for nlri := b.NLRI; nlri != nil; nlri = nlri.Next { - if opt.AddPathRX { + if opt.UseAddPath { nlriLen = int(nlri.serializeAddPath(nlriBuf)) } else { nlriLen = int(nlri.serialize(nlriBuf)) @@ -87,7 +86,7 @@ func (b *BGPUpdate) SerializeUpdate(opt *types.Options) ([]byte, error) { return buf.Bytes(), nil } -func (b *BGPUpdate) SerializeUpdateAddPath(opt *types.Options) ([]byte, error) { +func (b *BGPUpdate) SerializeUpdateAddPath(opt *EncodeOptions) ([]byte, error) { budget := MaxLen - MinLen buf := bytes.NewBuffer(nil) diff --git a/protocols/bgp/server/BUILD.bazel b/protocols/bgp/server/BUILD.bazel index 78bdeb1f3635cabb3ead2855ae4431ee20a3c04c..bd45a72d0abd1f419175febf884094109f6eb982 100644 --- a/protocols/bgp/server/BUILD.bazel +++ b/protocols/bgp/server/BUILD.bazel @@ -21,7 +21,6 @@ go_library( "update_helper.go", "update_sender.go", "util.go", - "withdraw.go", ], importpath = "github.com/bio-routing/bio-rd/protocols/bgp/server", visibility = ["//visibility:public"], @@ -49,7 +48,6 @@ go_test( "server_test.go", "update_helper_test.go", "update_sender_test.go", - "withdraw_test.go", ], embed = [":go_default_library"], deps = [ diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go index 44437ea9ade40a7038f0fa084d5117d3dddecc1d..1cb23da4d8102e081024db968e9be8a534d4bbb7 100644 --- a/protocols/bgp/server/fsm.go +++ b/protocols/bgp/server/fsm.go @@ -9,7 +9,6 @@ import ( "time" "github.com/bio-routing/bio-rd/protocols/bgp/packet" - "github.com/bio-routing/bio-rd/protocols/bgp/types" log "github.com/sirupsen/logrus" ) @@ -55,8 +54,6 @@ type FSM struct { msgRecvFailCh chan error stopMsgRecvCh chan struct{} - options *types.Options - local net.IP ribsInitialized bool @@ -64,6 +61,7 @@ type FSM struct { ipv6Unicast *fsmAddressFamily supportsMultiProtocol bool + supports4OctetASN bool neighborID uint32 state state @@ -101,7 +99,6 @@ func newFSM2(peer *peer) *FSM { msgRecvCh: make(chan []byte), msgRecvFailCh: make(chan error), stopMsgRecvCh: make(chan struct{}), - options: &types.Options{}, } if peer.ipv4 != nil { @@ -245,6 +242,12 @@ func (fsm *FSM) msgReceiver() error { } } +func (fsm *FSM) decodeOptions() *packet.DecodeOptions { + return &packet.DecodeOptions{ + Use32BitASN: fsm.supports4OctetASN, + } +} + func (fsm *FSM) startConnectRetryTimer() { fsm.connectRetryTimer = time.NewTimer(fsm.connectRetryTime) } diff --git a/protocols/bgp/server/fsm_address_family.go b/protocols/bgp/server/fsm_address_family.go index b72224a4aa0402f30e0171804801fb8dca2b0740..5426d07f3b2f0079cb382824c3ccbb8e570237fc 100644 --- a/protocols/bgp/server/fsm_address_family.go +++ b/protocols/bgp/server/fsm_address_family.go @@ -31,6 +31,7 @@ type fsmAddressFamily struct { addPathSend routingtable.ClientOptions addPathRecv bool + addPathRX bool initialized bool } @@ -65,7 +66,7 @@ func (f *fsmAddressFamily) init(n *routingtable.Neighbor) { clientOptions := routingtable.ClientOptions{ BestOnly: true, } - if f.fsm.options.AddPathRX { + if f.addPathRX { clientOptions = f.addPathSend } f.rib.RegisterWithOptions(f.adjRIBOut, clientOptions) diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go index 8a090b18afa9fc06064573886677133f56460031..43986d237a6cf3509f728e648a06a56030407384 100644 --- a/protocols/bgp/server/fsm_established.go +++ b/protocols/bgp/server/fsm_established.go @@ -30,6 +30,8 @@ func (s establishedState) run() (state, string) { } } + opt := s.fsm.decodeOptions() + for { select { case e := <-s.fsm.eventCh: @@ -48,7 +50,7 @@ func (s establishedState) run() (state, string) { case <-s.fsm.keepaliveTimer.C: return s.keepaliveTimerExpired() case recvMsg := <-s.fsm.msgRecvCh: - return s.msgReceived(recvMsg) + return s.msgReceived(recvMsg, opt) } } } @@ -74,7 +76,6 @@ func (s *establishedState) init() error { LocalASN: s.fsm.peer.localASN, RouteServerClient: s.fsm.peer.routeServerClient, LocalAddress: localAddr, - CapAddPathRX: s.fsm.options.AddPathRX, RouteReflectorClient: s.fsm.peer.routeReflectorClient, ClusterID: s.fsm.peer.clusterID, } @@ -148,8 +149,8 @@ func (s *establishedState) keepaliveTimerExpired() (state, string) { return newEstablishedState(s.fsm), s.fsm.reason } -func (s *establishedState) msgReceived(data []byte) (state, string) { - msg, err := packet.Decode(bytes.NewBuffer(data), s.fsm.options) +func (s *establishedState) msgReceived(data []byte, opt *packet.DecodeOptions) (state, string) { + msg, err := packet.Decode(bytes.NewBuffer(data), opt) if err != nil { switch bgperr := err.(type) { case packet.BGPError: diff --git a/protocols/bgp/server/fsm_open_confirm.go b/protocols/bgp/server/fsm_open_confirm.go index 07b8a6152dd64c56055c7cbd0745980e462c3886..17df63c1a3481b09f6b1671ce412d761e27cf240 100644 --- a/protocols/bgp/server/fsm_open_confirm.go +++ b/protocols/bgp/server/fsm_open_confirm.go @@ -18,6 +18,8 @@ func newOpenConfirmState(fsm *FSM) *openConfirmState { } func (s openConfirmState) run() (state, string) { + opt := s.fsm.decodeOptions() + for { select { case e := <-s.fsm.eventCh: @@ -34,7 +36,7 @@ func (s openConfirmState) run() (state, string) { case <-s.fsm.keepaliveTimer.C: return s.keepaliveTimerExpired() case recvMsg := <-s.fsm.msgRecvCh: - return s.msgReceived(recvMsg) + return s.msgReceived(recvMsg, opt) } } } @@ -81,8 +83,8 @@ func (s *openConfirmState) keepaliveTimerExpired() (state, string) { return newOpenConfirmState(s.fsm), s.fsm.reason } -func (s *openConfirmState) msgReceived(data []byte) (state, string) { - msg, err := packet.Decode(bytes.NewBuffer(data), s.fsm.options) +func (s *openConfirmState) msgReceived(data []byte, opt *packet.DecodeOptions) (state, string) { + msg, err := packet.Decode(bytes.NewBuffer(data), opt) if err != nil { switch bgperr := err.(type) { case packet.BGPError: diff --git a/protocols/bgp/server/fsm_open_sent.go b/protocols/bgp/server/fsm_open_sent.go index 7a0999899a5d0b7089892f1fb169d3a0abdc591f..dd13dbfaa4a0f66624fc292dee97e6e5dd56abff 100644 --- a/protocols/bgp/server/fsm_open_sent.go +++ b/protocols/bgp/server/fsm_open_sent.go @@ -22,6 +22,9 @@ func newOpenSentState(fsm *FSM) *openSentState { func (s openSentState) run() (state, string) { go s.fsm.msgReceiver() + + opt := s.fsm.decodeOptions() + for { select { case e := <-s.fsm.eventCh: @@ -38,7 +41,7 @@ func (s openSentState) run() (state, string) { case <-s.fsm.holdTimer.C: return s.holdTimerExpired() case recvMsg := <-s.fsm.msgRecvCh: - return s.msgReceived(recvMsg) + return s.msgReceived(recvMsg, opt) } } } @@ -73,8 +76,8 @@ func (s *openSentState) holdTimerExpired() (state, string) { return newIdleState(s.fsm), "Holdtimer expired" } -func (s *openSentState) msgReceived(data []byte) (state, string) { - msg, err := packet.Decode(bytes.NewBuffer(data), s.fsm.options) +func (s *openSentState) msgReceived(data []byte, opt *packet.DecodeOptions) (state, string) { + msg, err := packet.Decode(bytes.NewBuffer(data), opt) if err != nil { switch bgperr := err.(type) { case packet.BGPError: @@ -191,24 +194,24 @@ func (s *openSentState) processAddPathCapability(addPathCap packet.AddPathCapabi switch addPathCap.SendReceive { case packet.AddPathReceive: if !f.addPathSend.BestOnly { - s.fsm.options.AddPathRX = true + f.addPathRX = true } case packet.AddPathSend: if f.addPathRecv { - s.fsm.options.AddPathRX = true + f.addPathRX = true } case packet.AddPathSendReceive: if !f.addPathSend.BestOnly { - s.fsm.options.AddPathRX = true + f.addPathRX = true } if f.addPathRecv { - s.fsm.options.AddPathRX = true + f.addPathRX = true } } } func (s *openSentState) processASN4Capability(cap packet.ASN4Capability) { - s.fsm.options.Supports4OctetASN = true + s.fsm.supports4OctetASN = true if s.peerASNRcvd == packet.ASTransASN { s.peerASNRcvd = cap.ASN4 diff --git a/protocols/bgp/server/update_helper.go b/protocols/bgp/server/update_helper.go index 2cb82934a0a12d2f25243db2bc82cd60fca10e02..a510e54e98c10e8db673b1156c26e3de1cf19f24 100644 --- a/protocols/bgp/server/update_helper.go +++ b/protocols/bgp/server/update_helper.go @@ -4,11 +4,12 @@ import ( "fmt" "io" - "github.com/bio-routing/bio-rd/protocols/bgp/types" + "github.com/bio-routing/bio-rd/protocols/bgp/packet" + log "github.com/sirupsen/logrus" ) -func serializeAndSendUpdate(out io.Writer, update serializeAbleUpdate, opt *types.Options) error { +func serializeAndSendUpdate(out io.Writer, update serializeAbleUpdate, opt *packet.EncodeOptions) error { updateBytes, err := update.SerializeUpdate(opt) if err != nil { log.Errorf("Unable to serialize BGP Update: %v", err) @@ -23,5 +24,5 @@ func serializeAndSendUpdate(out io.Writer, update serializeAbleUpdate, opt *type } type serializeAbleUpdate interface { - SerializeUpdate(opt *types.Options) ([]byte, error) + SerializeUpdate(opt *packet.EncodeOptions) ([]byte, error) } diff --git a/protocols/bgp/server/update_helper_test.go b/protocols/bgp/server/update_helper_test.go index 6c599f18c965d55a9a611509ea10e2c5d5ffa35e..86a70f64d5626c4cbb38fb4eca5b793d7a548093 100644 --- a/protocols/bgp/server/update_helper_test.go +++ b/protocols/bgp/server/update_helper_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/bio-routing/bio-rd/protocols/bgp/packet" - "github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/bio-routing/bio-rd/net" "github.com/stretchr/testify/assert" @@ -15,7 +14,7 @@ import ( type failingUpdate struct{} -func (f *failingUpdate) SerializeUpdate(opt *types.Options) ([]byte, error) { +func (f *failingUpdate) SerializeUpdate(opt *packet.EncodeOptions) ([]byte, error) { return nil, errors.New("general error") } @@ -93,7 +92,7 @@ func TestSerializeAndSendUpdate(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - opt := &types.Options{} + opt := &packet.EncodeOptions{} err := serializeAndSendUpdate(test.buf, test.testUpdate, opt) assert.Equal(t, test.err, err) diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go index ed63c74dcbc23da9d01b7b131e2325f5278a50f8..d7e23556e603f07e98da986c28267a3d69401adc 100644 --- a/protocols/bgp/server/update_sender.go +++ b/protocols/bgp/server/update_sender.go @@ -20,6 +20,7 @@ type UpdateSender struct { fsm *FSM afi uint16 safi uint8 + options *packet.EncodeOptions iBGP bool rrClient bool toSendMu sync.Mutex @@ -33,6 +34,8 @@ type pathPfxs struct { } func newUpdateSender(fsm *FSM, afi uint16, safi uint8) *UpdateSender { + f := fsm.addressFamily(afi, safi) + return &UpdateSender{ fsm: fsm, afi: afi, @@ -41,6 +44,10 @@ func newUpdateSender(fsm *FSM, afi uint16, safi uint8) *UpdateSender { rrClient: fsm.peer.routeReflectorClient, destroyCh: make(chan struct{}), toSend: make(map[string]*pathPfxs), + options: &packet.EncodeOptions{ + Use32BitASN: fsm.supports4OctetASN, + UseAddPath: f.addPathRX, + }, } } @@ -108,7 +115,7 @@ func (u *UpdateSender) sender(aggrTime time.Duration) { for _, pfx := range pathNLRIs.pfxs { budget -= int(packet.BytesInAddr(pfx.Pfxlen())) + 1 - if u.fsm.options.AddPathRX { + if u.options.UseAddPath { budget -= 4 } @@ -157,7 +164,7 @@ func (u *UpdateSender) sendUpdates(pathAttrs *packet.PathAttribute, updatePrefix return } - err = serializeAndSendUpdate(u.fsm.con, update, u.fsm.options) + err = serializeAndSendUpdate(u.fsm.con, update, u.options) if err != nil { log.Errorf("Failed to serialize and send: %v", err) } @@ -282,7 +289,7 @@ func (u *UpdateSender) withDrawPrefixes(out io.Writer, prefixes ...bnet.Prefix) WithdrawnRoutes: rootNLRI, } - return serializeAndSendUpdate(out, update, u.fsm.options) + return serializeAndSendUpdate(out, update, u.options) } @@ -305,7 +312,7 @@ func (u *UpdateSender) withDrawPrefixesAddPath(out io.Writer, pfx bnet.Prefix, p }, } - return serializeAndSendUpdate(out, update, u.fsm.options) + return serializeAndSendUpdate(out, update, u.options) } func (u *UpdateSender) withDrawPrefixesMultiProtocol(out io.Writer, pfx bnet.Prefix, p *route.Path) error { @@ -326,7 +333,7 @@ func (u *UpdateSender) withDrawPrefixesMultiProtocol(out io.Writer, pfx bnet.Pre }, } - return serializeAndSendUpdate(out, update, u.fsm.options) + return serializeAndSendUpdate(out, update, u.options) } // UpdateNewClient does nothing diff --git a/protocols/bgp/server/update_sender_test.go b/protocols/bgp/server/update_sender_test.go index d46297d6effae19b01dab67eb0bbce231916a9ae..95cb85703891f8ad3b72de17829be0d201fdf0b7 100644 --- a/protocols/bgp/server/update_sender_test.go +++ b/protocols/bgp/server/update_sender_test.go @@ -12,7 +12,6 @@ import ( "github.com/stretchr/testify/assert" bnet "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/routingtable/filter" "github.com/bio-routing/bio-rd/routingtable/locRIB" @@ -881,12 +880,14 @@ func TestSender(t *testing.T) { importFilter: filter.NewAcceptAllFilter(), exportFilter: filter.NewAcceptAllFilter(), }, fsmA) + fsmA.ipv6Unicast.addPathRX = test.addPath } else { fsmA.ipv4Unicast = newFSMAddressFamily(packet.IPv4AFI, packet.UnicastSAFI, &familyParameters{ rib: rib, importFilter: filter.NewAcceptAllFilter(), exportFilter: filter.NewAcceptAllFilter(), }, fsmA) + fsmA.ipv4Unicast.addPathRX = test.addPath } fsmA.holdTimer = time.NewTimer(time.Second * 90) @@ -895,12 +896,6 @@ func TestSender(t *testing.T) { fsmA.state = newEstablishedState(fsmA) fsmA.con = btest.NewMockConn() - if test.addPath { - fsmA.options = &types.Options{ - AddPathRX: true, - } - } - updateSender := newUpdateSender(fsmA, test.afi, packet.UnicastSAFI) for _, pathPfx := range test.paths { @@ -990,11 +985,10 @@ func TestWithDrawPrefixes(t *testing.T) { buf := bytes.NewBuffer([]byte{}) u := &UpdateSender{ - fsm: &FSM{ - options: &types.Options{}, - }, - afi: packet.IPv6AFI, - safi: packet.UnicastSAFI, + fsm: &FSM{}, + afi: packet.IPv6AFI, + safi: packet.UnicastSAFI, + options: &packet.EncodeOptions{}, } err := u.withDrawPrefixes(buf, tc.Prefix...) @@ -1033,13 +1027,11 @@ func TestWithDrawPrefixesMultiProtocol(t *testing.T) { u := &UpdateSender{ fsm: &FSM{ - options: &types.Options{ - AddPathRX: false, - }, supportsMultiProtocol: true, }, - afi: packet.IPv6AFI, - safi: packet.UnicastSAFI, + afi: packet.IPv6AFI, + safi: packet.UnicastSAFI, + options: &packet.EncodeOptions{}, } err := u.withDrawPrefixesMultiProtocol(buf, test.Prefix, &route.Path{}) @@ -1104,10 +1096,9 @@ func TestWithDrawPrefixesAddPath(t *testing.T) { buf := bytes.NewBuffer([]byte{}) u := &UpdateSender{ - fsm: &FSM{ - options: &types.Options{ - AddPathRX: true, - }, + fsm: &FSM{}, + options: &packet.EncodeOptions{ + UseAddPath: true, }, } diff --git a/protocols/bgp/types/BUILD.bazel b/protocols/bgp/types/BUILD.bazel index 5f94662087b2e46f593e4386d2bac21e65896225..50a86ef428ad5e92ffbb6365f30e566c0267873b 100644 --- a/protocols/bgp/types/BUILD.bazel +++ b/protocols/bgp/types/BUILD.bazel @@ -7,7 +7,6 @@ go_library( "as_path.go", "community.go", "large_community.go", - "options.go", "unknown_attribute.go", ], importpath = "github.com/bio-routing/bio-rd/protocols/bgp/types", diff --git a/protocols/bgp/types/options.go b/protocols/bgp/types/options.go deleted file mode 100644 index 19b580d2829b96d8f974311536b299211a98ca95..0000000000000000000000000000000000000000 --- a/protocols/bgp/types/options.go +++ /dev/null @@ -1,7 +0,0 @@ -package types - -// Options represents options to the update sender, decoder and encoder -type Options struct { - Supports4OctetASN bool - AddPathRX bool -}