diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go index 0ffc69fca4cf7feba47830c5e229a4c07ea7048f..35b09747657385236307c03b67a71bcf74f69a0f 100644 --- a/protocols/bgp/server/update_sender.go +++ b/protocols/bgp/server/update_sender.go @@ -216,12 +216,7 @@ func (u *UpdateSender) copyAttributesWithoutNextHop(pa *packet.PathAttribute) (a // RemovePath withdraws prefix `pfx` from a peer func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool { - if u.fsm.options.SupportsMultiProtocol { - // TODO: imeplent withdraw - return false - } - - err := withDrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p) + err := u.withdrawPrefix(pfx, p) if err != nil { log.Errorf("Unable to withdraw prefix: %v", err) return false @@ -229,6 +224,14 @@ func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool { return true } +func (u *UpdateSender) withdrawPrefix(pfx bnet.Prefix, p *route.Path) error { + if u.fsm.options.SupportsMultiProtocol { + return withDrawPrefixesMultiProtocol(u.fsm.con, u.fsm.options, pfx) + } + + return withDrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p) +} + // UpdateNewClient does nothing func (u *UpdateSender) UpdateNewClient(client routingtable.RouteTableClient) error { log.Warningf("BGP Update Sender: UpdateNewClient not implemented") diff --git a/protocols/bgp/server/withdraw.go b/protocols/bgp/server/withdraw.go index 98243560f929952ab7c26e47e3c797af17016772..013f6ce33c5b247d6021292c3b611f3c325f24f5 100644 --- a/protocols/bgp/server/withdraw.go +++ b/protocols/bgp/server/withdraw.go @@ -58,3 +58,17 @@ func withDrawPrefixesAddPath(out io.Writer, opt *types.Options, pfx net.Prefix, } return serializeAndSendUpdate(out, update, opt) } + +func withDrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Prefix) error { + update := &packet.BGPUpdate{ + PathAttributes: &packet.PathAttribute{ + TypeCode: packet.MultiProtocolUnreachNLRICode, + Value: packet.MultiProtocolUnreachNLRI{ + AFI: packet.IPv6AFI, + SAFI: packet.UnicastSAFI, + Prefixes: []net.Prefix{pfx}, + }, + }, + } + return serializeAndSendUpdate(out, update, opt) +} diff --git a/protocols/bgp/server/withdraw_test.go b/protocols/bgp/server/withdraw_test.go index cfe0a0283c0af493317284b495b150ae27f1edc8..393be032dcd178b2cef772f576b24e1c5b2d29e4 100644 --- a/protocols/bgp/server/withdraw_test.go +++ b/protocols/bgp/server/withdraw_test.go @@ -61,6 +61,46 @@ func TestWithDrawPrefixes(t *testing.T) { } } +func TestWithDrawPrefixesMultiProtocol(t *testing.T) { + tests := []struct { + Name string + Prefix net.Prefix + Expected []byte + }{ + { + Name: "IPv6 MP_UNREACH_NLRI", + Prefix: net.NewPfx(net.IPv6FromBlocks(0x2804, 0x148c, 0, 0, 0, 0, 0, 0), 32), + Expected: []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // BGP Marker + 0x00, 0x22, // BGP Message Length + 0x02, // BGP Message Type == Update + 0x00, 0x00, // WithDraw Octet length + 0x00, 0x0b, // Length + 0x80, // Flags + 0x0f, // Attribute Code + 0x08, // Attribute length + 0x00, 0x02, // AFI + 0x01, // SAFI + 0x20, 0x28, 0x04, 0x14, 0x8c, // Prefix + }, + }, + } + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + buf := bytes.NewBuffer([]byte{}) + opt := &types.Options{ + AddPathRX: false, + } + err := withDrawPrefixesMultiProtocol(buf, opt, test.Prefix) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + assert.Equal(t, test.Expected, buf.Bytes()) + }) + } +} + func TestWithDrawPrefixesAddPath(t *testing.T) { testcases := []struct { Name string