1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-26 21:57:41 +03:00

s3:smb2_server: move sconn->smb2.*credits* to xconn->smb2.credits.*

This prepares the structures for multi-channel support.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
This commit is contained in:
Stefan Metzmacher 2014-05-23 12:10:23 +02:00 committed by Michael Adam
parent 4f3f889dcd
commit 36e3484260
3 changed files with 103 additions and 93 deletions

View File

@ -434,6 +434,52 @@ struct smbXsrv_connection {
struct smbd_smb2_send_queue *send_queue;
size_t send_queue_len;
struct {
/*
* seq_low is the lowest sequence number
* we will accept.
*/
uint64_t seq_low;
/*
* seq_range is the range of credits we have
* granted from the sequence windows starting
* at seq_low.
*
* This gets incremented when new credits are
* granted and gets decremented when the
* lowest sequence number is consumed
* (when seq_low gets incremented).
*/
uint16_t seq_range;
/*
* The number of credits we have currently granted
* to the client.
*
* This gets incremented when new credits are
* granted and gets decremented when any credit
* is comsumed.
*
* Note: the decrementing is different compared
* to seq_range.
*/
uint16_t granted;
/*
* The maximum number of credits we will ever
* grant to the client.
*
* Typically we will only grant 1/16th of
* max_credits.
*
* This is the "server max credits" parameter.
*/
uint16_t max;
/*
* a bitmap of size max_credits
*/
struct bitmap *bitmap;
bool multicredit;
} credits;
bool allow_2ff;
struct {
uint32_t capabilities;
@ -796,49 +842,6 @@ struct smbd_server_connection {
bool blocking_lock_unlock_state;
} locks;
struct smbd_smb2_request *requests;
/*
* seqnum_low is the lowest sequence number
* we will accept.
*/
uint64_t seqnum_low;
/*
* seqnum_range is the range of credits we have
* granted from the sequence windows starting
* at seqnum_low.
*
* This gets incremented when new credits are
* granted and gets decremented when the
* lowest sequence number is consumed
* (when seqnum_low gets incremented).
*/
uint16_t seqnum_range;
/*
* credits_grantedThe number of credits we have currently granted
* to the client.
*
* This gets incremented when new credits are
* granted and gets decremented when any credit
* is comsumed.
*
* Note: the decrementing is different compared
* to seqnum_range.
*/
uint16_t credits_granted;
/*
* The maximum number of credits we will ever
* grant to the client.
*
* Typically we will only grant 1/16th of
* max_credits.
*
* This is the "server max credits" parameter.
*/
uint16_t max_credits;
/*
* a bitmap of size max_credits
*/
struct bitmap *credits_bitmap;
bool supports_multicredit;
} smb2;
/*

View File

@ -300,7 +300,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
/* largeMTU is not supported over NBT (tcp port 139) */
if (p != NBT_SMB_PORT) {
capabilities |= SMB2_CAP_LARGE_MTU;
req->sconn->smb2.supports_multicredit = true;
xconn->smb2.credits.multicredit = true;
/* Windows 2012R2 allows up to 8 MB */
max_limit = 0x800000; /* 8MB */

View File

@ -204,13 +204,13 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
TALLOC_FREE(xconn->transport.fde);
sconn->smb2.seqnum_low = 0;
sconn->smb2.seqnum_range = 1;
sconn->smb2.credits_granted = 1;
sconn->smb2.max_credits = lp_smb2_max_credits();
sconn->smb2.credits_bitmap = bitmap_talloc(sconn,
sconn->smb2.max_credits);
if (sconn->smb2.credits_bitmap == NULL) {
xconn->smb2.credits.seq_low = 0;
xconn->smb2.credits.seq_range = 1;
xconn->smb2.credits.granted = 1;
xconn->smb2.credits.max = lp_smb2_max_credits();
xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
xconn->smb2.credits.max);
if (xconn->smb2.credits.bitmap == NULL) {
return NT_STATUS_NO_MEMORY;
}
@ -578,34 +578,38 @@ static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
uint64_t message_id, uint64_t seq_id)
{
struct bitmap *credits_bm = sconn->smb2.credits_bitmap;
struct smbXsrv_connection *xconn = sconn->conn;
struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
unsigned int offset;
uint64_t seq_tmp;
if (seq_id < sconn->smb2.seqnum_low) {
seq_tmp = xconn->smb2.credits.seq_low;
if (seq_id < seq_tmp) {
DEBUG(0,("smb2_validate_sequence_number: bad message_id "
"%llu (sequence id %llu) "
"(granted = %u, low = %llu, range = %u)\n",
(unsigned long long)message_id,
(unsigned long long)seq_id,
(unsigned int)sconn->smb2.credits_granted,
(unsigned long long)sconn->smb2.seqnum_low,
(unsigned int)sconn->smb2.seqnum_range));
(unsigned int)xconn->smb2.credits.granted,
(unsigned long long)xconn->smb2.credits.seq_low,
(unsigned int)xconn->smb2.credits.seq_range));
return false;
}
if (seq_id >= sconn->smb2.seqnum_low + sconn->smb2.seqnum_range) {
seq_tmp += xconn->smb2.credits.seq_range;
if (seq_id >= seq_tmp) {
DEBUG(0,("smb2_validate_sequence_number: bad message_id "
"%llu (sequence id %llu) "
"(granted = %u, low = %llu, range = %u)\n",
(unsigned long long)message_id,
(unsigned long long)seq_id,
(unsigned int)sconn->smb2.credits_granted,
(unsigned long long)sconn->smb2.seqnum_low,
(unsigned int)sconn->smb2.seqnum_range));
(unsigned int)xconn->smb2.credits.granted,
(unsigned long long)xconn->smb2.credits.seq_low,
(unsigned int)xconn->smb2.credits.seq_range));
return false;
}
offset = seq_id % sconn->smb2.max_credits;
offset = seq_id % xconn->smb2.credits.max;
if (bitmap_query(credits_bm, offset)) {
DEBUG(0,("smb2_validate_sequence_number: duplicate message_id "
@ -614,9 +618,9 @@ static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
"(bm offset %u)\n",
(unsigned long long)message_id,
(unsigned long long)seq_id,
(unsigned int)sconn->smb2.credits_granted,
(unsigned long long)sconn->smb2.seqnum_low,
(unsigned int)sconn->smb2.seqnum_range,
(unsigned int)xconn->smb2.credits.granted,
(unsigned long long)xconn->smb2.credits.seq_low,
(unsigned int)xconn->smb2.credits.seq_range,
offset));
return false;
}
@ -624,7 +628,7 @@ static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
/* Mark the message_ids as seen in the bitmap. */
bitmap_set(credits_bm, offset);
if (seq_id != sconn->smb2.seqnum_low) {
if (seq_id != xconn->smb2.credits.seq_low) {
return true;
}
@ -635,13 +639,13 @@ static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
while (bitmap_query(credits_bm, offset)) {
DEBUG(10,("smb2_validate_sequence_number: clearing "
"id %llu (position %u) from bitmap\n",
(unsigned long long)(sconn->smb2.seqnum_low),
(unsigned long long)(xconn->smb2.credits.seq_low),
offset));
bitmap_clear(credits_bm, offset);
sconn->smb2.seqnum_low += 1;
sconn->smb2.seqnum_range -= 1;
offset = sconn->smb2.seqnum_low % sconn->smb2.max_credits;
xconn->smb2.credits.seq_low += 1;
xconn->smb2.credits.seq_range -= 1;
offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
}
return true;
@ -650,6 +654,7 @@ static bool smb2_validate_sequence_number(struct smbd_server_connection *sconn,
static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
const uint8_t *inhdr)
{
struct smbXsrv_connection *xconn = sconn->conn;
uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
uint16_t credit_charge = 1;
@ -660,7 +665,7 @@ static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
return true;
}
if (sconn->smb2.supports_multicredit) {
if (xconn->smb2.credits.multicredit) {
credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
credit_charge = MAX(credit_charge, 1);
}
@ -670,20 +675,20 @@ static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
"seqnum low/range: %llu/%llu\n",
(unsigned long long) message_id,
(unsigned long long) credit_charge,
(unsigned long long) sconn->smb2.credits_granted,
(unsigned long long) sconn->smb2.seqnum_low,
(unsigned long long) sconn->smb2.seqnum_range));
(unsigned long long) xconn->smb2.credits.granted,
(unsigned long long) xconn->smb2.credits.seq_low,
(unsigned long long) xconn->smb2.credits.seq_range));
if (sconn->smb2.credits_granted < credit_charge) {
if (xconn->smb2.credits.granted < credit_charge) {
DEBUG(0, ("smb2_validate_message_id: client used more "
"credits than granted, mid %llu, charge %llu, "
"credits_granted %llu, "
"seqnum low/range: %llu/%llu\n",
(unsigned long long) message_id,
(unsigned long long) credit_charge,
(unsigned long long) sconn->smb2.credits_granted,
(unsigned long long) sconn->smb2.seqnum_low,
(unsigned long long) sconn->smb2.seqnum_range));
(unsigned long long) xconn->smb2.credits.granted,
(unsigned long long) xconn->smb2.credits.seq_low,
(unsigned long long) xconn->smb2.credits.seq_range));
return false;
}
@ -711,7 +716,7 @@ static bool smb2_validate_message_id(struct smbd_server_connection *sconn,
}
/* substract used credits */
sconn->smb2.credits_granted -= credit_charge;
xconn->smb2.credits.granted -= credit_charge;
return true;
}
@ -760,6 +765,7 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
const struct iovec *in_vector,
struct iovec *out_vector)
{
struct smbXsrv_connection *xconn = sconn->conn;
const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
uint16_t credit_charge = 1;
@ -785,10 +791,10 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
* Which means we would grant more credits
* for client which use multi credit requests.
*/
current_max_credits = sconn->smb2.max_credits / 16;
current_max_credits = xconn->smb2.credits.max / 16;
current_max_credits = MAX(current_max_credits, 1);
if (sconn->smb2.supports_multicredit) {
if (xconn->smb2.credits.multicredit) {
credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
credit_charge = MAX(credit_charge, 1);
}
@ -798,9 +804,9 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
SMB_ASSERT(sconn->smb2.max_credits >= sconn->smb2.credits_granted);
SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
if (sconn->smb2.max_credits < credit_charge) {
if (xconn->smb2.credits.max < credit_charge) {
smbd_server_connection_terminate(sconn,
"client error: credit charge > max credits\n");
return;
@ -842,7 +848,7 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
additional_credits = MIN(additional_credits, additional_max);
credits_granted = credit_charge + additional_credits;
} else if (sconn->smb2.credits_granted == 0) {
} else if (xconn->smb2.credits.granted == 0) {
/*
* Make sure the client has always at least one credit
*/
@ -864,19 +870,19 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
* this makes sure the client consumes the lowest sequence
* number, before we can grant additional credits.
*/
credits_possible = UINT64_MAX - sconn->smb2.seqnum_low;
credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
if (credits_possible > 0) {
/* remove UINT64_MAX */
credits_possible -= 1;
}
credits_possible = MIN(credits_possible, current_max_credits);
credits_possible -= sconn->smb2.seqnum_range;
credits_possible -= xconn->smb2.credits.seq_range;
credits_granted = MIN(credits_granted, credits_possible);
SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
sconn->smb2.credits_granted += credits_granted;
sconn->smb2.seqnum_range += credits_granted;
xconn->smb2.credits.granted += credits_granted;
xconn->smb2.credits.seq_range += credits_granted;
DEBUG(10,("smb2_set_operation_credit: requested %u, charge %u, "
"granted %u, current possible/max %u/%u, "
@ -886,10 +892,10 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
(unsigned int)credits_granted,
(unsigned int)credits_possible,
(unsigned int)current_max_credits,
(unsigned int)sconn->smb2.credits_granted,
(unsigned int)sconn->smb2.max_credits,
(unsigned long long)sconn->smb2.seqnum_low,
(unsigned int)sconn->smb2.seqnum_range));
(unsigned int)xconn->smb2.credits.granted,
(unsigned int)xconn->smb2.credits.max,
(unsigned long long)xconn->smb2.credits.seq_low,
(unsigned int)xconn->smb2.credits.seq_range));
}
static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
@ -1805,13 +1811,14 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
uint32_t data_length)
{
struct smbXsrv_connection *xconn = req->sconn->conn;
uint16_t needed_charge;
uint16_t credit_charge = 1;
const uint8_t *inhdr;
inhdr = SMBD_SMB2_IN_HDR_PTR(req);
if (req->sconn->smb2.supports_multicredit) {
if (xconn->smb2.credits.multicredit) {
credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
credit_charge = MAX(credit_charge, 1);
}
@ -2970,7 +2977,7 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *s
return NT_STATUS_OK;
}
max_send_queue_len = MAX(1, sconn->smb2.max_credits/16);
max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
cur_send_queue_len = xconn->smb2.send_queue_len;
if (cur_send_queue_len > max_send_queue_len) {